Пример #1
0
 /// <summary>
 ///  used to test ridge detection using structure tensor.
 /// </summary>
 public static void Test2StructureTensor()
 {
     // create a local image matrix
     double[,] image =
     {
         {
             0.1, 0.1, 0.1, 10.1, 0.1, 0.1, 0.1,
         },
         {
             0.1, 0.1, 0.1, 10.0, 0.1, 0.1, 0.1,
         },
         {
             0.1, 0.1, 0.1, 9.5, 0.1, 0.1, 0.1,
         },
         {
             0.1, 0.1, 0.1, 10.0, 0.1, 0.1, 0.1,
         },
         {
             0.1, 0.1, 0.1, 9.9, 0.1, 0.1, 0.1,
         },
         {
             0.1, 0.1, 0.1, 10.0, 0.1, 0.1, 0.1,
         },
         {
             0.1, 0.1, 0.1, 10.2, 0.1, 0.1, 0.1,
         },
     };
     RidgeTensorResult result = RidgeDetection_VerticalDirection(image);
 }
Пример #2
0
        public static RidgeTensorResult RidgeDetection_VerticalDirection(double[,] M)
        {
            // 0,1,2,3 indicate directions East, North, West, South respectively of the position (x,y).
            //The following variables are required to obtain the local gradient.
            double dx0, dy1, dx2, dy3;

            //The following variables are required to construct the structure tensor.
            double dxdx0, dydy1, dxdx2, dydy3, dydx0, dydx2;

            int rowCount  = M.GetLength(0);
            int colCount  = M.GetLength(1);
            int halfwidth = colCount / 2;

            //accumulate info in the positive direction
            //var avMatrixValues = new double[2, 2];
            var avStructTensor = new double[2, 2];

            //var window = new double[2, 2];

            //search for ridge in central vertical cells
            int N = 0;

            dx0   = 0.0;
            dy1   = 0.0;
            dx2   = 0.0;
            dy3   = 0.0;
            dxdx0 = 0.0;
            dydy1 = 0.0;
            dxdx2 = 0.0;
            dydy3 = 0.0;
            dydx0 = 0.0;
            dydx2 = 0.0;

            //avoid the edge rows
            for (int r = 1; r < rowCount - 1; r++)
            {
                // calculate gradients in four directions
                dx0 += M[r, halfwidth + 1] - M[r, halfwidth];
                dy1 += M[r - 1, halfwidth] - M[r, halfwidth];
                dx2 += M[r, halfwidth - 1] - M[r, halfwidth];
                dy3 += M[r + 1, halfwidth] - M[r, halfwidth];

                // accumulate structure tensor components
                dxdx0 += dx0 * dx0;
                dydy1 += dy1 * dy1;
                dxdx2 += dx2 * dx2;
                dydy3 += dy3 * dy3;
                dydx0 += dx0 * dy1;
                dydx2 += dx2 * dy3;

                // count number of contributing cells so can get average
                N++;
            }

            // get average
            dx0   /= N;
            dy1   /= N;
            dx2   /= N;
            dy3   /= N;
            dxdx0 /= N;
            dydy1 /= N;
            dxdx2 /= N;
            dydy3 /= N;
            dydx0 /= N;
            dydx2 /= N;

            double[,] stM1 =
            {
                {
                    dxdx0, dydx0,
                },
                {
                    dydx0, dydy1,
                },
            };
            double[] eigenvalues1 = CalculateEigenValues(stM1);
            double[,] stM2 =
            {
                {
                    dxdx2, dydx2,
                },
                {
                    dydx2, dydy3,
                },
            };
            double[] eigenvalues2 = CalculateEigenValues(stM2);

            double ridgeMagnitude = (dx0 + dx2) / 2;

            if (dx0 < 3.0 || dx2 < 3.0)
            {
                ridgeMagnitude = 0.0;
            }

            //accumulate results
            RidgeTensorResult result = new RidgeTensorResult();

            // this magnitude is equivalent to Sobel calculation over three columns
            result.AvMagnitude = ridgeMagnitude;
            double eigenDominance1 = Math.Abs((eigenvalues1[0] - eigenvalues1[1]) / (eigenvalues1[0] + eigenvalues1[1]));
            double eigenDominance2 = Math.Abs((eigenvalues2[0] - eigenvalues2[1]) / (eigenvalues2[0] + eigenvalues2[1]));

            result.AvDominance = (eigenDominance1 + eigenDominance2) / 2;

            double radiansE = Math.Atan2(dy1, dx0);
            double radiansW = Math.Atan2(dy3, dx2);
            double degrees1 = radiansE * (180 / Math.PI);
            double degrees2 = radiansW * (180 / Math.PI);

            result.AvRadians           = (radiansE + radiansW) / 2;
            result.DirectionDifference = radiansE - radiansW;
            result.DirectionIndecision = result.DirectionDifference / (radiansE + radiansW);

            // ridge direction is at right angles to the slope direction. Add 90 degrees.
            double piDiv2 = Math.PI / 2;

            result.RidgeDirection = result.AvRadians + piDiv2;

            // correct if slope > 90 degrees or < 90 degrees.
            if (result.RidgeDirection < -piDiv2)
            {
                result.RidgeDirection += Math.PI;
            }

            if (result.RidgeDirection > piDiv2)
            {
                result.RidgeDirection -= Math.PI;
            }

            //calculate boundaries in degrees = easier!!
            double category1Boundary = 22.5;
            double category2Boundary = category1Boundary * 3;

            //double category3Boundary = category1Boundary * 5;
            //double category4Boundary = category1Boundary * 7;

            double ridgeAngle = result.RidgeDirection * (180 / Math.PI);

            //double angle = (Math.PI / (double)8) * (180 / Math.PI);
            result.RidgeDirectionCategory = 0;
            if (ridgeAngle >= -category1Boundary && ridgeAngle <= category1Boundary)
            {
                result.RidgeDirectionCategory = 1;
            }
            else
            if (ridgeAngle <= category2Boundary && ridgeAngle > category1Boundary)
            {
                result.RidgeDirectionCategory = 2;
            }
            else
            if (ridgeAngle < -category1Boundary && ridgeAngle > -category2Boundary)
            {
                result.RidgeDirectionCategory = 3;
            }
            else
            if (ridgeAngle > category2Boundary && ridgeAngle < piDiv2)
            {
                result.RidgeDirectionCategory = 4;
            }
            else
            if (ridgeAngle <= -category2Boundary && ridgeAngle > -piDiv2)
            {
                result.RidgeDirectionCategory = 4;
            }

            //over-ride direction for vertical
            result.RidgeDirectionCategory = 4;
            return(result);
        }