/// <summary>
        /// Подсчитывает среднеквадратичное отклонение по каждому компоненту RGB.
        /// </summary>
        /// <param name="image">Матрица первого изображения</param>
        /// <param name="imageStart">Левая верхняя сопоставляемая точка в матрице image</param>
        /// <param name="template">Матрица сопоставляемого шаблона</param>
        /// <param name="reservedColor">Точки этого цвета в шаблоне не учитываются</param>
        public static SimpleColor CalculateDifference(SimpleColor[][] image, Point imageStart, 
			SimpleColor[][] template, SimpleColor reservedColor)
        {
            int red = 0, green = 0, blue = 0;
            int uncounted = 0;
            int width = template.GetLength(0);
            int height = template[0].GetLength(0);

            for (int dx = 0; dx < width; ++dx)
                for (int dy = 0; dy < height; ++dy)
                {
                    var templateColor = template[dx][dy];

                    if (reservedColor == templateColor)
                    {
                        ++uncounted;
                        continue;
                    }

                    var imageColor = image[imageStart.X + dx][imageStart.Y + dy];

                    var dR = imageColor.R - templateColor.R;
                    var dG = imageColor.G - templateColor.G;
                    var dB = imageColor.B - templateColor.B;

                    red += dR * dR;
                    green += dG * dG;
                    blue += dB * dB;
                }

            var totalPoints = width * height - uncounted;
            return GetResultSimpleColor(red, green, blue, totalPoints);
        }
        /// <summary>
        /// Searches for potential positions of template
        /// </summary>
        private IEnumerable<Point> GetSmallPicturePositions(SimpleColor[][] source)
        {
            int maxX = source.GetLength(0) - template.GetLength(0);
            int maxY = source[0].GetLength(0) - template[0].GetLength(0);
            var verticals = new List<Point>[maxX];

            Parallel.For(0, maxX, x =>
                {
                    verticals[x] = new List<Point>();
                    for (int y = 0; y < maxY; ++y)
                    {
                        if (ImageComparer.Equals(
                            source,
                            new Point(x + smallPictureRegion.Left, y + smallPictureRegion.Top),
                            smallPictureTemplate,
                            reservedColor,
                            smallPictureMaxDifference))
                        {
                            verticals[x].Add(new Point(x, y));
                        }
                    }
                });

            for (int x = 0; x < maxX; ++x)
                foreach (var p in verticals[x])
                    yield return p;
        }
 private static void CheckSize(SimpleColor[][] template)
 {
     if (template.GetLength(0) < smallTemplateWidth || template[0].GetLength(0) < smallTemplateHeight)
         throw new ArgumentException(
             string.Format("To small size of template. Required at least: width = {0}, height = {1}",
                 smallTemplateWidth, smallTemplateHeight));
 }