1.基本概念
(1)Hough Line Transform用来做直线检测,前提是已经完成边缘检测(最常用的就是canny检测)。
(2)数学计算概念:平面空间到极坐标空间转换
x,y为像素坐标,该公式的演变如下:
因此可以通过像素坐标,再加上的变化,可以得出极坐标的图像,一个像素坐标对应极坐标系的一条曲线。详细如下:
多个曲线在一点重合,说明这几点存在相同的r和theta,所以换成平面坐标系就是一条直线,说明在这个角度方向上,这几个像素在一条直线,反推可以做出直线。
2.实现步骤和API
(1)边缘检测(canny)
(2)使用霍夫变换直线概率 cv::HoughLinesP最终输出是直线的两个点(x0,y0,x1,y1)
(3)霍夫变换直线概率 cv::HoughLinesP介绍:
cv::HoughLinesP(InputArray src, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0,double maxLineGap=0)
参数1 src:边缘检测的输出图像
参数2 lines:两个端点的坐标
参数3 rho:参数极径 以像素值为单位的分辨率
参数4 theta:参数极角 以弧度为单位的分辨率
参数5 threshold:只有获得足够交点的极坐标点才被看成是直线
参数6 minLineLength:组成直线,最小点数量
参数7 minLineGap:最大间隔
3.代码实现
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
char inputName[] = "input name";
char outputName[] = "output name";
int main()
{
Mat src, dst,srcGray;
src = imread("D:/VS project/Image/vertical.png");
if (src.empty())
{
cout << "找不到图像" << endl;
return -1;
}
namedWindow(inputName, CV_WINDOW_AUTOSIZE);
imshow(inputName, src);
namedWindow(outputName, CV_WINDOW_AUTOSIZE);
//先边缘检测
Canny(src,srcGray,100,200,3);
//转回有颜色的
cvtColor(srcGray, dst, COLOR_GRAY2BGR);
vector<Vec4f>plines;//数组
HoughLinesP(srcGray, plines, 1, CV_PI / 180, 10, 0, 0);//输出2个点(x0,y0,x1,y1)
Scalar color = Scalar(255, 0, 0);
for (size_t i = 0; i < plines.size(); i++)//size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数
{
Vec4f hline = plines[i];
line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, 8);
}
imshow(outputName, dst);
waitKey(0);
return 0;
}