霍夫线变换

霍夫线变换是一种在图像中寻找直线的方法。OpenCV中支持三种霍夫线变换,分别是标准霍夫线变换、多尺度霍夫线变换、累计概率霍夫线变换。

在OpenCV中可以调用函数HoughLines来调用标准霍夫线变换和多尺度霍夫线变换。HoughLinesP函数用于调用累积概率霍夫线变换。

我们都知道,二维坐标轴上表示一条直线的方程式y = a*x + b,我们想求出一条直线就得想方设法求出其中的a和b的值。如果用极坐标来表示就是

opencv3计算曲线拐点 opencv求直线交点_Desktop

theta就是直线与水平线所成的角度,而rho就是圆的半径(也可以理解为原点到直线的距离),同样地,这两个参数也是表征一条直线的重要参数,确定他们俩了,也就确定一条直线了。正如下图所示。

opencv3计算曲线拐点 opencv求直线交点_opencv3计算曲线拐点_02

在OpenCV里,我们只需调用HoughLines就是可以得到表征一条直线的这两个参数值!

标准hough变换:
Imgproc.HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn, double min_theta, double max_theta)
参数说明:
image:源图像
lines:hough变换后储存检测到的线条的输出矢量
rho:以像素为单位的距离精度
theta:以弧度为单位的角度精度
threshold:识别某部分为一条直线时必须达到的值
srn:rho参数的除数距离,有默认值0
stn:theta参数的除数距离,默认值0
min_theta:检测到的直线的最小角度
max_theta:检测到的直线的最大角度

HoughLines代码

public static void main(String[] args) {
        System.load("F:\\opencv\\x64\\opencv_java401.dll");

        Mat src = Imgcodecs.imread("C:\\Users\\beawan\\Desktop\\test\\test.jpg");
        Mat canny = new Mat();
        Imgproc.Canny(src, canny, 50, 200, 3);
        Mat storage = new Mat();
        //这里注意第五个参数,表示阈值,阈值越大,表明检测的越精准,速度越快,得到的直线越少(得到的直线都是很有把握的直线)
        //这里得到的lines是包含rho和theta的,而不包括直线上的点,所以下面需要根据得到的rho和theta来建立一条直线
        Imgproc.HoughLines(canny, storage, 1, Math.PI / 180, 150, 0, 0, 0, 10);
        for (int x = 0; x < storage.rows(); x++) {
            double[] vec = storage.get(x, 0);

            double rho = vec[0]; //就是圆的半径r
            double theta = vec[1]; //就是直线的角度

            Point pt1 = new Point();
            Point pt2 = new Point();

            double a = Math.cos(theta);
            double b = Math.sin(theta);

            double x0 = a * rho;
            double y0 = b * rho;

            int lineLength = 1000;

            pt1.x = Math.round(x0 + lineLength * (-b));
            pt1.y = Math.round(y0 + lineLength * (a));
            pt2.x = Math.round(x0 - lineLength * (-b));
            pt2.y = Math.round(y0 - lineLength * (a));

            if (theta >= 0) {
                Imgproc.line(src, pt1, pt2, new Scalar(255, 0, 0), 1, Imgproc.LINE_4, 0);
            }
        }
        Imgcodecs.imwrite("C:\\Users\\beawan\\Desktop\\test\\houghLines.jpg", src);
    }

图片

opencv3计算曲线拐点 opencv求直线交点_Desktop_03


直线

opencv3计算曲线拐点 opencv求直线交点_hough变换_04

累计概率hough变换:
Imgproc.HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap)
参数说明:
image:源图像
lines:hough变换后储存检测到的线条的输出矢量
rho:以像素为单位的距离精度
theta:以弧度为单位的角度精度
threshold:识别某部分为一条直线时必须达到的值
minLineLength:最低线段的长度,默认为0
maxLineGap:允许将同一行点与点之间连接起来的最大的距离,默认为0

public static void main(String[] args) {
        System.load("F:\\opencv\\x64\\opencv_java401.dll");

        Mat src = Imgcodecs.imread("C:\\Users\\beawan\\Desktop\\test\\test.jpg");
        Mat canny = new Mat();
        Imgproc.Canny(src, canny, 50, 200, 3);
        Mat storage = new Mat();
        Imgproc.HoughLinesP(canny, storage, 1, Math.PI / 180, 200, 0, 0);

        for (int x = 0; x < storage.rows(); x++) {
            double[] vec = storage.get(x, 0);
            double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
            Point start = new Point(x1, y1);
            Point end = new Point(x2, y2);
            Imgproc.line(src, start, end, new Scalar(255, 0, 0), 5, Imgproc.LINE_4, 0);
        }

        Imgcodecs.imwrite("C:\\Users\\beawan\\Desktop\\test\\houghLinesP.jpg", src);
    }

直线

opencv3计算曲线拐点 opencv求直线交点_Math_05