public void Restart()
 {
     lock ( templateMutex )
     {
         openEyeTemplate              = null;
         closedEyeTemplate            = null;
         nextInitializationImageIndex = 0;
         closeEyeMessageTimer         = -1;
     }
 }
        private void UpdateTemplates(FastBitmap img)
        {
            float templateDiff = Math.Abs(inputOpenEyeNcc - inputClosedEyeNcc);

            if (templateDiff >= MinimumDifferenceForUpdate)
            {
                string   executableName     = Application.ExecutablePath;
                FileInfo executableFileInfo = new FileInfo(executableName);
                FastBitmap.NccTemplate currentImageTemplate = img.GetNccTemplate(GetTemplateRectange(EyeLocation));

                if (inputOpenEyeNcc > inputClosedEyeNcc)
                {
                    openEyeTemplate.MergeTemplates(currentImageTemplate, templateDiff);
                }
                else
                {
                    closedEyeTemplate.MergeTemplates(currentImageTemplate, templateDiff);
                }
            }
        }
        public void Update(FastBitmap img, Point eyeLocation, float timeElapsed)
        {
            lock ( templateMutex )
            {
                if (IsReady)
                {
                    Point searchAreaStartPoint = GetSearchAreaStartPoint(eyeLocation);

                    try
                    {
                        img.GetIntensityMap(searchAreaStartPoint.X, searchAreaStartPoint.Y,
                                            initialSearchintensityMapWidth, initialSearchintensityMapHeight, initialSearchIntensityMap);

                        Point   tempPoint;
                        float[] refinedSearchNccScores;

                        SetInitialNccSearchTemplates(eyeLocation);

                        refinedSearchNccScores = openEyeTemplate.GetTopNccScores(initialSearchTemplates, refinedSearchIndices);


                        inputOpenEyeNcc = float.NegativeInfinity;

                        for (int i = 0; i < refinedSearchIndices.Length; ++i)
                        {
                            FastBitmap.NccTemplate tempTemplate = initialSearchTemplates[refinedSearchIndices[i]];
                            float tempNcc = img.GetNccScore(openEyeTemplate, new Rectangle(tempTemplate.X - (stepAmount - 1),
                                                                                           tempTemplate.Y - (stepAmount - 1), (2 * stepAmount) - 1, (2 * stepAmount) - 1), out tempPoint);

                            if (tempNcc > inputOpenEyeNcc)
                            {
                                inputOpenEyeNcc = tempNcc;
                                eyeOpenLoc      = tempPoint;
                            }
                        }

                        refinedSearchNccScores = closedEyeTemplate.GetTopNccScores(initialSearchTemplates, refinedSearchIndices);

                        inputClosedEyeNcc = float.NegativeInfinity;

                        for (int i = 0; i < refinedSearchIndices.Length; ++i)
                        {
                            FastBitmap.NccTemplate tempTemplate = initialSearchTemplates[refinedSearchIndices[i]];
                            float tempNcc = img.GetNccScore(closedEyeTemplate, new Rectangle(tempTemplate.X - (stepAmount - 1),
                                                                                             tempTemplate.Y - (stepAmount - 1), (2 * stepAmount) - 1, (2 * stepAmount) - 1), out tempPoint);

                            if (tempNcc > inputClosedEyeNcc)
                            {
                                inputClosedEyeNcc = tempNcc;
                                eyeClosedLoc      = tempPoint;
                            }
                        }
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        // Set as eye open since this performs no action, set open eye location as estimated location
                        inputOpenEyeNcc   = 1;
                        eyeOpenLoc        = eyeLocation;
                        inputClosedEyeNcc = 0;
                    }
                }
                else
                {
                    if (!xDistanceBetweenEyesSet)
                    {
                        throw new InvalidOperationException("Must call SetXDistanceBetweenEyes before calling Update");
                    }
                    try
                    {
                        initializationTemplates[nextInitializationImageIndex] = img.GetNccTemplate(GetTemplateRectange(eyeLocation));
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        return;
                    }

                    if (closeEyeMessageTimer > 0)
                    {
                        closeEyeMessageTimer -= timeElapsed;
                        inputOpenEyeNcc       = img.GetNccScore(openEyeTemplate, GetFindingTemplateSearchArea(eyeLocation), 1, out eyeOpenLoc);
                    }
                    else
                    {
                        if (openEyeTemplate == null)
                        {
                            for (int i = 0; i < nextInitializationImageIndex; ++i)
                            {
                                initializationNccScores[i, nextInitializationImageIndex]
                                      = initializationNccScores[nextInitializationImageIndex, i]
                                      = initializationTemplates[i].GetNcc(initializationTemplates[nextInitializationImageIndex]);
                            }
                        }
                        else
                        {
                            inputOpenEyeNcc = img.GetNccScore(openEyeTemplate, GetFindingTemplateSearchArea(eyeLocation), 1, out eyeOpenLoc);

                            initializationNccScores[nextInitializationImageIndex, 0]
                                = openEyeTemplate.GetNcc(initializationTemplates[nextInitializationImageIndex]);
                        }

                        initializationNccScores[nextInitializationImageIndex, nextInitializationImageIndex] = 1;

                        nextInitializationImageIndex++;

                        if (InitializationImageCount == nextInitializationImageIndex)
                        {
                            if (openEyeTemplate == null)
                            {
                                int bestIndex = GetBestRepresentativeTemplateIndex();
                                openEyeTemplate = initializationTemplates[bestIndex];
                                cmsTrackingSuiteAdapter.SendMessage(CloseEyesMessage);
                                closeEyeMessageTimer = CloseEyeMessageStartTime;

                                if (CMSLogger.CanCreateLogEvent(false, true, false, "BlinkLinkLogTemplatesEvent"))
                                {
                                    BlinkLinkLogTemplatesEvent logEvent = new BlinkLinkLogTemplatesEvent();
                                    logEvent.IsOpenTemplates  = true;
                                    logEvent.SelectedTemplate = bestIndex;
                                    logEvent.SetTemplates(initializationTemplates);
                                    CMSLogger.SendLogEvent(logEvent);
                                }
                            }
                            else
                            {
                                float nccScore;
                                int   bestIndex = GetFurtherestFromEyeOpen(out nccScore);
                                FastBitmap.NccTemplate representativeTemplate = initializationTemplates[bestIndex];

                                if (nccScore <= ClassDifferenceThreshold)
                                {
                                    closedEyeTemplate = representativeTemplate;

                                    if (CMSLogger.CanCreateLogEvent(false, true, false, "BlinkLinkLogTemplatesEvent"))
                                    {
                                        BlinkLinkLogTemplatesEvent logEvent = new BlinkLinkLogTemplatesEvent();
                                        logEvent.IsOpenTemplates  = false;
                                        logEvent.SelectedTemplate = bestIndex;
                                        logEvent.SetTemplates(initializationTemplates);
                                        CMSLogger.SendLogEvent(logEvent);
                                    }
                                }
                            }

                            nextInitializationImageIndex = 0;
                        }
                    }
                }
            }
        }
        private void CalculateNccDimensions(int xDistBetweenEyes)
        {
            float heightSearchMultipler = 1f;
            float widthSearchMultiplier = 1f;

            heightSearchMultipler = 1.5f;
            widthSearchMultiplier = 2.5f;

            nccTemplateWidth = (int)(xDistBetweenEyes * XEyeDistToNccTemplateWidthRatio);

            if (nccTemplateWidth % 2 == 0)
            {
                ++nccTemplateWidth;
            }

            nccTemplateHeight = (int)(xDistBetweenEyes * XEyeDistToNccTemplateHeightRatio);

            if (nccTemplateHeight % 2 == 0)
            {
                ++nccTemplateHeight;
            }

            nccSearchAreaHeight = (int)(xDistBetweenEyes * XEyeDistToSearchHeightRatio * heightSearchMultipler);

            if (nccSearchAreaHeight % 2 == 0)
            {
                ++nccSearchAreaHeight;
            }

            nccSearchAreaWidth = (int)(xDistBetweenEyes * XEyeDistToSearchWidthRatio * widthSearchMultiplier);

            if (nccSearchAreaWidth % 2 == 0)
            {
                ++nccSearchAreaWidth;
            }

            findingTemplateNccSearchAreaWidth = (int)(xDistBetweenEyes * XEyeDistToSearchWidthRatio);

            if (findingTemplateNccSearchAreaWidth % 2 == 0)
            {
                ++findingTemplateNccSearchAreaWidth;
            }

            findingTemplateNccSearchAreaHeight = (int)(xDistBetweenEyes * XEyeDistToSearchHeightRatio);

            if (findingTemplateNccSearchAreaHeight % 2 == 0)
            {
                ++findingTemplateNccSearchAreaHeight;
            }


            halfNccTemplateWidth    = (nccTemplateWidth - 1) / 2;
            halfNccTemplateHeight   = (nccTemplateHeight - 1) / 2;
            halfNccSearchAreaHeight = (nccSearchAreaHeight - 1) / 2;
            halfNccSearchAreaWdith  = (nccSearchAreaWidth - 1) / 2;
            halfFindingTemplateNccSearchAreaHeight = (findingTemplateNccSearchAreaHeight - 1) / 2;
            halfFindingTemplateNccSearchAreaWidth  = (findingTemplateNccSearchAreaWidth - 1) / 2;

            int xSteps = nccSearchAreaWidth / stepAmount;
            int ySteps = nccSearchAreaHeight / stepAmount;

            if (nccSearchAreaWidth % stepAmount != 0)
            {
                xSteps++;
            }

            if (nccSearchAreaHeight % stepAmount != 0)
            {
                ySteps++;
            }

            initialSearchTemplates = new FastBitmap.NccTemplate[xSteps * ySteps];

            for (int i = 0; i < initialSearchTemplates.Length; ++i)
            {
                initialSearchTemplates[i] = new FastBitmap.NccTemplate(nccTemplateWidth, nccTemplateHeight);
            }

            int refinedSearchWidth = (2 * stepAmount) - 1;

            refinedSearchTemplates = new FastBitmap.NccTemplate[refinedSearchWidth * refinedSearchWidth];

            for (int i = 0; i < refinedSearchTemplates.Length; ++i)
            {
                refinedSearchTemplates[i] = new FastBitmap.NccTemplate(nccTemplateWidth, nccTemplateHeight);
            }



            initialSearchintensityMapWidth  = nccTemplateWidth + nccSearchAreaWidth;
            initialSearchintensityMapHeight = nccTemplateHeight + nccSearchAreaHeight;
            initialSearchIntensityMap       = new float[initialSearchintensityMapWidth, initialSearchintensityMapHeight];
        }