示例#1
0
        private void OnEnrollCompleted(IAsyncResult r)
        {
            try
            {
                if (InvokeRequired)
                {
                    BeginInvoke(new AsyncCallback(OnEnrollCompleted), r);
                }
                else
                {
                    var task   = _biometricClient.EndPerformTask(r);
                    var status = task.Status;

                    // Check if extraction was canceled
                    if (status == NBiometricStatus.Canceled)
                    {
                        return;
                    }

                    if (status == NBiometricStatus.Ok)
                    {
                        lblQuality.Text = $"Quality: {_subjectFinger.Objects[0].Quality}";

                        _template = _subject.Save();

                        ShowMessage(@"Please wait while your fingerprint is being processed...");
                        UpdateStateToParent(ApplicationController.State.Captured_Good);
                    }
                    else
                    {
                        lblQuality.Text = string.Empty;

                        ShowMessage(@"Fingerprint image is of low quality");
                        UpdateStateToParent(ApplicationController.State.Captured_Bad);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowMessage(string.Format("Extraction error: {0}", ex.Message));
                Logger.logToFile(ex, AppSettings.ErrorLogPath);
            }
        }
示例#2
0
 private void SetActiveTemplate(NBuffer template)
 {
     this.Template = null;
     this.Template = template;
 }
示例#3
0
        private string MatchStudents(NFRecord template, BindingList<student> StudentsInCourse)
        {
            const string Components = "Biometrics.FingerExtraction,Biometrics.FingerMatching";

            matchedFingerID = 0;
            matchedScore = 0;
            string highestStudent = "";
            int highestMatch = 0;

            NFExtractor extractor = null;
            NMatcher matcher = null;
            try
            {
                lblStatus.Text = "Getting License!";
                Application.DoEvents();
                // Obtain license.
                if (!NLicense.ObtainComponents(licServer, 5000, Components))
                {
                    Console.WriteLine(@"Could not obtain licenses for components: {0}", Components);
                    //return -1;
                }
                lblStatus.Text = "Got License!";
                Application.DoEvents();
                // create an extractor
                //extractor = new NFExtractor();

                // extract probe template

                NBuffer probeTemplate = template.Save();

                lblStatus.Text = "Exctracting templates";
                // extract gallery templates
                int args = StudentsInCourse.Count * 10;
                NBuffer[] galleryTemplates = new NBuffer[args - 1];
                string[] students = new string[args - 1];
                int n = 0;
                foreach (student currentStudent in StudentsInCourse)
                {
                    for (int count = 0; count < 10; count++)
                    {
                        try
                        {
                            galleryTemplates[n+count] = new NBuffer(currentStudent.template[count]);
                            students[n + count] = currentStudent.StudentNumber;

                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Could not load template for student" + currentStudent.StudentNumber + " - " + ex.Message);
                        }
                    }

                    n = n + 10;
                }

                // create a matcher
                matcher = new NMatcher();
                // identify reference template by comparing to each template from arguments
                Console.WriteLine(@"=== identification started ===");
                matcher.IdentifyStart(probeTemplate);

                lblStatus.Text = "Identifying start";
                try
                {
                    for (int i = 1; i < args; i++)
                    {
                        if (galleryTemplates[i - 1].Size != 0)
                        {
                            int score = matcher.IdentifyNext(galleryTemplates[i - 1]);
                            if (score > highestMatch)
                            {
                                Console.WriteLine(@"template[{0}] scored {1} {2}", i - 1, score, score > 0 ? "(Matched)" : "");
                                Console.WriteLine("student number matched: " + students[i-1]);
                                highestMatch = score;
                                highestStudent = students[i - 1];
                                matchedFingerID = i % 10;
                                matchedScore = score;
                            }

                        }

                    }
                }
                finally
                {
                    matcher.IdentifyEnd();
                }
                Console.WriteLine(@"=== identification finished ===");

                //return 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

            }
            finally
            {
                lblStatus.Text = "Releasing License";
                Application.DoEvents();
                NLicense.ReleaseComponents(Components);

                if (extractor != null)
                {
                    extractor.Dispose();
                }
                if (matcher != null)
                {
                    matcher.Dispose();
                }
                lblStatus.Text = "License Released";
                Application.DoEvents();
            }

            return highestStudent;
        }
示例#4
0
        internal static BiometricsRecord GetBiometricsRecord(BiometricsRecord _BiometricsRecord, string SourceFileDir)
        {
            String userDir = SourceFileDir + "\\" + _BiometricsRecord.EnrollmentId + "\\";

            //Find Images If Exists and Save in Biometrics Record

            //Get Signature
            if (File.Exists(userDir + "sign_image.jpg"))
            {
                byte[] imageBytes = File.ReadAllBytes(userDir + "sign_image.jpg");
                Image image = Image.FromStream(new MemoryStream(imageBytes));
                _BiometricsRecord.Signature = image;
            }

            //Get Photo
            if (File.Exists(userDir + "photo_image.jpg"))
            {
                byte[] imageBytes = File.ReadAllBytes(userDir + "photo_image.jpg");
                Image image = Image.FromStream(new MemoryStream(imageBytes));
                _BiometricsRecord.Photograph = image;
            }

            //Get Photo Template
            if (File.Exists(userDir + "photo_template.tem"))
            {
                byte[] imageBytes = File.ReadAllBytes(userDir + "photo_template.tem");
                _BiometricsRecord.PhotographTemplate = imageBytes;
            }

            //Get Finger Images
            foreach (var fingerDescription in Enum.GetValues(typeof(FingerDescription)))
            {
                string fingerFile = userDir + fingerDescription + ".jpg";
                string fingerTemplateFile = userDir + fingerDescription + ".tem";

                Image image = null;
                if (File.Exists(fingerFile))
                {
                    byte[] imageBytes = File.ReadAllBytes(fingerFile);
                    image = Image.FromStream(new MemoryStream(imageBytes));
                }

                //Get Finger Template
                if (File.Exists(fingerTemplateFile))
                {
                    var imageBytes = File.ReadAllBytes(fingerTemplateFile);
                    var fingerprintBuffer = new NBuffer(imageBytes);

                    //NFinger finger, NBuffer fingerTemplate
                    using (var biometricClient = new NBiometricClient())
                    using (var subject = new NSubject())
                    using (var finger = new NFinger())
                    {
                        //Read finger image from enrollment and add it to NFinger object
                        finger.Image = NImage.FromMemory(fingerprintBuffer, NImageFormat.Wsq);
                        //add NFinger object to NSubject
                        subject.Fingers.Add(finger);
                        ////Set finger template size (recommended, for enroll to database, is large) (optional)
                        //biometricClient.FingersTemplateSize = NTemplateSize.Large;

                        //Create template from added finger image
                        var status = biometricClient.CreateTemplate(subject);
                        if (status == NBiometricStatus.Ok)
                        {
                            _BiometricsRecord.SaveActiveUserFingerRecords(finger, subject, (FingerDescription)fingerDescription);
                        }
                    }
                }
            }
            //Get Grouped Finger Templates
            if (File.Exists(userDir + "fingers_template.tem"))
            {
                byte[] imageBytes = File.ReadAllBytes(userDir + "fingers_template.tem");
                _BiometricsRecord.FingerTemplates = imageBytes;
            }
            return _BiometricsRecord;
        }
示例#5
0
        internal bool SaveBiometricsRecords(BiometricsRecord BiometricsRecord, string DestFileDir)
        {
            NFTemplate _NFTemplate = new NFTemplate();
            //Create Folder for the User
            String userDir = DestFileDir + "\\" + BiometricsRecord.EnrollmentId + "\\";
            if (!Directory.Exists(userDir))
            {
                DirectoryInfo dir = Directory.CreateDirectory(userDir);
            }

            //Save User Signature
            if (BiometricsRecord.Signature != null)
            {
                BiometricsRecord.Signature.Save(userDir + "sign_image.jpg");
            }

            //Save User Photo
            if (BiometricsRecord.Photograph != null)
            {
                BiometricsRecord.Photograph.Save(userDir + "photo_image.jpg");
                File.WriteAllBytes(userDir + "photo_template.tem", BiometricsRecord.PhotographTemplate.ToArray());
            }

            if (BiometricsRecord.FingerprintRecords.Count > 0)
            {
                //save Fingerprint
                foreach (var userFingerprint in BiometricsRecord.FingerprintRecords)
                {
                    userFingerprint.FingerImage.Save(userDir + userFingerprint.FingerDescription + ".jpg");
                    File.WriteAllBytes(userDir + userFingerprint.FingerDescription + ".tem", userFingerprint.FingerTemplate.ToArray());

                    //Add FingerTemplate to NFTemplate

                    if (userFingerprint.FingerRecord != null)
                    {
                        _NFTemplate.Records.Add(userFingerprint.FingerRecord);
                    }
                    else
                    {
                        var wsq = new NBuffer(userFingerprint.FingerWsq);

                        //var image = NImage.FromMemory(wsq, NImageFormat.Wsq).ToBitmap();

                        //NFinger finger, NBuffer fingerTemplate
                        using (var biometricClient = new NBiometricClient())
                        using (var subject = new NSubject())
                        using (var finger = new NFinger())
                        {
                            //Read finger image from enrollment and add it to NFinger object
                            finger.Image = NImage.FromMemory(wsq, NImageFormat.Wsq);
                            //add NFinger object to NSubject
                            subject.Fingers.Add(finger);
                            ////Set finger template size (recommended, for enroll to database, is large) (optional)
                            //biometricClient.FingersTemplateSize = NTemplateSize.Large;

                            //Create template from added finger image
                            var status = biometricClient.CreateTemplate(subject);
                            if (status == NBiometricStatus.Ok)
                            {
                                userFingerprint.FingerRecord = finger.Objects[0].Template;
                                _NFTemplate.Records.Add(finger.Objects[0].Template);
                            }
                        }
                        //NLicense.ReleaseComponents("Biometrics.FingerExtraction");
                    }

                }

                //Save Grouped FingerTemplates
                var ms = new NMemoryStream();
                _NFTemplate.Save(ms);
                BiometricsRecord.FingerTemplates = ms.ToArray();
                File.WriteAllBytes(userDir + "fingers_template.tem", BiometricsRecord.FingerTemplates);

            }

            //Save User Record as Serilalised Binary Data
            BinarySerialization.WriteToBinaryFile(userDir + "UserRecord.crims", BiometricsRecord);

            //If the code runs to this point without Failure, We are good
            return true;
        }
示例#6
0
        private void OnCapturingCompleted(IAsyncResult r)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new AsyncCallback(OnCapturingCompleted), r);
            }
            else
            {
                try
                {
                    var status = _biometricClient.EndCapture(r);
                    // If Stop button was pushed
                    if (status == NBiometricStatus.Canceled)
                    {
                        return;
                    }

                    lblStatus.Text = status.ToString();
                    if (status != NBiometricStatus.Ok)
                    {
                        // Since capture failed start capturing again
                        _subject.Faces[0].Image = null;
                        _biometricClient.BeginCapture(_subject, OnCapturingCompleted, null);
                    }
                    else
                    {
                        if (_subject.Faces[0].Image != null)
                        {
                            //facesView.Image = image;
                            var size = new Size {
                                Width = int.Parse(Settings.Default.ImageWidth), Height = int.Parse(Settings.Default.ImageHeight)
                            };
                            var memoryStream = new MemoryStream();
                            _subject.Faces[0].Image.ToBitmap().Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                            var faceBoundingRect = _subject.Faces[0].Objects[0].BoundingRect;
                            //var resizedImage = _subject.Faces[0].Image.Crop(50, 50, 50, 50).ToBitmap();

                            //int widthOffset;
                            //if (faceBoundingRect.Left > faceBoundingRect.Right)
                            //{
                            //    //widthOffset = 2*tt.Right/6 + tt.Width;
                            //    widthOffset = (faceBoundingRect.Left - faceBoundingRect.Right) / 3 + faceBoundingRect.Width + 50;
                            //}
                            //else
                            //{
                            //    //widthOffset = 2*tt.Left/6 + tt.Width;
                            //    //widthOffset = tt.Left + tt.Width + 50;

                            //    widthOffset = (faceBoundingRect.Right - faceBoundingRect.Left) / 3 + faceBoundingRect.Width;
                            //}

                            //if (faceBoundingRect.Left > faceBoundingRect.Right)
                            //{
                            //    //widthOffset = tt.Left - tt.Right;
                            //    widthOffset = (faceBoundingRect.Right - faceBoundingRect.Right) / 2 + faceBoundingRect.Width / 2 + 50;
                            //}
                            //else
                            //{
                            //    widthOffset = faceBoundingRect.Right - faceBoundingRect.Left;
                            //    widthOffset = (faceBoundingRect.Width * 10) / 100 + faceBoundingRect.Width;
                            //}

                            var resizedImage = ResizeImage(memoryStream, (faceBoundingRect.Location.X - faceBoundingRect.Left) + faceBoundingRect.Width, faceBoundingRect.Height + 50, true, faceBoundingRect.X, faceBoundingRect.Top, faceBoundingRect.Right, faceBoundingRect.Bottom);
                            if (resizedImage != null)
                            {
                                pictureBoxCroped.Image = resizedImage;
                                _croppedPhotoImage     = resizedImage;
                            }
                            _template = _subject.GetTemplateBuffer();
                            EnableControls(false);
                        }

                        //UpdateView(_subject.Faces[0], status);
                    }
                }
                catch (Exception ex)
                {
                    AppUtils.ShowException(ex);
                    lblStatus.Text = string.Empty;
                    EnableControls(false);
                }
            }
        }
