霍夫变换
霍夫变换是图像处理中的一种特征提取技术,可以识别图像中的几何形状。它将图像空间中的特征点映射到参数空间进行投影,通过检测累计结果的局部极值点得到一个符号某特定形状的点的集合。经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。它的抗噪声、抗形变能力较强。另一种直线提取的方法是对图像边缘点进行链码追踪,在得到的链码串中提取直线。
霍夫变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。
霍夫变换原理
- 在直线中检测直线的问题,实质就是找到构成直线的所有的像素点,那么问题就是从找到直线,变成找到符合的所有的点的问题。
- 进行坐标系变换变成。这样表示过点的直线束。
- x-y空间的直线上每一点在坐标系中都可以表示为经过点的直线。找到所有点的问题,转变成寻找直线的问题。
- 对于图像上的每一点,在k-b坐标系中对应着很多的直线。找到直线的交点,就对应着找到图像中的直线。
OpenCV中的霍夫直线检测
OpenCV霍夫检测直线常用的方法是将平面中任一条直线用类似于极坐标方式表示:
其中:p: 表示直角坐标系中原点到直线的距离(垂直距离),θ: 表示x轴与p的夹角, 图像平面上的一个点就对应到ρ-θ平面上的一条曲线上。
如果对位于同一直线上的n个点进行变换,原图像空间的n个点在参数空间对应得到有n条正弦曲线,并且这些曲线相交于一点。
- Hough变换在算法设计上步骤如下:
- 在ρ,θ合适的最大值与最小值之间建立一个离散的参数空间。
- 将参数空间(ρ,θ) 量化成m*n(m为ρ的等份数,n为θ的等份数)个单元,并设置累加器矩阵。
- 给参数空间的每一个单元分配一个累加器Q(i,j),并把累加器的初始值设置为0。
- 对图像边界上的每一个点(x,y)带入ρ=xcosθ+ysinθ,求得每个θ对应的ρ值。
- 在参数空间中,找到ρ和θ所对应的单元,并将该单元的累加器加1,即:Q(i,j)=Q(i,j)+1。
- 当直角坐标系中的所有点都经过4和5两步遍历后,检验参数空间中每个累加器的值,累加器最大的单元所对应的ρ和θ即为直角坐标系中直线方程的参数。
当直角坐标系中的点分布在 R 条直线附近时,可在第 5 步检测累加器时,取出累加器中前 R 个值最大的单元所对应的ρk和θk(k=1,2,…,R ),以ρk和θk为直角坐标系中直线方程式ρ=xcosθ+ysinθ的参数,即可同时实现多条直线的检测。
OpenCV中的API
opencv支持两种不同的霍夫变换:标准霍夫变换(SHT)和累积概率霍夫变换(PPHT)。
1. HoughLines
- 说明 使用标准霍夫转换方式检测二值图像中的直线。函数实现标准或者标准的多尺度霍夫变换算法检测。
- 声明
void 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
);
- 参数
image | 8位的单通道的二值图像。 |
lines | 输出的直线向量。每条线由2-3个向量元素 or 表示。表示到坐标原点(图像的左上角)的距离。 是线的旋转角度( )。是累加器的值。 |
rho | 距离步长。 |
theta | 角度步长。 |
threshold | 累加器阈值参数。仅返回那些获得足够投票的行(),即只有大于该值的点才有可能被当作极大值,即至少有多少条正弦曲线交于一点才被认为是直线。 |
srn | 对于多尺度霍夫变换,它是距离分辨率的除数。粗略的累加器距离分辨率为,准确的累加器分辨率为。如果和都使用经典的Hough变换。否则,这两个参数都应为正。 |
stn | 对于多尺度霍夫变换,它是距离分辨率的除数。 |
min_theta | 对于标准和多尺度霍夫变换,请使用最小角度检查线条。必须介于0和之间。 |
max_theta | 对于标准和多尺度霍夫变换,请使用最大角度来检查线条。必须介于和CV_PI之间。 |
rho一般取1,theta取pi/180,阈值可调,其它默认即可。 函数返回lines为三维数组,为每个直线的极坐标交点的极径,极角,可通过公式解算出直线端点进行绘制
2. HoughLinesP
- 说明 用概率霍夫变换在二进制图像中查找线段。该函数实现了用于行检测的概率霍夫变换算法。
- 声明
void HoughLinesP(
InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength = 0,
double maxLineGap = 0
);
- 参数
image | 8位单通道二进制源图像。该图像可以通过该功能进行修改。 |
lines | 输出的线向量。每个线由4元向量表示。 和是每个被检测线段的终点。 |
rho | 累加器的距离分辨率(以像素为单位)。 |
theta | 累加器的角度分辨率(以弧度为单位)。 |
threshold | 累加器阈值参数。仅返回那些获得足够投票的行。 |
minLineLength | 最小线长。短于此的线段将被拒绝。 |
maxLineGap | 连接同一条线上的点之间的最大允许间隙。 |
- 行检测实例:
void houghTest() {
Mat src, dst, color_dst;
src = imread("D:/test/building.jpg");
Canny(src, dst, 100, 200, 3);
cvtColor(dst, color_dst, COLOR_GRAY2BGR);
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI / 180, 120, 50, 10);
for (size_t i = 0; i < lines.size(); i++)
{
line(color_dst, Point(lines[i][0], lines[i][1]),
Point(lines[i][2], lines[i][3]), Scalar(0, 0, 255), 1, 8);
}
imshow("Source", src);
imshow("Detected Lines", color_dst);
waitKey(0);
}
应用
霍尔直线的使用步骤:
- 读图片
- 高斯去噪
- 灰度化
- 边缘检测----二值化
- 霍夫直线检测
- 画线
void houghLineTest(Mat& src) {
//1.图像灰度化
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
//2. 模糊处理
Mat blur;
GaussianBlur(gray, blur, Size(3, 3),0);
//3. 边缘提取
Mat canny;
Canny(blur, canny, 50, 200);
//4. 霍夫直线检测
Mat dst1=src.clone();
Mat dst2 = src.clone();
vector<Vec2f> lines;
HoughLines(canny, lines, 1, CV_PI / 180,150, 0, 0);
//5. 画线
for (size_t i = 0; i < lines.size(); i++)
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta);
double b = sin(theta);
double x0 = a * rho;
double y0 = b * rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
line(dst1, pt1, pt2, Scalar(0, 0, 255), 1, LINE_AA);
}
vector<Vec4i> linesP;
HoughLinesP(canny, linesP, 1, CV_PI / 180, 150, 50,10);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i ln = linesP[i];
line(dst2, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 255, 0), 1, LINE_AA);
}
imshow("src", src);
imshow("dst1", dst1);
imshow("dst2", dst2);
waitKey(0);
}
学习:霍夫变换(Hough Line Transform)-直线检测
霍夫变换–直线,圆的识别
霍夫检测(直线,圆)
OpenCv–霍夫直线变换(检测直线)
OpenCV霍夫变换系列(前篇)-经典霍夫线变换
[在OpenCV里实现霍夫直线检测1]()
Opencv学习笔记-----霍夫变换直线检测及原理理解
霍夫变换直线检测及原理理解
霍夫变换检测直线原理分析
霍夫变换