书名:OpenCV计算机视觉编程攻略(第3版)
作者:[加]罗伯特·拉戈尼尔
译者:相银初
出版社:人民邮电出版社
出版时间:2018-05
ISBN:9787115480934
霍夫变换的目的是在二值图像中找出全部直线,并且这些直线必须穿过足够多的像素点。
它的处理方法是,检查输入的二值分布图中每个独立的像素点,识别出穿过该像素点的所有可能直线。
如果同一条直线穿过很多像素点,就说明这条直线明显到足以被认定。
为了统计某条直线被标识的次数,霍夫变换使用了一个二维累加器。
累加器的大小依据(ρ, θ)的步长确定,其中(ρ, θ)参数用来表示一条直线。
为了说明霍夫变换的功能,我们建立一个180×200的矩阵(对应θ的步长为π/180, ρ的步长为1):
// 创建霍夫累加器
// 这里的图像类型为uchar;实际使用时应该用int
cv::Mat acc(200,180, CV_8U, cv::Scalar(0));
// 选取一个像素点
int x=50, y=30;
// 循环遍历所有角度
for (int i=0; i<180; i++) {
double theta= i*PI/180.;
// 找到对应的rho值
double rho= x*std::cos(theta)+y*std::sin(theta);
// j对应-100~100 的rho
int j= static_cast<int>(rho+100.5);
std::cout << i << ", " << j << std::endl;
// 增值累加器
acc.at<uchar>(j, i)++;
}
每次计算得到(ρ, θ)对后,其对应的累加器入口的数值就会增加,表示对应的直线穿过了图像中的某个像素点(或者说每个像素点为一批候选直线投票)。
如果把累加器作为图像显示(翻转过来,并乘以100,以便数字1能显示),结果如下所示。
上面的曲线表示穿过这个点的所有直线的集合。现在用像素点(30, 10)重复上述过程,得到的累加器如下所示。
可以看到,这两条曲线在一个位置相交,这个位置表示对应的直线通过了这两个像素点。累加器的对应入口收到了两次投票,表明有两个像素点在这条直线上。
如果对二值分布图中的所有像素点重复上述过程,那么同一条直线上的像素点会使累加器的同一个入口增长很多次。
最后,为了检测图像中的直线(即像素点对齐的位置),只需要标识出累加器中的局部限值,该累加器用于接收大量投票数。
cv::HoughLines函数的最后一个参数表示最低投票数,只有不低于这个数的直线才会被检测到。这表明最低投票数越小,检测到的直线数量就越多。
如果把例子中的数值降为50,检测到的直线就如下图所示。