示例#7
0
 private void SaveTemplateForVerification(NBuffer _template)
 {
     TemplateNotifyer(_template);
 }
示例#8
0
        private void OnEnrollCompleted(IAsyncResult r)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new AsyncCallback(OnEnrollCompleted), r);
            }
            else
            {
                var task = _biometricClient.EndPerformTask(r);

                var status = task.Status;

                // Check if extraction was canceled
                if (status == NBiometricStatus.Canceled)
                {
                    return;
                }

                if (status == NBiometricStatus.Ok)
                {
                    lblQuality.Text = $"Quality: {_subjectFinger.Objects[0].Quality}";

                    if (_nfView.Finger.Image != null)
                    {
                        _nfView.Finger.Image.Dispose();
                        _nfView.Finger.Image = null;
                    }
                    if (_nfView.Finger.Objects[0].Template != null)
                    {
                        _nfView.Finger.Objects[0].Template.Dispose();
                        _nfView.Finger.Objects[0].Template = null;
                    }
                    lblQuality.Text = string.Empty;

                    OnIsScanningChanged(false);

                    _template = _subject.Save();

                    _nfView.Finger.Objects[0].Template = _subject.Fingers[0].Objects[0].Template;
                    SaveTemplateForVerification(_template);
                    SaveUserIdForVerification(textBoxIDNumber.Text);
                    UpdateStateToParent(ApplicationController.State.Captured_Good);

                    NImage image = _subjectFinger.Image;
                    if (image == null)
                    {
                        return;
                    }

                    _nfView.Width        = (int)image.Width;
                    _nfView.Height       = (int)image.Height;
                    _nfView.Finger.Image = image;
                    _nfView.Refresh();
                }
                else
                {
                    MessageBox.Show($"Fingerprint image is of low quality OR The template was not extracted: {status}.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    _subject       = null;
                    _subjectFinger = null;
                }
            }
        }
