public static double CalculateAngle(Descriptor first, Descriptor second)
 {
     return(Math.Acos(Math.Round(Descriptor.InnearMultiplication(first, second) / (first.Norm * second.Norm), 15)));
 }
        public void CreateDescriptors()
        {
            this.descriptors = new List <Descriptor>();

            for (int k = this.keypoints.Count - 1; k >= 0; k--)
            {
                int t = this.keypoints[k].ExtermaIndex;

                int scale = (int)extermas[t].ScaleLevel;

                int blure = (int)extermas[t].BlureLevel;

                int index = GetImageIndex(scale, blure);

                int row = (int)extermas[t].Row;

                int column = (int)extermas[t].Column;

                double rotationAngle = keypoints[k].Orientation;

                Matrix neighbour = GeometricEnhancement.GetImagePortion(this.scaleSpace[index], row, column, 9, rotationAngle);

                //Matrix angle = new Matrix(17, 17);

                List <double>[,] histogram = new List <double> [4, 4];

                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        histogram[i, j] = new List <double>(new double[8]);
                    }
                }

                double sigma = 16 * 0.5;

                double sigma2 = sigma * sigma;

                //

                for (int i = row - 8; i < row + 8; i++)
                {
                    for (int j = column - 8; j < column + 8; j++)
                    {
                        int xPrime = j - column; int yPrime = i - row;

                        double magnitude = CalculateMagnitude(neighbour, j - (column - 8) + 1, (i - (row - 8)) + 1);

                        double tempAngle = CalculateAngle(neighbour, j - (column - 8) + 1, (i - (row - 8)) + 1) - rotationAngle;


                        double angle = tempAngle >= 0 ? tempAngle : 2 * Math.PI + tempAngle;

                        //
                        double angleD    = angle * 180 / Math.PI;
                        double rotationD = rotationAngle * 180 / Math.PI;

                        int temp = (int)Math.Floor(angle / (Math.PI / 4)) % 8; //8 bin

                        int tempI = (int)(Math.Floor((i - row + 8) / 4.0));

                        int tempJ = (int)(Math.Floor((j - column + 8) / 4.0));

                        histogram[tempI, tempJ][temp] += magnitude * 1 / (2 * Math.PI * sigma2) * Math.Exp(-(xPrime * xPrime + yPrime * yPrime) / (2 * sigma2));
                    }
                }

                List <double> tempResult = new List <double>();

                foreach (List <double> item in histogram)
                {
                    tempResult.AddRange(item.ToArray());
                }

                Descriptor descriptor = new Descriptor(this.extermas[t], this.keypoints[k], tempResult.ToArray());

                if (descriptor.Norm != 0)
                {
                    this.descriptors.Add(descriptor);
                }
                else
                {
                    this.keypoints.RemoveAt(k);

                    //this.extermas.Remove(k);
                }
                //this.descriptors.Add();
            }
        }