- 🚀 个人简介:CSDN「博客新星」TOP 10 , C/C++ 领域新星创作者
- 💟 作 者:锡兰_CC ❣️
- 📝 专 栏:【OpenCV • c++】计算机视觉
- 🌈 若有帮助,还请关注➕点赞➕收藏,不行的话我再努努力💪💪💪
文章目录
- 什么是霍夫变换?
- 霍夫变化的原理
- 霍夫线变化
- 标准的霍夫变换(SHT)
- 参考代码:
- 多尺度霍夫变化(MHT)
什么是霍夫变换?
霍夫变化是从图像中识别几何形状的基本图像处理方法之一,应用广泛。霍夫变换用来检测图像中的直线,其原理是利用坐标空间变换将两个坐标进行相应的转换,或通过直线映射到另一坐标空间的点形成的峰值。从而把检测任意形状的问题转化为统计峰值的问题。它的优点在于分割结果的鲁棒性,它的缺点是要求知道物体边界线的解析方程。
霍夫变化的原理
以直线检测为例,每个像素坐标点经过空间变换都编程对直线特质有贡献的统一度量。
对于二维图像数据 f(x,y),平面坐标为 (x,y),极坐标为 (r,θ)。从坐标轴可看出公式:xcosθ+ysinθ=r
对于图像像素平面坐标 (x,y),我们需要做的就是通过空间坐标映射关系,将图像笛卡尔坐标系转换到极坐标霍夫空间系统,这种点到曲线的映射变换称为霍夫变换。
霍夫线变化
在许多实际的图像处理应用中,我们可以检测图像中的轮廓部分或图形,直线检测有利于分析图像中的角度及其结构特征。
霍夫线变化是基于图像二值化的变换,利用二值化图像中的点集来确定候选直线的集合。在图像的边缘,可以用方程 f(x,p) = 0 来表示任意的曲线,其中p为曲线的参数向量,那么利用霍夫变换进行线检测算法的步骤如下:
-
在参数 p 的范围内量化参数空间,将霍夫空间坐标 (r,θ) 初始化为 0。
-
在阈值化后的梯度图像中,对每个图像点 (i,j) 进行遍历,对于满足参数 p,加权累计所有满足 f(x,p) = 0 的单位 S§,则 S§ = S§ + delta§。
-
计算当前霍夫空间的累计数组 S§ 的局部最大值,那么对应的就是原始图像中 f(x,p) = 0 的解析实现。
OpenCv 算法并没有直接将曲线提取出来,而是返回相应的**(r,θ)平面的局部最大值**,因此要对OpenCV中的函数参数接口进一步理解分析。
标准的霍夫变换(SHT)
参考代码:
void HoughLinesP(InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength = 0,
double maxLineGap = 0)
其中,image
代表输入图像,lines
代表输出线向量,每个向量由四个元素 (x1, y1, x2, y2)
组成,(x1, y1)
和(x2, y2)
为线段的终点坐标,rho
代表累计像素的距离分辨率,theta
代表累计弧度的角度分辨率,ehreshold
代表要检测一条直线所需最少的曲线交点,minLineLength
代表最小的线长度,maxLineGap
代表最大的长度,用于线段连接。
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc_c.h>
#include <opencv2/imgproc/types_c.h>
#include<opencv2/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
cv::Mat srcImage = cv::imread("...cc.png", 0);
if (!srcImage.data)
return 1;
cv::Mat edgeMat, houghMat;
// Canny 边缘检测 二值图像
Canny(srcImage, edgeMat, 50, 180, 3);
cvtColor(edgeMat, houghMat, CV_GRAY2BGR);
// 标准的霍夫变换
vector<Vec2f> lines;
HoughLines(edgeMat, lines, 1, CV_PI / 180, 100, 0, 0);
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), b = sin(theta);
double x0 = a * rho, 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(houghMat, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);
}
cv::imshow("srcImage", srcImage);
cv::imshow("houghMat", houghMat);
cv::waitKey();
cv::waitKey(0);
return 0;
}
多尺度霍夫变化(MHT)
void HoughLinesP(InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength = 0,
double maxLineGap = 0)
其中,image
代表输入图像,lines
代表输出线向量,每个向量由两个元素 (,θ)
组成,(x1, y1)
和(x2, y2)
为线段的终点坐标,rho
代表累计像素的距离分辨率,theta
代表累计弧度的角度分辨率,ehreshold
代表要检测一条直线所需最少的曲线交点,minLineLength
代表最小的线长度,maxLineGap
代表最大的长度,用于线段连接。
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc_c.h>
#include <opencv2/imgproc/types_c.h>
#include<opencv2/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
cv::Mat srcImage = cv::imread("...cc.png", 0);
if (!srcImage.data)
return 1;
cv::Mat edgeMat, houghMat;
// Canny 边缘检测 二值图像
Canny(srcImage, edgeMat, 50, 180, 3);
cvtColor(edgeMat, houghMat, CV_GRAY2BGR);
// 统计概率的霍夫变换
vector<Vec4i> lines;
HoughLinesP(edgeMat, lines, 1, CV_PI / 180, 50, 50, 10);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
// 绘制线检测结果
line(houghMat, Point(l[0], l[1]),
Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
}
cv::imshow("srcImage", srcImage);
cv::imshow("houghMat", houghMat);
cv::waitKey();
cv::waitKey(0);
return 0;
}
其他:
更多专栏订阅:
- 👍 【开卷数据结构】
- 💛 【备战蓝桥,冲击省一】
- 💕 从零开始的 c++ 之旅
- 💖 【OpenCV • c++】计算机视觉