Click here to Skip to main content
15,897,371 members
Articles / Web Development / HTML

A Framework in C# for Fingerprint Verification

2 Jan 2019CPOL11 min read 1.6M   143.6K   672  
In this article, we introduce a framework in C# for fingerprint verification, we briefly explain how to perform fingerprint verification experiments and how to integrate your algorithms to the framework.
/*
 * Created by: Miguel Angel Medina P�rez (miguel.medina.perez@gmail.com)
 * Created: Thursday, December 21, 2007
 * Comments by: Miguel Angel Medina P�rez (miguel.medina.perez@gmail.com)
 */

using System;

namespace PatternRecognition.FingerprintRecognition.Core
{
    /// <summary>
    ///     Represents the type of the minutia.
    /// </summary>
    public enum MinutiaType
    {
        /// <summary>
        ///     Represents a minutia which type could not be identified.
        /// </summary>
        Unknown,

        /// <summary>
        ///     Represents a ridge ending.
        /// </summary>
        End,

        /// <summary>
        ///     Represents a ridge bifurcation.
        /// </summary>
        Bifurcation,
    } ;

    /// <summary>
    ///     Represents a minutia.
    /// </summary>
    /// <remarks>
    ///     <para>
    ///         This minutia representation assumes that the angle is represented in radians.
    ///     </para>
    ///     <para>
    ///         The hash code of these objects uses four bytes per minutia: <see cref="Minutia.X"/> in the left most 11 bits; <see cref="Minutia.Y"/> in the next 11 bits; <see cref="Minutia.Angle"/> in the next eight bits; and <see cref="Minutia.MinutiaType"/> in the last two bits. Therefore, this method is ineffective for values of <see cref="Minutia.X"/> or <see cref="Minutia.Y"/> greater than 2047.
    ///     </para>
    /// </remarks>
    [Serializable]
    public class Minutia
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Minutia"/> class using the specified location and angle.
        /// </summary>
        /// <remarks>
        ///     The default value of <see cref="MinutiaType"/> is <see cref="Core.MinutiaType.Unknown"/>.
        /// </remarks>
        /// <param name="x">
        ///     The horizontal position of the minutia.
        /// </param>
        /// <param name="y">
        ///     The vertical position of the minutia.
        /// </param>
        /// <param name="angle">
        ///     The angle of the minutia.
        /// </param>
        public Minutia(Int16 x, Int16 y, double angle)
        {
            X = x;
            Y = y;
            Angle = angle;
            MinutiaType = MinutiaType.Unknown;
            Flag = false;
        }

        public Minutia()
        {
            X = 0;
            Y = 0;
            Angle = 0;
            MinutiaType = MinutiaType.Unknown;
            Flag = false;
        }

        /// <summary>
        ///     Returns a hash code for the current minutia.
        /// </summary>
        /// <remarks>
        ///     When building hash code, this method stores value X in the left most 11 bits; value Y, in the next 11 bits; value Angle, in the next 8 bits; and value MinutiaType, in the last 2 bits. Therefore, this method could be ineffective for values of X or Y greater than 2047.
        /// </remarks>
        /// <returns>
        ///     A hash code for the current minutia.
        /// </returns>
        public override int GetHashCode()
        {
            // Storing value X in the left most 11 bits.
            int blockX = (2047 & X) << 21;
            // Storing value Y in the next 11 bits.
            int blockY = (2047 & Y) << 10;
            // Storing value Angle in the next 8 bits.
            int blockAngle = Convert.ToByte(Math.Round(Angle * 255 / (2 * Math.PI))) << 2;
            // Storing value MinutiaType in the last 2 bits.
            int blockType = MinutiaType == MinutiaType.Unknown ? 0 : (MinutiaType == MinutiaType.End ? 1 : 2);

            return blockX | blockY | blockAngle | blockType;
        }

        /// <summary>
        ///     Determines whether two specified minutiae have the same property values.
        /// </summary>
        /// <param name="m1">A minutia.</param>
        /// <param name="m2">A minutia.</param>
        /// <returns>
        ///     True if every property value of <paramref name="m1"/> is equal to the respective property value of <paramref name="m2"/>; otherwise, false.
        /// </returns>
        public static bool operator ==(Minutia m1, Minutia m2)
        {
            return m1.X == m2.X && m1.Y == m2.Y && m1.Angle == m2.Angle;
        }

        /// <summary>
        ///     Determines whether two specified minutiae have different property values.
        /// </summary>
        /// <param name="m1">A minutia.</param>
        /// <param name="m2">A minutia.</param>
        /// <returns>
        ///     True if every property value of <paramref name="m1"/> is different from the respective property value of <paramref name="m2"/>; otherwise, false.
        /// </returns>
        public static bool operator !=(Minutia m1, Minutia m2)
        {
            return !Equals(m1, m2);
        }

        /// <summary>
        ///     Gets or sets the horizontal position of the minutia.
        /// </summary>
        public Int16 X { set; get; }

