Hough line transformation.

The class implements Hough line transformation, which allows to detect straight lines in an image. Lines, which are found by the class, are provided in polar coordinates system - lines' distances from image's center and lines' slopes are provided. The pole of polar coordinates system is put into processing image's center and the polar axis is directed to the right from the pole. Lines' slope is measured in degrees and is actually represented by angle between polar axis and line's radius (normal going from pole to the line), which is measured in counter-clockwise direction.

Found lines may have negative radius. This means, that the line resides in lower part of the polar coordinates system and its HoughLine.Theta value should be increased by 180 degrees and radius should be made positive.

The class accepts binary images for processing, which are represented by 8 bpp grayscale images. All black pixels (0 pixel's value) are treated as background, but pixels with different value are treated as lines' pixels.

See also documentation to HoughLine class for additional information about Hough Lines.

Sample usage:

HoughLineTransformation lineTransform = new HoughLineTransformation( ); // apply Hough line transofrm lineTransform.ProcessImage( sourceImage ); Bitmap houghLineImage = lineTransform.ToBitmap( ); // get lines using relative intensity HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity( 0.5 ); foreach ( HoughLine line in lines ) { // ... }

Initial image:

Hough line transformation image:

        //1. bright pixel / dark pixel
        //2.lowest gray level
        //3.highest gray level
        //4.number of peaks in the x direction.
        //5.number of peaks in the y direction.
        public static double[] ExtractFeatures(Bitmap bmp,int i)
        {
            //Apply GrayScale
            GrayscaleBT709 greyScaleFilter = new GrayscaleBT709();
            Bitmap newBmp = greyScaleFilter.Apply((Bitmap)bmp.Clone());

            //Count Blobs
            BlobCounter blobCounter = new BlobCounter();
            blobCounter.BackgroundThreshold = Color.FromArgb(255, 150, 150, 150);
            blobCounter.ProcessImage(newBmp);
            int blobs = (blobCounter.ObjectsCount - 1) * 30;

            //Count Corner
            SusanCornersDetector scd = new SusanCornersDetector();
            scd.DifferenceThreshold = 70;
            scd.GeometricalThreshold = 8;
            int corners = scd.ProcessImage((Bitmap)newBmp.Clone()).Count();

            //Apply Edge Filter
            CannyEdgeDetector filter = new CannyEdgeDetector();
            //newBmp = filter.Apply(newBmp);
            Histogram his = new HorizontalIntensityStatistics(newBmp).Gray;
            Histogram vis = new VerticalIntensityStatistics(newBmp).Gray;

            HoughLineTransformation lineTransform = new HoughLineTransformation();
            // apply Hough line transofrm
            lineTransform.ProcessImage(filter.Apply(newBmp));
            Bitmap houghLineImage = lineTransform.ToBitmap();
            // get lines using relative intensity
            HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(1);
            int linesCount = lines.Count() * 30;

            double[] features = new double[13] { blobs, corners, his.Max, his.Min, his.Mean, his.Median, his.StdDev,
                vis.Max, vis.Min, vis.Mean, vis.Median, vis.StdDev,linesCount};

            //double[] features = new double[3] { blobs, corners,lines};

            newBmp.Save(String.Format("test{0}.bmp",i));
            return features;
        }
Example #2
0
        //Finds the degree tilt of the part using Hough Line Detection
        //Reference Documentation for Method:http://www.aforgenet.com/framework/docs/html/6141703e-d685-efb5-2f7f-b430aa42210f.htm
        public double findDegreeTilt(Bitmap inImage)
        {
            //Creating HoughLineTranformation object
            AForge.Imaging.HoughLineTransformation lineTransform = new AForge.Imaging.HoughLineTransformation();
            //Adjusts the number of decimal places of the returned angle (Reference Documentation:http://www.aforgenet.com/framework/docs/html/24be38e1-20d8-214e-7adb-31a61854e839.htm)
            lineTransform.StepsPerDegree = 10;
            //Applys filter on image
            lineTransform.ProcessImage(inImage);
            //Creating a temporary bitmap to apply graphics to(Grpahics doesn't accept canny images)
            Bitmap   tempBitmap = new Bitmap(inImage.Width, inImage.Height);
            Graphics g          = Graphics.FromImage(tempBitmap);

            //Redrawing original image on temporary image
            g.DrawImage(inImage, 0, 0);
            Pen bluePen = new Pen(Color.Blue, 2.0f);

            //Stores all Hough lines found with the filter
            //.8 repersents the intensity constant(higher the constant the less lines the filter picks up)
            AForge.Imaging.HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(.8);
            double averageAngle = 0;

            //Converts each Hough line found to cartesian coordinates and draw each one
            foreach (AForge.Imaging.HoughLine line in lines)
            {
                //Stores the radius and theta and polar line
                int    lineRadius = line.Radius;
                double lineTheta  = line.Theta;
                //Negative radii are made positive
                if (lineRadius < 0)
                {
                    lineTheta += 180;
                    lineRadius = -lineRadius;
                }
                //Converting line theta from degrees to radians
                lineTheta = (lineTheta / 180) * Math.PI;

                //Image center coordinates
                double centerX = inImage.Width / 2.0;
                double centerY = inImage.Height / 2.0;

                //Initialization of hough line coordinates
                double firstX = 0, lastX = 0, firstY = 0, lastY = 0;

                //Creating line coordinates
                if (line.Theta != 0)
                {
                    firstX = -centerX;
                    lastX  = centerX;

                    firstY = (-Math.Cos(lineTheta) * firstX + lineRadius) / Math.Sin(lineTheta);
                    lastY  = (-Math.Cos(lineTheta) * lastX + lineRadius) / Math.Sin(lineTheta);
                }
                else
                {
                    firstX = line.Radius;
                    lastX  = line.Radius;

                    firstY = centerY;
                    lastY  = -centerY;
                }

                //Adjusting lineTheta angle to be in a range from 0 to 90 degrees
                double partRotationAngle = 90.0 - (double)(lines[0].Theta);
                if (partRotationAngle < 0)
                {
                    partRotationAngle += 90;
                }
                //Treat the angle of 90 the same as 0
                if (partRotationAngle == 90)
                {
                    partRotationAngle = 0;
                }
                //Adding the returned angles to average result later on
                averageAngle += partRotationAngle;
                //Draws cartesian line repersenting polar hough line
                g.DrawLine(bluePen, new System.Drawing.Point((int)(firstX + centerX), (int)(centerY - firstY)), new System.Drawing.Point((int)(lastX + centerX), (int)(centerY - lastY)));
            }
            //Calculate the average degree of tilt to improve consistancy
            averageAngle /= (double)lines.Length;
            //Set the label to display rotation angle
            offsetAngle.Text = averageAngle.ToString();
            //If wanted by the user, the hough lines will be displayed in they canny image panel
            if (houghLineCheckBox.Checked)
            {
                cannyImagePanel.Image = tempBitmap;
            }
            //Returns the avearge offset angle
            return(averageAngle);
        }
Example #3
0
        private bool GetIntersect(Bitmap grayImage, Bitmap bitmap, int[, ,] intersectPoint)
        {
            HoughLineTransformation lineTransform = new HoughLineTransformation();
            lineTransform.ProcessImage(grayImage);
            Bitmap houghLineImage = lineTransform.ToBitmap();
            // get lines using relative intensity
            HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(0.5);

            BitmapData bitmapData = bitmap.LockBits(
               new Rectangle(0, 0, bitmap.Width, bitmap.Height),
               ImageLockMode.ReadWrite, bitmap.PixelFormat);
            BitmapData grayImageData = grayImage.LockBits(
               new Rectangle(0, 0, grayImage.Width, grayImage.Height),
               ImageLockMode.ReadWrite, grayImage.PixelFormat);
            UnmanagedImage unmanagedImage = new UnmanagedImage(bitmapData);

            int w2 = 0, h2 = 0;
            Color color = Color.Black;
            int[] mVer = new int[19];
            double[] mHor = new double[19];
            double[] cVer = new double[19];
            double[] cHor = new double[19];
            int verCount = 0;
            int horCount = 0;

            foreach (HoughLine line in lines)
            {

                String temp = line.Theta.ToString();
                // get line's radius and theta values
                int r = line.Radius;
                double t = line.Theta;

                // check if line is in lower part of the image
                if (r < 0)
                {
                    t += 180;
                    r = -r;
                }

                // convert degrees to radians
                t = (t / 180) * Math.PI;

                // get image centers (all coordinate are measured relative
                // to center)
                w2 = grayImage.Width / 2;
                h2 = grayImage.Height / 2;

                double x0 = 0, x1 = 0, y0 = 0, y1 = 0;

                if (line.Theta != 0)
                {
                    // vertical line
                    if (line.Theta > 0 && line.Theta < 10 || line.Theta > 170)
                    {
                        if (verCount == 19)
                        {
                            bitmap.UnlockBits(bitmapData);
                            grayImage.UnlockBits(grayImageData);
                            return false;

                        }
                        y0 = -h2;
                        y1 = h2;
                        x0 = (r - (Math.Sin(t) * y0)) / Math.Cos(t);
                        x1 = (r - (Math.Sin(t) * y1)) / Math.Cos(t);

                        color = Color.Red;

                        x0 = w2 + (int)x0;
                        x1 = w2 + (int)x1;
                        y0 = (h2 - y0);
                        y1 = (h2 - y1);

                        //mVer[verCount] = (int) -(Math.Cos(t)/Math.Sin(t));
                        //cVer[verCount] = (double)r*(1/Math.Sin(t));

                        if ((int)x0 == (int)x1)
                        {
                            mVer[verCount] = (int)((y1 - y0) / (x1 - x0 + 1));
                            cVer[verCount] = y0 - (mVer[verCount] * x0);
                        }
                        else
                        {
                            mVer[verCount] = (int)((y1 - y0) / (x1 - x0));
                            cVer[verCount] = (y0 - (mVer[verCount] * x0));
                        }
                        Drawing.Line(bitmapData,
                        new IntPoint((int)x0, (int)y0),
                        new IntPoint((int)x1 ,(int)y1),
                        color);
                        Drawing.Line(grayImageData,
                        new IntPoint((int)x0 , (int)y0),
                        new IntPoint((int)x1 , (int)y1),
                        color);

                        verCount++;
                    }

                    // horizontal
                    if (line.Theta > 80 && line.Theta < 100)
                    {
                        if (horCount == 19)
                        {
                            bitmap.UnlockBits(bitmapData);
                            grayImage.UnlockBits(grayImageData);
                            return false;

                        }

                        x0 = -w2; // most left point
                        x1 = w2;  // most right point6

                        y0 = (-Math.Cos(t) * x0 + r) / Math.Sin(t);
                        y1 = (-Math.Cos(t) * x1 + r) / Math.Sin(t);

                        x0 = x0 + w2;
                        x1 = x1 + w2;
                        y0 = (int)(h2 - (int)y0);
                        y1 = (int)(h2 - (int)y1);

                        //mHor[horCount] = (int)-(Math.Cos(t) / Math.Sin(t));
                        //cHor[horCount] = (double)r * (1 / Math.Sin(t));
                        if (y0 - (mHor[horCount] * x0) < 10 || y0 - (mHor[horCount] * x0) > bitmap.Height - 10)
                            continue;
                        mHor[horCount] = ((y1 - y0) / (x1 - x0));
                        cHor[horCount] = y0 - (mHor[horCount] * x0);
                        horCount++;

                        Drawing.Line(bitmapData,
                        new IntPoint((int)x0,(int)y0),
                        new IntPoint((int)x1, (int)y1),
                        Color.Blue);
                        Drawing.Line(grayImageData,
                         new IntPoint((int)x0, (int)y0),
                         new IntPoint((int)x1, (int)y1),
                         Color.Blue);
                    }
                }
                else
                {
                    if (verCount == 19)
                    {
                        bitmap.UnlockBits(bitmapData);
                        grayImage.UnlockBits(grayImageData);
                        return false;

                    }
                    // vertical line
                    x0 = line.Radius;
                    x1 = line.Radius;
                    y0 = h2;
                    y1 = -h2;

                    color = Color.Yellow;

                    x0 = x0 + w2;
                    x1 = x1 + w2;
                    y0 = (h2 - (int)y0);
                    y1 = (h2 - (int)y1);

                    //mVer[verCount] = (int)-(Math.Cos(t) / Math.Sin(t));
                    //cVer[verCount] = (double)r * (1 / Math.Sin(t));

                    if (x0 < 10 || x0 > bitmap.Width - 10)
                        continue;
                    mVer[verCount] = (int)((y1 - y0) / (x1 - x0 + 1));
                    cVer[verCount] = y0 - (mVer[verCount] * x0);

                    Drawing.Line(bitmapData,
                    new IntPoint((int)x0, (int)y0),
                    new IntPoint((int)x1, (int)y1),
                    color);
                    Drawing.Line(grayImageData,
                     new IntPoint((int)x0, (int)y0),
                     new IntPoint((int)x1, (int)y1),
                     color);
                    //MessageBox.Show("y0 = " + y0 + " y1 = " + y1 + " x0 = " + x0 + " x1 = " + x1 +
                    //       " m = " + mVer[verCount] + " c = " + cVer[verCount], "ok", MessageBoxButtons.OK);
                    verCount++;

                }
            }

            int m = 0;
            int n = 0;
            if (horCount == 19 && verCount == 19)
            {
                for (int i = 0; i < 19; i++)
                {
                    for (int j = 0; j < 19; j++)
                    {

                        intersectPoint[0, i, j] = (int)((cHor[j] - cVer[i]) / (mVer[i] - mHor[j]));
                        intersectPoint[1, i, j] = (int)((mHor[j] * intersectPoint[0, i, j]) + cHor[j]);
                        Debug.WriteLine(intersectPoint[0, i, j] + " " + intersectPoint[1, i, j] + " " + cHor[j] + " " + mHor[j]);
                    }
                }
                bitmap.UnlockBits(bitmapData);
                grayImage.UnlockBits(grayImageData);
                return true;
            }
            else {
                bitmap.UnlockBits(bitmapData);
                grayImage.UnlockBits(grayImageData);
                return false;
            }

            //int num = 0;
            //MessageBox.Show("num = " + num + " mv =" + mVer[num] + "," + " cv = " + cVer[num] + " mh =" + mHor[num] + "," + " ch = " + cHor[num] + "," + "x = "
            //    + intersectPoint[0, num, num] + "y = " + intersectPoint[1, num, num], "ok", MessageBoxButtons.OK);

            //MessageBox.Show(mVer[18] + "," + cVer[18] + "," + intersectPoint[0, 18, 18], "ok", MessageBoxButtons.OK);
            //MessageBox.Show(intersectPoint. + "", "ok", MessageBoxButtons.OK);
        }
Example #4
0
        // Process image
        private void ProcessImage( Bitmap bitmap )
        {
            Grayscale grayscaleFilter = new Grayscale(0.33, 0.33, 0.34);
            // apply the filter
            Bitmap grayImage = grayscaleFilter.Apply(bitmap);

            //Get Histogram
            /*int[] histogram = new int[256];
            for (int i = 0; i < 256; i++) {
                histogram[i] = 0;
            }
            for (int i = 0; i < grayImage.Width; i++ )
            {
                for (int j = 0; j < grayImage.Height; j++) {
                    histogram[(Convert.ToInt32(grayImage.GetPixel(i, j).R.ToString()) + Convert.ToInt32(grayImage.GetPixel(i, j).G.ToString()) +
                        Convert.ToInt32(grayImage.GetPixel(i, j).B.ToString()))/3] +=1;
                }
            }*/

            //create filter
            SobelEdgeDetector sobelFilter = new SobelEdgeDetector();
            // apply the filter
            sobelFilter.ApplyInPlace(grayImage);
            Threshold filter = new Threshold(243);
            // apply the filter
            filter.ApplyInPlace(grayImage);

            HoughLineTransformation lineTransform = new HoughLineTransformation();

            lineTransform.ProcessImage(grayImage);
            Bitmap houghLineImage = lineTransform.ToBitmap();
            // get lines using relative intensity
            HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(0.5);

            BitmapData bitmapData = bitmap.LockBits(
               new Rectangle(0, 0, bitmap.Width, bitmap.Height),
               ImageLockMode.ReadWrite, bitmap.PixelFormat);
            BitmapData grayImageData = grayImage.LockBits(
               new Rectangle(0, 0, grayImage.Width, grayImage.Height),
               ImageLockMode.ReadWrite, grayImage.PixelFormat);
            UnmanagedImage unmanagedImage = new UnmanagedImage(bitmapData);

            int w2 = 0, h2 = 0;
            int vertical = 0;
            int horizons = 0;

            int testColor = 0;
            Color color = Color.Black;

            foreach (HoughLine line in lines)
            {

                String temp = line.Theta.ToString();
                //MessageBox.Show(temp, "ok", MessageBoxButtons.OK);
                // get line's radius and theta values
                int r = line.Radius;
                double t = line.Theta;

                // check if line is in lower part of the image
                if (r < 0)
                {
                    t += 180;
                    r = -r;
                }

                // convert degrees to radians
                t = (t / 180) * Math.PI;

                // get image centers (all coordinate are measured relative
                // to center)
                w2 = grayImage.Width / 2;
                h2 = grayImage.Height / 2;

                double x0 = 0, x1 = 0, y0 = 0, y1 = 0;

                if (line.Theta != 0)
                {
                    // horizontal
                    // none-vertical line

                    if (line.Theta > 0 && line.Theta < 10 || line.Theta > 170)
                    {
                        x0 = -w2; // most left point
                        x1 = w2;  // most right point

                        y0 = (-Math.Cos(t) * x0 + r) / Math.Sin(t);
                        y1 = (-Math.Cos(t) * x1 + r) / Math.Sin(t);

                        color = Color.Red;

                        Drawing.Line(bitmapData,
                        new IntPoint((int)x0 + w2, h2 - (int)y0),
                        new IntPoint((int)x1 + w2, h2 - (int)y1),
                        color);
                        Drawing.Line(grayImageData,
                         new IntPoint((int)x0 + w2, h2 - (int)y0),
                         new IntPoint((int)x1 + w2, h2 - (int)y1),
                         color);
                    }

                    if (line.Theta > 80 && line.Theta < 100)
                    {
                        x0 = -w2; // most left point
                        x1 = w2;  // most right point

                        y0 = (-Math.Cos(t) * x0 + r) / Math.Sin(t);
                        y1 = (-Math.Cos(t) * x1 + r) / Math.Sin(t);

                        Drawing.Line(bitmapData,
                        new IntPoint((int)x0 + w2, h2 - (int)y0),
                        new IntPoint((int)x1 + w2, h2 - (int)y1),
                        Color.Blue);
                        Drawing.Line(grayImageData,
                         new IntPoint((int)x0 + w2, h2 - (int)y0),
                         new IntPoint((int)x1 + w2, h2 - (int)y1),
                         Color.Blue);
                    }

                }
                else
                {
                    // vertical line
                    x0 = line.Radius;
                    x1 = line.Radius;
                    y0 = h2;
                    y1 = -h2;

                    color = Color.Red;

                    Drawing.Line(bitmapData,
                    new IntPoint((int)x0 + w2, h2 - (int)y0),
                    new IntPoint((int)x1 + w2, h2 - (int)y1),
                    color);
                    Drawing.Line(grayImageData,
                     new IntPoint((int)x0 + w2, h2 - (int)y0),
                     new IntPoint((int)x1 + w2, h2 - (int)y1),
                     color);
                }
            }

            bitmap.UnlockBits(bitmapData);
            grayImage.UnlockBits(grayImageData);
            MessageBox.Show(lines.Length+"", "ok", MessageBoxButtons.OK);
            // put new image to clipboard

            Clipboard.SetDataObject(bitmap);
            // and to picture box
            pictureBox.Image = bitmap;

            UpdatePictureBoxPosition();
        }
Example #5
0
        /// <summary>
        /// Apply - search for broken bones - by finding lines and detecting angles between them
        /// </summary>
        /// <param name="bmp">Bitmap - original</param>
        /// <returns>Bitmap - processed</returns>
        public Bitmap Apply(Bitmap bmp)
        {
            System.Drawing.Imaging.PixelFormat pf = bmp.PixelFormat;
            ROI = bmp.Rectangle();
            var lineTransform = new AForge.Imaging.HoughLineTransformation();

            lineTransform.MinLineIntensity = 60;
            lineTransform.LocalPeakRadius  = 15;
            //lineTransform.StepsPerDegree = 10;
            //lineTransform.LocalPeakRadius = 10;
            // apply Hough line transofrm
            lineTransform.ProcessImage(bmp);
            Bitmap houghLineImage = lineTransform.ToBitmap();
            // get lines using relative intensity
            var lines = lineTransform.GetLinesByRelativeIntensity(0.5);

            lines = filterLinesByTheta(lines);


            Dilatation dl = new Dilatation();

            dl.ApplyInPlace(bmp);

            Invert filter = new Invert();

            filter.ApplyInPlace(bmp);

            bmp = bmp.Bit8ToBit24();

            foreach (var line in lines)
            {
                // get line's radius and theta values
                int    radius             = line.Radius;
                double lineSlopeInDegrees = line.Theta;

                // check if line is in lower part of the image
                if (radius < 0)
                {
                    lineSlopeInDegrees += 180;
                    radius              = -radius;
                }

                var radians = lineSlopeInDegrees.DegreesToRadians();

                var imageCenter = bmp.GetCenter();

                double x0 = 0,  //most left point
                       y0 = 0,
                       x1 = 0,  //most right point
                       y1 = 0;

                if (line.Theta != 0)
                {
                    // none-vertical line
                    x0 = -imageCenter.X; // most left point
                    x1 = imageCenter.X;  // most right point

                    // calculate corresponding y values
                    y0 = (-radians.Cosinus() * x0 + radius) / radians.Sinus();
                    y1 = (-radians.Cosinus() * x1 + radius) / radians.Sinus();
                }
                else
                {
                    // vertical line
                    x0 = line.Radius;
                    x1 = line.Radius;

                    y0 = imageCenter.Y;
                    y1 = -imageCenter.Y;
                }

                var line2 = new Line(
                    (int)x0 + imageCenter.X, imageCenter.Y - (int)y0,
                    (int)x1 + imageCenter.X, imageCenter.Y - (int)y1);
                line2.X1 = (int)x0 + imageCenter.X;
                line2.Y1 = imageCenter.Y - (int)y0;
                line2.X2 = (int)x1 + imageCenter.X;
                line2.Y2 = imageCenter.Y - (int)y1;
                Lines.Add(line2);
            }
            return(drawLines(bmp));
        }