C++ opencv概率霍夫变换(HoughLinesP)直线检测

本文介绍了使用C++和OpenCV进行直线检测的方法,重点讲解了霍夫线变换,包括标准霍夫变换和概率霍夫线变换。其中,概率霍夫线变换(HoughLinesP)在效率上更优,可直接输出线段的端点坐标。通过实例展示了如何在道路和车辆图像中应用概率霍夫变换进行直线检测。
摘要由CSDN通过智能技术生成

霍夫线变换

  1. 霍夫线变换是一种用于检测直线的变换。
  2. 为了应用变换,首先需要进行边缘检测预处理。

标准和概率霍夫线变换

OpenCV 实现了两种霍夫线变换:

标准霍夫变换

HoughLines()

void cv::HoughLines	(	InputArray	image,
	OutputArray	lines,
	double 	rho,
	double 	theta,
	int 	threshold,
	double 	srn = 0,
	double 	stn = 0,
	double 	min_theta = 0,
	double 	max_theta = CV_PI 
)

#include <opencv2/imgproc.hpp>

参数

image8 位、单通道二进制源图像。该函数可以修改图像。
lines线的输出向量。每条线由一个 2 或 3 元素向量表示( ρ , θ )或者( ρ , θ ,票数).ρ是到坐标原点的距离( 0 , 0 )(图像的左上角)。θ是以弧度为单位的线旋转角度(0 ∼垂直线, π/ 2∼水平线)。选票是累加器的值。
rho累加器的距离分辨率(以像素为单位)。
theta累加器的角度分辨率(以弧度为单位)。
threshold累加器阈值参数。仅返回那些获得足够票数的线(>门槛)。
srn对于多尺度霍夫变换,它是距离分辨率 rho 的除数。粗略的累加器距离分辨率为 rho ,准确的累加器分辨率为 rho/srn 。如果 srn=0 和 stn=0 ,则使用经典的霍夫变换。否则,这两个参数都应该是正数。
stn对于多尺度霍夫变换,它是距离分辨率 theta 的一个除数。
min_theta对于标准和多尺度霍夫变换,检查线的最小角度。必须介于 0 和 max_theta 之间。
max_theta对于标准和多尺度霍夫变换,检查线的最大角度。必须介于 min_theta 和 CV_PI 之间。

例子:

样本/cpp/tutorial_code/ImgTrans/houghlines.cpp

概率霍夫线变换

  • 霍夫线变换的更有效实现。它将检测到的线的极值作为输出(x0,y0,x1,y1)
  • 在 OpenCV 中,它是用函数HoughLinesP()实现的

HoughLinesP()

void cv::HoughLinesP	(	InputArray	image,
	OutputArray	lines,
	double 	rho,
	double 	theta,
	int 	threshold,
	double 	minLineLength = 0,
	double 	maxLineGap = 0 
	)	

参数

image8 位、单通道二进制源图像。该函数可以修改图像。
lines线的输出向量。每条线由一个 4 元素向量表示(X1,是的1,X2,是的2), 在哪里(X1,是的1)和(X2,是的2)是每个检测到的线段的终点。
rho累加器的距离分辨率(以像素为单位)。
theta累加器的角度分辨率(以弧度为单位)。
threshold累加器阈值参数。仅返回那些获得足够票数的线(>门槛)。
minLineLength最小线长。比这短的线段被拒绝。
maxLineGap同一条线上的点之间连接它们的最大允许间隙。

也可以看看

线段检测器

例子:

样本/cpp/tutorial_code/ImgTrans/houghlines.cpp

应用示例

目的:检测图片里道路和车的直线。

使用方法:mask掩膜,概率霍夫线变换。

实现过程:读取图片 转灰度图像 高斯降噪 边缘检测 掩膜 概率霍夫变换 保存图片

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <iostream>
#include <fstream>


using namespace std;
using namespace cv;

// MASK THE EDGE IMAGE
/**
*@brief Mask the image so that only the edges that form part of the lane are detected
*@param img_edges is the edges image 
*@return Binary image with only the desired edges being represented
*/
/*道路轮廓*/
Mat mask1(Mat img_edges) {
    Mat output;
    Mat mask = cv::Mat::zeros(img_edges.size(), img_edges.type());
    Point pts[4] = {
        Point(650, 500),
        Point(850, 500),
        Point(450, 800),
        Point(250, 800),
};
    // Create a binary polygon mask
    fillConvexPoly(mask, pts, 4, cv::Scalar(255, 0, 0));
    // Multiply the edges image and the mask to get the output
    bitwise_and(img_edges, mask, output);

    return output;
}

/*前面车辆的车身边缘的候选轮廓*/
Mat mask2(Mat img_edges) {
    Mat output;
    Mat mask = cv::Mat::zeros(img_edges.size(), img_edges.type());
    Point pts[4] = {
        Point(720, 250),
        Point(1300, 250),
        Point(1350, 830),
        Point(650, 830),
    };
    fillConvexPoly(mask, pts, 4, cv::Scalar(255, 0, 0));
    bitwise_and(img_edges, mask, output);

    return output;
}

int main()
{
    Mat image;
    Mat grayImage;
    Mat cannyImage;
    Mat img_mask1;
    Mat img_mask2;
    image = imread("C:\\Users\\10985\\source\\repos\\CVDemo01\\test02_original\\440.png");
    if (!image.data) {
         cout << "Image reading error !" << endl;
    }

    //将图像转换为灰度图
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    //高斯降噪
    GaussianBlur(grayImage, grayImage, Size(3, 3),0, 0, BORDER_DEFAULT);

    //边缘检测
    Canny(grayImage, cannyImage, 50, 150, 3, false);
    
    // Mask the image so that we only get the ROI
    /*道路轮廓*/
    img_mask1 = mask1(cannyImage);
    /*前面车辆的车身边缘的候选轮廓*/
    img_mask2 = mask2(cannyImage);

    /*Mat oneline(cannyImage.size(), CV_8U, Scalar(0));*/
    /* 将Hough变换应用于轮廓图像*/
    vector<Vec4f> lines1;
    HoughLinesP(img_mask1, lines1, 1, 1, 10, 40, 20);
    for (int j = 0; j < lines1.size(); j++)
    {
         Vec4f hline = lines1[j];
		 line(image, Point(hline[0], hline[1]), Point(hline[2], hline[3]), Scalar(0, 255, 0), 2);
    }

    vector<Vec4f> lines2;
    HoughLinesP(img_mask2, lines2, 1, 1, 10, 10, 40);
    for (int j = 0; j < lines2.size(); j++)
    {
        Vec4f hline = lines2[j];
        /*选择接近于垂直/水平的部分 
         - 前面车辆的车身边缘的候选人.*/
        if ((hline[1] - hline[3]) <= 1 & (hline[1] - hline[3]) >= -1 || (hline[0] - hline[2]) <= 1 & (hline[0] - hline[2]) >= -1) {
            line(image, Point(hline[0], hline[1]), Point(hline[2], hline[3]), Scalar(255, 0, 0), 2);
        }
    }

    //保存 
    stringstream str2;
    str2 << "C:/Users/10985/source/repos/CVDemo01/04_houghTest/" << "result.png";
    imwrite(str2.str(), image);

    return 0;
}

读取的原图

结果图片 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值