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;
                        }
                    }
                }
            }
        }