霍夫变换是一种特征检测(feature extraction),被广泛应用在图像分析(image
analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。
霍夫变换是用来辨别找出物件中的特征,其流程大致如下:
给定一个物件、要辨别的形状的种类,算法会在参数空间(parameter space)中执行投票来决定物体的形状,而这是由累加空间(accumulator space)里的局部最大值(local maximum)来决定。
1.霍夫直线变换:在图像中寻找直线
2.霍夫圆变换:在图像中寻找圆。
如何知道被检测的是一条直线?
首先将图像转换为极坐标系
极坐标中点的坐标由θ和r进行表征
即
根据上面的公式,我们能够推导出如下公式:
推导过程可以如下:
公式有什么作用?
例如
对于上面这条直线,有如下五个点是在直线上的:
所以我们可以得到五条直线:
如果我们以θ为横坐标,r为纵坐标,当我们把这五条直线画在同一个坐标系中,我们能得到下面这幅图:
我们发现,这五条直线交于同一点,这就是直线有的特点,我们就通过这个特点,将所有的直线累加,那交点处因为是所有直线的累加,其像素值一定是最高的,我们知道,像素越高,在图像上越亮,当达到255的时候,是最亮,即为白色。所以我们可以通过这种方式来检测到直线。
有这样的一张图像,对应的极坐标图像如下
白色的点就是直线交汇的地方
用极坐标反推即可得推测出直线的位置
此API最终输出的是极坐标中的坐标,也就是(θ,r)
最终结果反算回去还需要一定的难度,于是opencv中有HoughLinesP
这里介绍HoughLines
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
);
(1)InputArray类型的src ,8位,单通道二进制源图像(灰度图像)。
(2)OutputArray类型的lines,直线的输出向量。每一直线都由一个双元素向量表示。rho是距坐标原点的距离(0,0)(图像左上角)。theta是以弧度为单位的线旋转角度。
(3)double类型的rho,累加器的距离分辨率(像素),一般取1
(4)double类型的theta,累加器的角度分辨率(弧度),一般取值CV_PI/180,每次一度。
(5)int类型的threshold,累加器阈值参数。只返回获得足够累加器数量的直线,一般取10,10个像素点算一个直线,如果直线足够长可以换成100。
(6)double类型的srn,对于多尺度Hough变换,它是距离分辨率rho的除数,粗累加器距离分辨率为rho,精确累加器分辨率为rho/srn。如果srn=0和stn=0,则使用经典Hough变换。否则,这两个参数都应为正。如果不用多尺度霍夫变换则设为0
(7)double类型的sth,对于多尺度Hough变换,它是距离分辨率θ的除数。如果不用多尺度霍夫变换则设为0
(8)double类型的min_theta,用于标准和多尺度Hough变换,检查直线的最小角度。必须介于0和maxθ之间。
(9)double类型的max_theta,用于标准和多尺度Hough变换,用于检查线条的最大角度。必须介于最小θ和CVπ之间。
此函数返回的直接是坐标
建议使用这个API
HoughLines(
InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength = 0,
double maxLineGap = 0
);
(1)InputArray类型的src ,8位,单通道二进制源图像(灰度图)。
(2)OutputArray类型的lines,直线的输出向量。每一直线都由一个双元素向量表示。rho是距坐标原点的距离(0,0)(图像左上角)。theta是以弧度为单位的线旋转角度。
(3)double类型的rho,累加器的距离分辨率(像素)一般取1
(4)double类型的theta,累加器的角度分辨率(弧度)一般取值CV_PI/180,每次一度。
(5)int类型的threshold,累加器阈值参数。只返回获得足够累加器数量的直线。一般取10,10个像素点算一个直线,如果直线足够长可以换成100。
(6)double类型的minLineLength,最小直线长度。小于该值的线段将被拒绝。
(7)double类型的maxLineGap,同一行上的点之间链接它们所允许的最大间距。
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src, src_gray, dst;
src = imread("C:/Users/86176/Pictures/pics/lines.jpg");
if (!src.data)
{
cout << "could not load image !";
return -1;
}
imshow("【输入图像】", src);
GaussianBlur(src, src, Size(3, 3), 0, 0);
Canny(src, src_gray, 0, 255);
cvtColor(src_gray, dst, CV_GRAY2BGR);
imshow("【获取边缘】", src_gray);
vector<Vec4f> plines;
HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 100, 0, 10);
Scalar color = Scalar(0, 0, 255);
for (size_t i = 0; i < plines.size(); i++) {
Vec4f hline = plines[i];
line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
}
imshow("【输出图像】", dst);
waitKey(0);
return 0;
}