        /// <summary>
        ///     Gets or sets the vertical position of the minutia.
        /// </summary>
        public Int16 Y { set; get; }

        /// <summary>
        ///     Gets or sets the angle of the minutia in radians.
        /// </summary>
        public double Angle { set; get; }

        /// <summary>
        ///     Gets or sets the minutia type.
        /// </summary>
        public MinutiaType MinutiaType { set; get; }

        /// <summary>
        ///     Allows flagging the minutia;
        /// </summary>
        public bool Flag { set; get; }
    }

    /// <summary>
    ///     Utility class used to store two minutiae and its matching value.
    /// </summary>
    public class MinutiaPair
    {
        /// <summary>
        ///     Gets or sets a minutia from the query fingerprint.
        /// </summary>
        public Minutia QueryMtia { set; get; }

        /// <summary>
        ///     Gets or sets a minutia from the template fingerprint.
        /// </summary>
        public Minutia TemplateMtia { set; get; }

        /// <summary>
        ///     Gets or sets the matching value of the two minutiae.
        /// </summary>
        public double MatchingValue { set; get; }

        /// <summary>
        ///     Returns a hash code for the current <see cref="MinutiaPair"/>.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            unchecked
            {
                return (QueryMtia.GetHashCode() * 397) ^ TemplateMtia.GetHashCode();
            }
        }

        public override string ToString()
        {
            return GetHashCode().ToString();
        }

        /// <summary>
        ///     Determines whether two specified pairs have the same minutiae.
        /// </summary>
        /// <param name="mp1">A minutia pair.</param>
        /// <param name="mp2">A minutia pair.</param>
        /// <returns>
        ///     True if the <see cref="QueryMtia"/> objects of the specified pairs have equal values and the <see cref="TemplateMtia"/> objects have equal values.
        /// </returns>
        public static bool operator ==(MinutiaPair mp1, MinutiaPair mp2)
        {            
            if (!ReferenceEquals(null, mp1))
                return mp1.Equals(mp2);
            if (ReferenceEquals(null, mp1) && ReferenceEquals(null, mp2))
                return true;
            return false;
        }

        /// <summary>
        ///     Determines whether two specified pairs have different minutiae.
        /// </summary>
        /// <param name="mp1">A minutia pair.</param>
        /// <param name="mp2">A minutia pair.</param>
        /// <returns>
        ///     True if the <see cref="QueryMtia"/> objects of the specified pairs have different values or the <see cref="TemplateMtia"/> objects have different values.
        /// </returns>
        public static bool operator !=(MinutiaPair mp1, MinutiaPair mp2)
        {
            if (!ReferenceEquals(null, mp1))
                return !mp1.Equals(mp2);
            if (ReferenceEquals(null, mp1) && ReferenceEquals(null, mp2))
                return false;
            return true;
        }

        /// <summary>
        ///     Determines wheter the specified <see cref="MinutiaPair"/> and the current object have the same minutiae. 
        /// </summary>
        /// <param name="obj">
        ///     The <see cref="MinutiaPair"/> to compare with the current object.
        /// </param>
        /// <returns>
        ///     True if the <see cref="QueryMtia"/> and <see cref="TemplateMtia"/> objects of the specified pair have the same values as the <see cref="QueryMtia"/> and <see cref="TemplateMtia"/> objects of the current object respectively.
        /// </returns>
        public bool Equals(MinutiaPair obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            return obj.QueryMtia.Equals(QueryMtia) && obj.TemplateMtia.Equals(TemplateMtia);
        }

        /// <summary>
        ///     Determines wheter the specified object and the current <see cref="MinutiaPair"/> have the same minutiae. 
        /// </summary>
        /// <param name="obj">
        ///     The object to compare with the current <see cref="MinutiaPair"/>.
        /// </param>
        /// <returns>
        ///     True if the <see cref="QueryMtia"/> and <see cref="TemplateMtia"/> objects of the specified pair have the same values as the <see cref="QueryMtia"/> and <see cref="TemplateMtia"/> objects of the current object respectively.
        /// </returns>
        public override bool Equals(object obj)
        {
            MinutiaPair mp = obj as MinutiaPair;
            return Equals(mp);
        }
    }

    public class MtiaMapper
    {
        public MtiaMapper(Minutia query, Minutia template)
        {
            dAngle = template.Angle - query.Angle;
            this.template = template;
            this.query = query;
        }

        public Minutia Map(Minutia m)
        {
            double newAngle = m.Angle + dAngle;
            double sin = Math.Sin(dAngle);
            double cos = Math.Cos(dAngle);
            return new Minutia
            {
                Angle = (newAngle > 2 * Math.PI) ? newAngle - 2 * Math.PI : (newAngle < 0) ? newAngle + 2 * Math.PI : newAngle,
                X = Convert.ToInt16(Math.Round((m.X - query.X) * cos - (m.Y - query.Y) * sin + template.X)),
                Y = Convert.ToInt16(Math.Round((m.X - query.X) * sin + (m.Y - query.Y) * cos + template.Y))
            };
        }

        private double dAngle;
        private Minutia template;
        private Minutia query;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Tecnológico de Monterrey
Mexico Mexico
I received my B.S. and M.S. degrees from the University of Ciego de Ávila, Cuba, in 2007 and I received my PhD. degree in 2014 from the National Institute of Astrophysics, Optics and Electronics (INAOE), Mexico.

I have developed software to solve pattern recognition problems. A successful example is the algorithm DMC which is the most accurate (according to EER) among those which compare both fingerprints and palmprints in the international competition FVC-onGoing.

I have been involved in several research projects about pattern recognition and I have published tens of papers in referenced journals such as "Pattern Recognition," "Knowledge-Based Systems," "Information Sciences", and "IEEE Transactions on Information Forensics and Security."

Written By
Cuba Cuba
Milton García-Borroto is graduated from Las Villas Central University, Cuba, in 2000. He received the M.S. degree in 2007 from the National Institute of Astrophisics, Optics and Electronics, Mexico, where he continues his studies toward a Ph.D. degree. His research interests are pattern recognition and biometry.

Relevant papers:
1. M. García-Borroto, J. F. Martinez Trinidad, J. A. Carrasco Ochoa, M. A. Medina-Pérez, and J. Ruiz-Shulcloper. LCMine: An efficient algorithm for mining discriminative regularities and its application in supervised classification. Pattern Recognition vol. 43, pp. 3025-3034, 2010.
2. M. García-Borroto, J. F. Martinez Trinidad, J. A. Carrasco Ochoa. A New Emerging Pattern Mining Algorithm and Its Application in Supervised Classification. M.J. Zaki et al. (Eds.): PAKDD 2010, Part I, Lecture Notes in Artificial Intelligence, vol. 6118, pp. 150–157, 2010.
3. M. A. Medina-Pérez, A. Gutiérrez-Rodríguez, and M. García-Borroto, "Improving Fingerprint Matching Using an Orientation-Based Minutia Descriptor," Lecture Notes in Computer Science, vol. 5856, pp. 121-128, 2009.
4. M. García-Borroto, Y. Villuendas-Rey, J. A. Carrasco-Ochoa, and J. F. Martínez-Trinidad, "Finding Small Consistent Subset for the Nearest Neighbor Classifier Based on Support Graphs," Lecture Notes in Computer Science, vol. 5856, pp. 465-472, 2009.
5. M. García-Borroto, Y. Villuendas-Rey, J. A. Carrasco-Ochoa, and J. F. Martínez-Trinidad, "Using Maximum Similarity Graphs to Edit Nearest Neighbor Classifiers," Lecture Notes in Computer Science, vol. 5856, pp. 489-496, 2009.
6. M. A. Medina-Pérez, M. García-Borroto, and J. Ruiz-Shulcloper, "Object Selection Based on Subclass Error Correcting for ALVOT," Lecture Notes in Computer Science, vol. 4756, pp. 496-505, 2007.

Andres Eduardo Gutierrez Rodriguez is graduated from Las Villas Central University, Cuba, in 2006. He received the M.S. degree in 2009 from the University of Ciego de Ávila, Cuba. His research interests are pattern recognition and biometry.

Relevant papers:

-M. A. Medina-Pérez, A. Gutiérrez-Rodríguez, and M. García-Borroto, "Improving Fingerprint Matching Using an Orientation-Based Minutia Descriptor," Lecture Notes in Computer Science, vol. 5856, pp. 121-128, 2009.
-A. E. Gutierrez-Rodriguez, M. A. Medina-Perez, J. F. Martinez-Trinidad, J. A. Carrasco-Ochoa, and M. Garcia-Borroto, "New Dissimilarity Measures for Ultraviolet Spectra Identification," Lecture Notes in Computer Science, vol. 6256, pp. 220-229, 2010.

Written By
Program Manager
Spain Spain
Octavio Loyola-González received his PhD degree in Computer Science from the National Institute for Astrophysics, Optics, and Electronics, Mexico. He has won several awards from different institutions due to his research work on applied projects; consequently, he is a Member of the National System of Researchers in Mexico (Rank1). He worked as a distinguished professor and researcher at Tecnologico de Monterrey, Campus Puebla, for undergraduate and graduate programs of Computer Sciences. Currently, he is responsible for running Machine Learning & Artificial Intelligence practice inside Stratesys., where he is involved in the development and implementation using analytics and data mining. He has outstanding experience in the fields of big data & pattern recognition, cloud computing, IoT, and analytical tools to apply them in sectors where he has worked for as Banking & Insurance, Retail, Oil&Gas, Agriculture, Cybersecurity, Biotechnology, and Dactyloscopy. From these applied projects, Dr. Loyola-González has published several books and papers in well-known journals, and he has several ongoing patents as manager and researcher in Stratesys.

Comments and Discussions