示例#9
0
        /// <summary>
        /// Sort an n-tuple file in external memory. The file is overwritten.
        /// </summary>
        /// <param name="file">The n-tuple file.</param>
        /// <param name="itemLength">The length of the tuples in the file.</param>
        /// <param name="maxItemsInMemory">The maximum amount of n-tuples to keep in memory.</param>
        /// <param name="sortOrder">The sort order to use.</param>
        public static void SortFile(string file, int itemLength, int maxItemsInMemory, params int[] sortOrder)
        {
            //
            // step 1: sort in chuncks that fit in the memory we have. the size of each chunk is
            // equal to the amount of memory provided (given in numbers of items)

            //
            // temp files used to store the sorted chunks
            var chunkFiles = new List <string>();

            //
            // IComparer used to compare two items. the priorities are given.
            var sorter = new NComparer(sortOrder);

            //
            // open the file for reading
            using (var br = new BinaryReader(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))) {
                //
                // counter to keep track of how much items we've read
                var i = 0;

                //
                // current chunk, represented as an array of items
                var chunk = new long[maxItemsInMemory][];

                //
                // we read as long as we have not yet reached the end of the file
                while (br.BaseStream.Position < br.BaseStream.Length)
                {
                    //
                    // if we still have space in the chunk, read the next triple from the file
                    if (i < maxItemsInMemory)
                    {
                        chunk[i] = Read(br, itemLength);
                        i++;
                    }
                    //
                    // if not, we need to sort and output the current chunk.
                    // for this part sorting is done in-memory
                    else
                    {
                        //
                        // use default array sorting using the IComparer we have defined earlier
                        Array.Sort(chunk, sorter);

                        //
                        // generate a file name for the chunk. it needs to be unique for obvious
                        // reasons
                        var fileName = String.Format("~{0}.chunk.tmp", Generator.GetRandomFilename(12));

                        //
                        // add the file to the list of chunk files. we'll need it later
                        chunkFiles.Add(fileName);

                        //
                        // open a binary writer and write the sorted items from the current chunk
                        // to the chunk file
                        using (var bw = new BinaryWriter(File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.None))) {
                            for (int j = 0; j < chunk.Length; j++)
                            {
                                if (chunk[j] != null)
                                {
                                    Write(bw, chunk[j]);
                                }
                            }
                        }

                        //
                        // clear the chunk array as it might not get completely overwritten during
                        // the next pass
                        Array.Clear(chunk, 0, chunk.Length);

                        //
                        // reset the triples-read counter
                        i = 0;
                    }
                }

                //
                // here, we have read the entire file, but there still might be some items left
                // in the last chunk that we need to handle.
                // the code to do this is duplicated from the else block above.
                if (i > 0)
                {
                    Array.Sort(chunk, sorter);

                    var fileName = String.Format("~{0}.chunk.tmp", Generator.GetRandomFilename(12));
                    chunkFiles.Add(fileName);

                    using (var bw = new BinaryWriter(File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.None))) {
                        for (int j = 0; j < chunk.Length; j++)
                        {
                            if (chunk[j] != null)
                            {
                                Write(bw, chunk[j]);
                            }
                        }
                    }
                }
            }

            //
            // force garbage collection
            GC.Collect();

            //
            // step 2: perform k-way merge sort on the chunks. now that we have the sorted chunks,
            // we need to merge them and write out the final result.

            //
            // the number of pages used for reading must be equal to the number of chunk files
            var numReadPages = chunkFiles.Count;

            //
            // the total number of pages has one additional page for writing the output to
            var numPages = numReadPages + 1;

            //
            // the size of each page is the number of items that may be kept in memory
            // devided by the number of pages. WARNING: if the amount of memory available is
            // too small in relation to the size of the input file, then there may be too
            // many chunks, hence too many pages to fit in memory when each page should have
            // at least space for 1 item.
            var pageSize = maxItemsInMemory / numPages;

            //
            // the buffer simply contains the pages
            var buffer = new NBuffer(numPages, pageSize);

            //
            // the last page is the one used for writing the output to. this variable is a shortcut
            // that allows us to say buffer[pageOutputId] instead of buffer[numPages - 1].
            var pageOutputId = numPages - 1;

            //
            // the page cursors are simply integers denoting the position of the reading pointers
            // in each of the pages
            var pageCursors = new int[numPages];

            //
            // the chunk cursors are binary readers pointing to each of the chunks from the
            // previous step
            var chunkCursors = new BinaryReader[numReadPages];

            //
            // these variables keep the currenly smallest item found (e.g. the one that needs to
            // be written next to the output file to maintain the sort order), and the Id of the
            // chunk this item resides in
            long[] minItem    = null;
            var    minChunkId = -1;

            //
            // we start by initializing the cursors and reading the initial parts of all the chunks
            // into their respective buffer pages
            for (int i = 0; i < numReadPages; i++)
            {
                pageCursors[i]  = 0;
                chunkCursors[i] = new BinaryReader(File.Open(chunkFiles[i], FileMode.Open, FileAccess.Read, FileShare.Read));
                ReadToPage(chunkCursors[i], itemLength, buffer[i]);
            }

            //
            // we open a binary writer to write the output (the sorted file) to. note we just
            // overwrite the existing file. this is possible because all information from the
            // original file is now duplicated in the sorted chunks anyway.

            using (var bw = new BinaryWriter(File.Open(file, FileMode.Create, FileAccess.Write, FileShare.None))) {
                //
                // entering the main loop of the merge that we will remain in for as long as there
                // are items in any of the pages used for reading
                do
                {
                    //
                    // reset the next item in the sort order to null. this is used to determine
                    // if can leave the main loop.
                    minItem = null;

                    //
                    // here we find the next item in the sort order (the smallest item) in any
                    // of the read pages
                    for (int i = 0; i < numReadPages; i++)
                    {
                        //
                        // fetch the current smallest item in this page. it will always be the
                        // one the respective cursor is pointing to.
                        var t = buffer[i][pageCursors[i]];

                        //
                        // it's possible the page does not contain (any more) items. if so we
                        // can just ignore it. for this we do assume that if we read a null from
                        // position i at some page, then all positions j > i on that same page are
                        // also null
                        if (t != null)
                        {
                            //
                            // if the current smallest item doesn't exist yet, then the one we've
                            // just read is trivially the new smallest item
                            if (minItem == null)
                            {
                                minItem    = t;
                                minChunkId = i;
                            }
                            //
                            // if a smallest item does exist, we need to do a comparison first.
                            // we use the same IComparer that we defined earlier
                            else
                            {
                                var c = sorter.Compare(t, minItem);
                                if (c < 0)
                                {
                                    minItem    = t;
                                    minChunkId = i;
                                }
                            }
                        }
                    }

                    //
                    // checking if a new smallest item has been identified. if it is we need to
                    // write it to the output page. if not, we don't need to do anything and will
                    // exit the main loop.
                    if (minItem != null)
                    {
                        //
                        // we increment the cursor belonging to the page where the next smallest
                        // item resides
                        pageCursors[minChunkId]++;

                        //
                        // check if we have read all the items on this page. if so, read the next
                        // set of items from the chunk file and reset the cursor
                        if (pageCursors[minChunkId] >= pageSize)
                        {
                            ReadToPage(chunkCursors[minChunkId], itemLength, buffer[minChunkId]);
                            pageCursors[minChunkId] = 0;
                        }

                        //
                        // put the next smallest item in the output page
                        buffer[pageOutputId][pageCursors[pageOutputId]] = minItem;

                        //
                        // increment the output page cursor
                        pageCursors[pageOutputId]++;

                        //
                        // check if the output page is full. if so, write its items to the output
                        // file, clear the page, and reset the cursor
                        if (pageCursors[pageOutputId] >= pageSize)
                        {
                            for (int i = 0; i < pageSize; i++)
                            {
                                Write(bw, buffer[pageOutputId][i]);
                            }
                            buffer[pageOutputId].Clear();
                            pageCursors[pageOutputId] = 0;
                        }
                    }
                } while (minItem != null);

                //
                // the items from all the chunks have been read and sorted, but the last couple
                // of them may still reside on the output page. here we write these last ones to
                // the output file.
                for (int i = 0; i < pageSize; i++)
                {
                    var t = buffer[pageOutputId][i];
                    if (t != null)
                    {
                        Write(bw, t);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            //
            // close the chunk cursors and delete the chunk files
            for (int i = 0; i < numReadPages; i++)
            {
                chunkCursors[i].Dispose();
                File.Delete(chunkFiles[i]);
            }
        }
示例#10
0
        private int identify()
        {
            verifyLicense();
            bool         largeTemplate   = true;
            cryptography decrypt         = new cryptography();
            NMatcher     templateMatcher = null;
            int          maxKeyNum       = 0;
            int          primKey         = 0;

            try {
                NBuffer probeTemplateBuffer = null;
                byte [] probeTemplateArray  = null;
                try {
                    NleDetectionDetails details;                     // unused
                    if (!createTemplate(globalInsetFaceBmp, largeTemplate, out details))
                    {
                        return(primKey);
                    }
                    probeTemplateBuffer = facialTemplate.Save();
                    probeTemplateArray  = probeTemplateBuffer.ToByteArray();
                } catch (IOException ex) {
                    MessageBox.Show("error reading input file {0}: " + ex);
                    return(primKey);
                }

                // extract gallery templates
                // This code allows for searching a database where rows (users) have been deleted,
                // causing primaryKeys to not be sequential.
                int row = 1;
                maxKeyNum = myDdInterface.maxPrimaryKey();
                if (maxKeyNum == 0)
                {
                    MessageBox.Show("There are no registered users.\nPlease enroll and try again.");
                    return(maxKeyNum);
                }
                List <byte []>  dbaseTemplates = new List <byte []> ();
                List <int [, ]> rowKeyList     = new List <int [, ]> ();        // list of row/primary keys

                for (int i = 0; i < maxKeyNum; i++)
                {
                    try {
                        byte [] tempArray = myDdInterface.getTemplateFromKey(i + 1);
                        if (tempArray != null)                        // skip deleted records
                        {
                            int [,] rowKeyRef = new int [1, 2];
                            dbaseTemplates.Add(tempArray);
                            // store row/primary key reference
                            rowKeyRef [0, 0] = row;
                            rowKeyRef [0, 1] = i + 1;
                            rowKeyList.Add(rowKeyRef);
                            row++;
                        }
                    } catch (IOException ex) {
                        MessageBox.Show("error reading reference template " + i + ": " + ex);
                        return(primKey);
                    }
                }

                templateMatcher = new NMatcher();
                templateMatcher.IdentifyStart(probeTemplateArray);

                try {
                    int numOfTemplates = dbaseTemplates.Count();
                    int score          = 0;
                    int highScore      = 0;
                    for (int i = 0; i < numOfTemplates; i++)
                    {
                        score = templateMatcher.IdentifyNext(dbaseTemplates [i]);
                        if (score > highScore)
                        {
                            highScore = score;
                            // get primary key based on row number
                            int [,] tempRef = new int [1, 2];
                            tempRef         = rowKeyList [i];
                            primKey         = tempRef [0, 1];
                        }
                    }
                    if (primKey == 0)
                    {
                        MessageBox.Show("Sorry, Unable to Identify.\nTry again.");
                        return(primKey);
                    }
                    else
                    {
                        string fName     = myDdInterface.getFName(primKey);
                        string lName     = myDdInterface.getLName(primKey);
                        Bitmap storedBmp = myDdInterface.getImageFromId(myDdInterface.userIdFromKey(primKey));                          // Check for potential errors referencing Primary key.
                        if (enrolledImagePictureBox.InvokeRequired)
                        {
                            enrolledImagePictureBox.Invoke(new Action(() => enrolledImagePictureBox.Image = storedBmp));
                            enrolledImageNameLabel.Invoke(new Action(() => enrolledImageNameLabel.Text    = (fName + " " + lName)));
                        }
                        else
                        {
                            enrolledImagePictureBox.Image = storedBmp;
                            enrolledImageNameLabel.Text   = (fName + " " + lName);
                        }
                        if (!enrolledImagePictureBox.Visible)
                        {
                            enrolledPicVisToggle();
                        }
                        if (tabIndex == 0)                        // play video only on main tab
                        {
                            playVideoFile(primKey);
                        }
                        return(primKey);
                    }
                } catch (Exception ex) {
                    MessageBox.Show("" + ex);
                } finally {
                    templateMatcher.IdentifyEnd();
                    facialTemplate = null;
                }
                return(primKey);
            } catch (Exception ex) {
                MessageBox.Show("" + ex);
                return(primKey);
            } finally {
                NLicense.ReleaseComponents(Components);
                if (templateMatcher != null)
                {
                    templateMatcher.Dispose();
                }
            }
        }