} // Done

        /// <summary>
        /// Определяет степень сходства двух заданных объектов.
        /// </summary>
        /// <param name="features1">Совокупность реперных характеристик одного из сравниваемых объектов.</param>
        /// <param name="features2">Совокупность реперных характеристик другого сравниваемого объекта.</param>
        /// <returns>Степень сходства заданных объектов.</returns>
        public virtual Affinity Detect(IEnumerable <T> features1, IEnumerable <T> features2)
        {
            if (CorrelationMatrix == null)
            {
                throw new AssertException("Отсутствует матрица корреляций, т.к. не был вызван метод Init базового класса детектора сходства.");
            }
            if (AffinityBlockBuilder == null)
            {
                throw new AffinityDetectorException("В свойстве AffinityBlockBuilder не задан метод разбиения реперных характеристик сравниваемых объектов на устойчивые блоки реперных характеристик.");
            }
            if (AffinityBlockCorrelator == null)
            {
                throw new AffinityDetectorException("В свойстве AffinityBlockCorrelator не задан метод определения степени корреляции между устойчивыми блоками реперных характеристик сравниваемых объектов.");
            }
            AffinityBlocks1 = AffinityBlockBuilder(features1);
            AffinityBlocks2 = AffinityBlockBuilder(features2);
            int    size        = 0;
            int    diffs       = 0;
            double reliability = 0;

            while (AffinityBlocks1.MoveNext() && AffinityBlocks2.MoveNext())
            {
                Correlation correlation = AffinityBlockCorrelatorInvoke(AffinityBlocks1.Current, AffinityBlocks2.Current);
                if (correlation.Importance > 0.5)
                {
                    // Учитываем только значимые блоки и пропускаем малозначительные, например, относящиеся к фону.
                    if (correlation.Value > 0.5)
                    {
                        // Соответствующие устойчивые блоки реперных характеристик коррелируют между собой.
                        reliability = reliability + correlation.Value;
                    }
                    else
                    {
                        // Соответствующие устойчивые блоки реперных характеристик не коррелируют между собой.
                        diffs++;
                    }
                    size++;
                }
            }
            if (size == diffs)
            {
                // Сравниваемые объекты гарантированно не похожи между собой.
                reliability      = 1;
                DetectedAffinity = new Affinity(0, reliability);
            }
            else
            {
                // Сравниваемые объекты имеют некоторое сходство по своим реперным характеристикам.
                reliability = reliability / (size - diffs);
                double affinity = 1 - (double)diffs / (double)size;
                DetectedAffinity = new Affinity(affinity, reliability);
            }
            return(DetectedAffinity);
        } // Detect
        } // GetPixelValue

        /// <summary>
        /// Дефолтовая реализация определения степени корреляции между устойчивыми блоками реперных характеристик, каждый из которых соответствует одному пикселю.
        /// Корреляция определяется по совпадению цветов пикселей:
        ///   0 - цвета соответствующих пикселей не совпадают,
        ///   1 - цвета соответствующих пикселей совпадают.
        /// </summary>
        /// <param name="affinityBlock1">Один из блоков реперных характеристик (пиксель), между которыми определяется степень корреляции.</param>
        /// <param name="affinityBlock2">Второй из блоков реперных характеристик (пиксель), между которыми определяется степень корреляции.</param>
        /// <returns>Степень корреляции между блоками реперных характеристик (пикселями).</returns>
        protected virtual Correlation DefaultAffinityBlockCorrelator(IAffinityBlock affinityBlock1, IAffinityBlock affinityBlock2)
        {
            Correlation result;
            Int32       color1 = (Int32)affinityBlock1.Value;
            Int32       color2 = (Int32)affinityBlock2.Value;

            if (color1 == color2)
            {
                result = new Correlation(1, 1);
            }
            else
            {
                result = new Correlation(0, 1);
            }
            return(result);
        } // DefaultAffinityBlockCorrelator