前言

我们如何在图像中快速识别出其中的圆和直线?一个非常有效的方法就是霍夫变换,它是图像中识别各种几何形状的基本算法之一。

霍夫线变换

霍夫线变换是一种在图像中寻找直线的方法。OpenCV中支持三种霍夫线变换,分别是标准霍夫线变换、多尺度霍夫线变换、累计概率霍夫线变换。

在OpenCV中可以调用函数HoughLines来调用标准霍夫线变换和多尺度霍夫线变换。HoughLinesP函数用于调用累积概率霍夫线变换。

我们都知道,二维坐标轴上表示一条直线的方程式y = a*x + b,我们想求出一条直线就得想方设法求出其中的a和b的值。如果用极坐标来表示就是

theta就是直线与水平线所成的角度,而rho就是圆的半径(也可以理解为原点到直线的距离),同样地,这两个参数也是表征一条直线的重要参数,确定他们俩了,也就确定一条直线了。正如下图所示。

在OpenCV里,我们只需调用HoughLines就是可以得到表征一条直线的这两个参数值!

HoughLines用法

#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>using namespace cv;
using namespace std;int main()
{Mat srcImage = imread("4.jpg");imshow("Src Pic", srcImage);Mat midImage, dstImage;//边缘检测Canny(srcImage, midImage, 50, 200, 3);//灰度化cvtColor(midImage, dstImage, CV_GRAY2BGR);// 定义矢量结构存放检测出来的直线vector<Vec2f> lines;//通过这个函数,我们就可以得到检测出来的直线集合了HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);//这里注意第五个参数,表示阈值,阈值越大,表明检测的越精准,速度越快,得到的直线越少(得到的直线都是很有把握的直线)//这里得到的lines是包含rho和theta的,而不包括直线上的点,所以下面需要根据得到的rho和theta来建立一条直线//依次画出每条线段for (size_t i = 0; i < lines.size(); i++){float rho = lines[i][0]; //就是圆的半径rfloat 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(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, LINE_AA); //Scalar函数用于调节线段颜色,就是你想检测到的线段显示的是什么颜色imshow("边缘检测后的图", midImage);imshow("最终效果图", dstImage);}waitKey();return 0;
}

原图

阈值我设为250,看看直线检测的效果。你会发现,怎么图中一些很明显的的直线都没检测出来啊?原因是,我们阈值写的有点高了,只有那些有足够的把握认为是直线的直线才可能检测出来。

然后我把阈值改为150,直线检测效果就变成这样子了。显然多了很多直线,这是我们把我们的要求降低了,把那些“可能是直线”的直线都当做是直线了。所以,阈值的选择很重要,就看你是要精确查找还是模糊查找了。

后来我又加了一句打印进去,想看看角度的单位是什么

    cout << "line " << i << ": " << "rho:" << rho << " theta:" << theta << endl;

可以看到,角度theta用的单位不是我们所说的度数(70度、80度),而是数学上的π/2,π/3。

要想转为我们所说的度数,自己写个转换吧

float angle = theta / CV_PI * 180;

可以看出,转换后的角度范围就是我们想要的度数!值得注意的是,rho表示离坐标原点(就是图片左上角的点)的距离,theta是直线的旋转角度(0度表示垂直线,90度表示水平线)。

HoughLinesP用法

此函数在HoughLines的基础上在末尾加了一个代表Probabilistic(概率)的P,表明使用的是累计概率变换。

#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>using namespace cv;
using namespace std;int main()
{Mat srcImage = imread("2.jpg");imshow("Src Pic", srcImage);Mat midImage, dstImage;Canny(srcImage, midImage, 50, 200, 3);cvtColor(midImage, dstImage, CV_GRAY2BGR);vector<Vec4i> lines;//与HoughLines不同的是,HoughLinesP得到lines的是含有直线上点的坐标的,所以下面进行划线时就不再需要自己求出两个点来确定唯一的直线了HoughLinesP(midImage, lines, 1, CV_PI / 180, 80, 50, 10);//注意第五个参数,为阈值//依次画出每条线段for (size_t i = 0; i < lines.size(); i++){Vec4i l = lines[i];line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186, 88, 255), 1, LINE_AA); //Scalar函数用于调节线段颜色imshow("边缘检测后的图", midImage);imshow("最终效果图", dstImage);}waitKey();return 0;
}

貌似效果还不错。

霍夫圆变换

刚刚的霍夫变换是检测直线的,如果我们想检测圆形,那该怎么办?那就用霍夫圆变换!用法也大同小异。

#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>using namespace cv;
using namespace std;int main()
{Mat srcImage = imread("test5.jpg");  Mat midImage, dstImage;//临时变量和目标图的定义  imshow("【原始图】", srcImage);//【3】转为灰度图,进行图像平滑  cvtColor(srcImage, midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图  GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);//【4】进行霍夫圆变换  vector<Vec3f> circles;HoughCircles(midImage, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 150, 0, 0); //注意第七的参数为阈值,可以自行调整,值越大,检测的圆更精准//【5】依次在图中绘制出圆  for (size_t i = 0; i < circles.size(); i++){Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));int radius = cvRound(circles[i][2]);//绘制圆心  circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);//绘制圆轮廓  circle(srcImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);}//【6】显示效果图    imshow("【效果图】", srcImage);waitKey(0);return 0;
}

可以看到,有一些圆没有检测出来,同时还有一些不是圆形的确有误以为是圆形了,说明阈值选择不是很妥当。

另外提一点,霍夫圆变换的检测速度真的慢,显然进行圆检测的计算量还真不少!

OpenCV探索之路(六):图像变换——霍夫变换相关推荐

  1. OpenCV中的图像变换——傅里叶变换

    OpenCV中的图像变换--傅里叶变换 1. 效果图 2. 原理 3. 源码 3.1 Numpy实现傅里叶变换 3.2 OpenCV实现傅里叶变换 3.3 HPF or LPF? 参考 这篇博客将介绍 ...

  2. OpenCV(六)之图像轮廓检测

    OpenCV(六)之图像轮廓检测 Contour detection系列 Contour detection-图像金字塔 图像金字塔-高斯金字塔 图像金字塔-拉普拉斯金字塔 Contour detec ...

  3. OpenCV探索之路(五):图像变换——边缘检测(canny、sobel、laplacian)

    前言 边缘检测的一般步骤: 滤波--消除噪声 增强--使边界轮廓更加明显 检测--选出边缘点 一.Canny算法 Canny边缘检测算法被很多人推崇为当今最优秀的边缘检测算法,所以我们第一个就介绍他. ...

  4. OpenCV探索之路(二十六):如何去除票据上的印章(C++ )

    最近在做票据识别的编码工作时遇到一些问题,就是票据上往往会有一些红色印章把一些重要信息区域给覆盖了,比如一些开发票人员盖印章时比较随意,容易吧一些关键区域给遮蔽了,这让接下来的票据识别很困难,因此,我 ...

  5. OpenCV探索之路(二十六):如何去除票据上的印章

    http://www.cnblogs.com/skyfsm/p/7638301.html 最近在做票据识别的编码工作时遇到一些问题,就是票据上往往会有一些红色印章把一些重要信息区域给覆盖了,比如一些开 ...

  6. 4 用python进行OpenCV实战之图像变换1(平移)

    前言 到目前为止,经过前几节的介绍,我们已经有了一个坚实的基础去做一些图像处理,在本节我们先将介绍图像变换中的平移,为后面几节学习图像变换中的旋转.改变大小.镜像.裁剪打下一个好的基础 1 平移 1. ...

  7. 【OpenCV十六新手教程】OpenCV角检测Harris角点检测

    本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187 作者:毛星云(浅墨) ...

  8. (六)基于霍夫变换的直线和圆检测

    1.Hough Transform https://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm 霍夫变换于1962年由Paul Hough首次提出,后于197 ...

  9. 3h精通OpenCV(六)-图像堆叠

    0.准备工作 右击新建的项目,选择Python File,新建一个Python文件,然后在开头import cv2导入cv2库,import numpy并且重命名为np. import cv2 imp ...

最新文章

  1. weblogic反序列化漏洞CVE-2018-2628-批量检测脚本
  2. nodejs 服务器怎么导入qs_nodejs基本原理总结
  3. C++使用ADO存取图片
  4. 9岁女孩联合国演讲上热搜,网友:自愧不如
  5. JavaScript的事件执行机制及异步
  6. URAL 1081 Binary Lexicographic Sequence
  7. 萧条下的养殖业成就兽药电子商务新时代
  8. 【PC端】jQuery+PHP实现浏览更多内容(jquery.more.js插件)
  9. 直面程序人生,始于当下,奔赴未来!
  10. ERROR: Cannot uninstall ‘certifi‘. It is a distutils installed project and thus we cannot accurately
  11. php支付宝App支付生成预支付订单(统一下单接口)
  12. 获取Android 手机设备信息:包括机型、操作系统版本号、手机分辨率、运营商、当前联网方式、IMEI、MEID、MAC地址
  13. 夏天开水果店怎么保存,水果店水果的保存方法
  14. java微信小程序内容安全 - 检测文本是否含有违法违规内容
  15. python个数计算公式_使用python中的公式计算第n个斐波纳契数
  16. vue百度地图标记多个marker和marker点击事件处理
  17. 搭建nlp_server服务器
  18. 插入图片与背景图片的区别
  19. 入门python爬虫
  20. OpenGL中纹理坐标和顶点坐标表示

热门文章

  1. Observer设计模式中-委托事件-应用在消息在窗体上显示
  2. 工作中学习,学习中成长
  3. GCC一些有用的技巧
  4. 三维点云学习(4)4-Hough Transform
  5. html云文件系统,一种HTML5云文件系统
  6. oracle自动分区maxvalue,对Maxvalue上限范围分区进行spilt操作
  7. vue中v-model的使用
  8. 职教高中计算机专业知识,新课改背景下计算机专业教学(职教)三维目标设计初探...
  9. RenderTransformOrigin 的作用
  10. 论文笔记--知识表示学习研究进展-2016