OpenCV霍夫变换(Hough Transform)直线检测详解

2020-01-06 20:16:34王振洲

OpenCV,霍夫变换,直线检测

概率Hough变换检测线段:

霍夫变换检测直线的目的,是找到二值图像中经过足够多数量点的所有直线,当同一直线穿过许多点,便意味着这条线的存在足够明显。

概率霍夫变换在原算法的基础上增加了一些改动,主要是:

1. 不再系统地逐行扫描图像,而是随机挑选(轮廓图像的)前景点,一旦累加器中的某一项交点的票数达到给定的最小值,就搜索轮廓图像在对应直线上的前景点,连成线段(要小于maxLineGap),然后记录线段参数(起终点),最后删除所有经过的点(即使它们并未投过票)。

2. 概率霍夫变换定义了两个额外的参数:一个是可以接受的最小线段长度(minLineLength),另一个是允许组成连续线段的最大像素间隔(maxLineGap),虽然额外步骤增加了算法的复杂度,但由于参与投票的点数有所减少,因此得到了一些补偿。

openCV中的概率霍夫变换直线检测函数 cv::HoughLinesP:

函数的输出是cv::Vec4i组成的向量,每个元素是检测到的线段的两个坐标点(pt1x, pt1y, pt2x, pt2y)。


#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
 
#define PI 3.1415926 
 
class LineFinder{
private:
 std::vector<cv::Vec4i> lines;
 double deltaRho; // 步长(theta表示与直线垂直的角度)
 double deltaTheta;
 int minVote;  // 判断是直线的最小投票数 
 double minLength; // 判断是直线的最小线段长度 
 double maxGap; // 允许组成连续线段的最大像素间隔
public:
 LineFinder() {
 deltaRho = 1;
 deltaTheta = PI / 180;
 minVote = 10;
 minLength = 0.0;
 maxGap = 0.0;
 }
 void setAccResolution(double dRho, double dTheta) {
 deltaRho = dRho;
 deltaTheta = dTheta;
 }
 void setMinVote(int minv) {
 minVote = minv;
 }
 void setLineLengthAndGap(double length, double gap) {
 minLength = length;
 maxGap = gap;
 }
 
 // Hough变换检测线段
 void findLines(cv::Mat& binary) {
 lines.clear();
 cv::HoughLinesP(binary, lines, deltaRho, deltaTheta, minVote, minLength, maxGap);
 }
 
 void drawDetectedLines(cv::Mat &image, cv::Scalar color = cv::Scalar(255)) {
 std::vector<cv::Vec4i>::const_iterator it2 = lines.begin();
 while (it2 != lines.end()) {
 cv::Point pt1((*it2)[0], (*it2)[1]);
 cv::Point pt2((*it2)[2], (*it2)[3]);
 cv::line(image, pt1, pt2, color, 1.5); //画线段
 ++it2;
 }
 }
};
 
int main(int argc, char *argv[])
{
 cv::Mat image = cv::imread("D:/VS_exercise/images/road1.jpg");
 cv::Mat imageGray;
 cv::Mat contours;
 cv::cvtColor(image, imageGray, cv::COLOR_RGB2GRAY);
 // 边缘检测
 cv::Canny(imageGray, contours, 190, 300);
 // Hough变换检测
 LineFinder finder;
 finder.setMinVote(80);
 finder.setLineLengthAndGap(100, 10); //概率Hough变换增加的两个参数
 finder.findLines(contours);
 finder.drawDetectedLines(image);
 
 // 显示
 cv::imshow("Detected Lines with Hough", image);
 cv::waitKey(0);
 return 0;
}