【OpenCV • c++】几何检测 —— 霍夫变换 | 霍夫直线检测 | 霍夫线变化

简介: 【OpenCV • c++】几何检测 —— 霍夫变换 | 霍夫直线检测 | 霍夫线变化

什么是霍夫变换?


 霍夫变化是从图像中识别几何形状的基本图像处理方法之一,应用广泛。霍夫变换用来检测图像中的直线,其原理是利用坐标空间变换将两个坐标进行相应的转换,或通过直线映射到另一坐标空间的点形成的峰值。从而把检测任意形状的问题转化为统计峰值的问题。它的优点在于分割结果的鲁棒性,它的缺点是要求知道物体边界线的解析方程。


霍夫变化的原理


 以直线检测为例,每个像素坐标点经过空间变换都编程对直线特质有贡献的统一度量。


e10fcea043340e510d38dc5296e4a2a3_f3fe68505c4246b7b2199fcdcf806cce.png


 对于二维图像数据 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;
}

e382a562a0a9180b473c4e011b1454f1_83394e8be2b145cbaeacfc61f1bdc7da.png


多尺度霍夫变化(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;
}

89c1245b4347feb35433b8f3a64e97c7_55714b5c0c8a43cab472f5c47703787e.png




相关文章
|
19天前
|
计算机视觉
Opencv学习笔记(八):如何通过cv2读取视频和摄像头来进行人脸检测(jetson nano)
如何使用OpenCV库通过cv2模块读取视频和摄像头进行人脸检测,并提供了相应的代码示例。
60 1
|
18天前
|
机器学习/深度学习 计算机视觉
目标检测笔记(六):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)
本文介绍了如何使用OpenCV进行特定区域的目标检测,包括人脸检测实例,展示了两种实现方法和相应的代码。
38 1
目标检测笔记(六):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)
|
18天前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
165 3
|
2月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
5月前
|
算法 开发工具 计算机视觉
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
75 1
|
18天前
|
算法 计算机视觉 Python
圆形检测算法-基于颜色和形状(opencv)
该代码实现了一个圆检测算法,用于识别视频中的红色、白色和蓝色圆形。通过将图像从RGB转换为HSV颜色空间,并设置对应颜色的阈值范围,提取出目标颜色的区域。接着对这些区域进行轮廓提取和面积筛选,使用霍夫圆变换检测圆形,并在原图上绘制检测结果。
47 0
|
2月前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
58 11
|
2月前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
22 3
|
4月前
|
机器学习/深度学习 传感器 算法
OpenCV4工业缺陷检测的六种方法
OpenCV4工业缺陷检测的六种方法
|
5月前
|
存储 编解码 算法
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
81 0