引言:
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。霍夫变换于1962年由Paul Hough 首次提出[53],后于1972年由Richard Duda和Peter Hart推广使用[54],经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆.
霍夫线变化:
1.霍夫线变换是一种用来寻找直线的方法.
2.霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像
实现:
众所周知, 一条直线在图像二维空间可由两个变量表示. 例如:
在 笛卡尔坐标系: 可由参数: 斜率k 和截距b表示.
在 极坐标系: 可由参数: 极径r 和极角
表示.
在笛卡标系在1.在笛卡尔坐标系中,该直线可以表示为:
对于霍夫变换,我们利用极坐标来表示该直线,因此,该直线的表达式可为:
化简得:
2.一般来说,对于点 ,我们可以将通过这个点的一族直线统一定义为:这就意味着,每一对(
,r) 代表一条通过点的直线。
3.如果对于一个给定点
我们在极坐标对极径极角平面绘出所有通过它的直线, 将得到一条正弦曲线.:
4.我们可以对图像中所有的点进行上述操作. 如果两个不同点进行上述操作后得到的曲线在平面
- 相交, 这就意味着它们通过同一条直线.
5.这意味着一般来说, 一条直线能够通过在平面
- 寻找交于一点的曲线数量来 检测. 越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成. 一般来说我们可以通过设置直线上点的 阈值 来定义多少条曲线交于一点我们才认为 检测 到了一条直线. 6.这就是霍夫线变换要做的. 它追踪图像中每个点对应曲线间的交点. 如果交于一点的曲线的数量超过了 阈值, 那么可以认为这个交点所代表的参数对 在原图像中为一条直线。
API:
InputArray src, // 输入图像,必须8-bit的灰度图像
OutputArray lines, // 输出的极坐标来表示直线
double rho, // 生成极坐标时候的像素扫描步长
double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180
int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线
double minLineLength=0;// 最小直线长度
double maxLineGap=0;// 最大间隔
霍夫直线检测:
代码实例:
#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("F:\\visual studio\\Image\\building.jpg");
if (src.empty())
{
cout << "Can't load the image" << endl;
return -1;
}
imshow("src", src);
Mat blursrc;
GaussianBlur(src, blursrc, Size(5, 5), 0, 0);
//Canny边缘检测 会将源图像转化为单通道8bit 边缘二值图像
Mat edge;
Canny(blursrc, edge, 50, 150, 3, false);
imshow("edge", edge);
Mat coloredge;
//因此后期要画出带有颜色的直线,所以先转化为BGR
cvtColor(edge, coloredge, COLOR_GRAY2BGR);
//HoughLinesP仍需要使用8bit 单通道 二值图像
vector<Vec4f> lines; //用于保存直线2个端点的坐标
HoughLinesP(edge, lines, 1, CV_PI / 180,80, 30, 10);
//画出直线
for (int i = 0; i < lines.size() ;i++)
{
Vec4f a_line = lines[i];
line(coloredge, Point(a_line[0], a_line[1]), Point(a_line[2], a_line[3]), Scalar(255, 0, 0), 2, LINE_AA);
}
imshow("line", coloredge);
waitKey(0);
}
效果展示: