/// <summary>
        /// Creates template from the input image by using provided parameters.
        /// </summary>
        /// <param name="orientation">Orientation image.</param>
        /// <param name="maxNumberOfFeatures">Maximum number of features per template. The features will be extracted so that their locations are semi-uniformly spread.</param>
        /// <param name="classLabel">Template class label.</param>
        /// <param name="featureImportanceFunc">Function which returns feature's strength.</param>
        public void Initialize(Gray <int>[,] orientation, int maxNumberOfFeatures, string classLabel, Func <Feature, int> featureImportanceFunc = null)
        {
            maxNumberOfFeatures   = System.Math.Max(0, System.Math.Min(maxNumberOfFeatures, GlobalParameters.MAX_NUM_OF_FEATURES));
            featureImportanceFunc = (featureImportanceFunc != null) ? featureImportanceFunc: (feature) => 0;

            Gray <byte>[,] importantQuantizedOrient = FeatureMap.Calculate(orientation, 0);
            List <Feature> features = ExtractTemplate(importantQuantizedOrient, maxNumberOfFeatures, featureImportanceFunc);

            BoundingRect = GetBoundingRectangle(features);
            //if (boundingRect.X == 1 && boundingRect.Y  == 1 && boundingRect.Width == 18)
            //    Console.WriteLine();

            for (int i = 0; i < features.Count; i++)
            {
                features[i].X -= BoundingRect.X;
                features[i].Y -= BoundingRect.Y;

                //if(features[i].X < 0 || features[i].Y < 0)
                //    Console.WriteLine();

                //PATCH!!!
                features[i].X = System.Math.Max(0, features[i].X);
                features[i].Y = System.Math.Max(0, features[i].Y);
            }


            this.Features   = features.ToArray();
            this.Size       = BoundingRect.Size;
            this.ClassLabel = classLabel;
        }
        private Image <Gray <byte> >[][,] calculate(Gray <int>[,] orientationDegImg)
        {
            var linearMaps = new Image <Gray <byte> > [GlobalParameters.NUM_OF_QUNATIZED_ORIENTATIONS][, ];

            Gray <byte>[,] sprededQuantizedOrient = FeatureMap.Calculate(orientationDegImg, this.NeigborhoodSize);
            for (int orient = 0; orient < GlobalParameters.NUM_OF_QUNATIZED_ORIENTATIONS; orient++)
            {
                var responseMap = computeResponseMap(sprededQuantizedOrient, orient);
                linearMaps[orient] = linearizeResponseMap(responseMap);
                //responseMap.Save("C:/RM_" + orient + ".bmp");
            }

            return(linearMaps);
        }
        private Image <Gray, Byte>[][,] calculate(Image <Gray, int> orientationDegImg)
        {
            Image <Gray, Byte>[][,] linearMaps = new Image <Gray, byte> [GlobalParameters.NUM_OF_QUNATIZED_ORIENTATIONS][, ];

            using (Image <Gray, Byte> sprededQuantizedOrient = FeatureMap.Calculate(orientationDegImg, this.NeigborhoodSize))
            {
                for (int orient = 0; orient < GlobalParameters.NUM_OF_QUNATIZED_ORIENTATIONS; orient++)
                {
                    using (var responseMap = computeResponseMap(sprededQuantizedOrient, orient))
                    {
                        linearMaps[orient] = linearizeResponseMap(responseMap);
                        //responseMap.Save("C:/RM_" + orient + ".bmp");
                    }
                }
            }

            return(linearMaps);
        }