« 上一篇下一篇 »

c# OpenCvSharp HoughLinesP 霍夫变换直线检测

using OpenCvSharp;

using OpenCvSharp.Extensions;

using DlibDotNet;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.Threading;


namespace app

{

    public partial class FrmMain : Form

    {

        public FrmMain()

        {

            InitializeComponent();

        }


        /// <summary>

        /// 直线检测

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void btnHoughLinesP_Click(object sender, EventArgs e)

        {

            // 加载图像

            Mat src = Cv2.ImRead(@"img\bianxing1.png");

            Cv2.ImShow("原图", src);


            // 灰度处理

            Mat grayMat = new Mat();

            Cv2.CvtColor(src, grayMat, ColorConversionCodes.BGR2GRAY);

            Cv2.ImShow("灰度处理", grayMat);


            // 模糊处理 降低噪音

            Mat blurMat = new Mat();

            Cv2.GaussianBlur(grayMat, blurMat, new OpenCvSharp.Size(3, 3), 9, 9);

            Cv2.ImShow("高斯滤波", blurMat);


            // 二值处理

            Mat binaryMat = new Mat();

            Cv2.Threshold(blurMat, binaryMat, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);

            Cv2.ImShow("二值处理", binaryMat);


            // 形态学操作

            // 闭运算

            // 先膨胀后腐蚀。能够排除小黑点。

            Mat morphMat = new Mat();

            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(9, 9), new OpenCvSharp.Point(-1, -1));

            Cv2.MorphologyEx(binaryMat, morphMat, MorphTypes.Close, kernel, new OpenCvSharp.Point(-1, -1), 3);

            Cv2.ImShow("形态学操作", morphMat);

            

            // 按位运算

            // opencv非运算不是1变0,0变1。而是 !x = 255 - x

            Cv2.BitwiseNot(morphMat, morphMat, new Mat());

            Cv2.ImShow("按位运算 BitwiseNot", morphMat);


            // 轮廓发现

            OpenCvSharp.Point[][] contours;

            HierarchyIndex[] hierarchy;

            Cv2.FindContours(morphMat, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());


            // 轮廓绘制

            int width = src.Cols;

            int height = src.Rows;

            Mat drawImg = Mat.Zeros(src.Size(), MatType.CV_8UC3);

            for (int i = 0; i < contours.Length; i++)

            {

                Rect rect = Cv2.BoundingRect(contours[i]);

                // 过滤

                if (rect.Width > width / 4 && rect.Width < width - 10)

                {

                    Cv2.DrawContours(drawImg, contours, i, new Scalar(0, 0, 255), 2, LineTypes.Link8, hierarchy);

                }

            }

            Cv2.ImShow("轮廓", drawImg);


            // 灰度转换

            Mat contoursImg = new Mat();

            int accu = Math.Min(width / 2, height / 2);

            Cv2.CvtColor(drawImg, contoursImg, ColorConversionCodes.BGR2GRAY);


            // 霍夫变换直线检测

            // 参数说明

            /*

            image:输入图像。8 bit 灰度图。

            lines:存储线段极坐标的容器,每一条线由具有四个元素的矢量(x_1, y_1, x_2, y_2) 表示,其中(x_1, y_1)和(x_2, y_2) 是每个检测到的线段的结束点。

            rho:生成极坐标的像素扫描步长。

            theta:生成极坐标的角度步长,一般是π / 180。

            threshold:要“检测” 一条直线所需最少的的曲线交点。

            minLineLength:默认值 0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。

            maxLineGap:默认值 0,允许将同一行点与点之间连接起来的最大的距离。

            */

            LineSegmentPoint[] lines = Cv2.HoughLinesP(contoursImg, 1, Math.PI / 180.0, accu / 5, accu / 5);

            Mat linesImg = Mat.Zeros(src.Size(), MatType.CV_8UC3);

            for (int i = 0; i < lines.Length; i++)

            {

                Cv2.Line(linesImg, lines[i].P1, lines[i].P2, new Scalar(0, 255, 0), 1, LineTypes.Link8);

            }

            Cv2.ImShow("霍夫变换直线检测", linesImg);

        }

    }

}