自OpenCV 4.3.0版本,imgproc模块的HoughCircles()函数,新增加了检测算法HOUGH_GRADIENT_ALT,精度得到了很大的提升。

1、举例opencv v4.5.5版本源码,

https://github.com/opencv/opencv/blob/4.5.5/modules/imgproc/src/hough.cpp

static void HoughCircles( InputArray _image, OutputArray _circles,int method, double dp, double minDist,double param1, double param2,int minRadius, int maxRadius,int maxCircles, double param3 )
{CV_INSTRUMENT_REGION();int type = CV_32FC3;if( _circles.fixedType() ){type = _circles.type();CV_CheckType(type, type == CV_32FC3 || type == CV_32FC4, "Wrong type of output circles");}CV_Assert(!_image.empty() && _image.type() == CV_8UC1 && (_image.isMat() || _image.isUMat()));if( dp <= 0 || minDist <= 0 || param1 <= 0)CV_Error( Error::StsOutOfRange, "dp, min_dist and canny_threshold must be all positive numbers" );switch( method ){case HOUGH_GRADIENT:{......}break;case HOUGH_GRADIENT_ALT:{std::vector<EstimatedCircle> circles;Mat image = _image.getMat();HoughCirclesAlt(image, circles, dp, minDist, minRadius, maxRadius, param1, param2);std::sort(circles.begin(), circles.end(), cmpAccum);size_t i, ncircles = circles.size();if( type == CV_32FC4 ){std::vector<Vec4f> cw(ncircles);for( i = 0; i < ncircles; i++ )cw[i] = GetCircle4f(circles[i]);if (ncircles > 0)Mat(1, (int)ncircles, cv::traits::Type<Vec4f>::value, &cw[0]).copyTo(_circles);}else if( type == CV_32FC3 ){std::vector<Vec3f> cwow(ncircles);for( i = 0; i < ncircles; i++ )cwow[i] = GetCircle(circles[i]);if (ncircles > 0)Mat(1, (int)ncircles, cv::traits::Type<Vec3f>::value, &cwow[0]).copyTo(_circles);}elseCV_Error(Error::StsError, "Internal error");}break;default:CV_Error( Error::StsBadArg, "Unrecognized method id. Actually only CV_HOUGH_GRADIENT is supported." );}
}static void HoughCirclesAlt( const Mat& img, std::vector<EstimatedCircle>& circles, double dp, double rdMinDist,double minRadius, double maxRadius, double cannyThreshold, double minCos2 )
{const int MIN_COUNT = 10;const int RAY_FP_BITS = 10;const int RAY_FP_SCALE = 1 << RAY_FP_BITS;const int ACCUM_FP_BITS = 6;const int RAY_SHIFT2 = ACCUM_FP_BITS/2;const int ACCUM_ALPHA_ONE = 1 << RAY_SHIFT2;const int ACCUM_ALPHA_MASK = ACCUM_ALPHA_ONE - 1;const int RAY_SHIFT1 = RAY_FP_BITS - RAY_SHIFT2;const int RAY_DELTA1 = 1 << (RAY_SHIFT1 - 1);const double ARC_DELTA = 80;const double ARC_EPS = 0.03;const double CIRCLE_AREA_OFFSET = 4000;const double ARC2CLUSTER_EPS = 0.06;const double CLUSTER_MERGE_EPS = 0.075;const double FINAL_MERGE_DIST_EPS = 0.01;const double FINAL_MERGE_AREA_EPS = CLUSTER_MERGE_EPS;if( maxRadius <= 0 )maxRadius = std::min(img.cols, img.rows)*0.5;if( minRadius > maxRadius )std::swap(minRadius, maxRadius);maxRadius = std::min(maxRadius, std::min(img.cols, img.rows)*0.5);maxRadius = std::max(maxRadius, 1.);minRadius = std::max(minRadius, 1.);minRadius = std::min(minRadius, maxRadius);cannyThreshold = std::max(cannyThreshold, 1.);dp = std::max(dp, 1.);Mat Dx, Dy, edges;Scharr(img, Dx, CV_16S, 1, 0);Scharr(img, Dy, CV_16S, 0, 1);Canny(Dx, Dy, edges, cannyThreshold/2, cannyThreshold, true);Mat mask(img.rows + 2, img.cols + 2, CV_8U, Scalar::all(0));double idp = 1./dp;......
}

2、算子说明

HoughCircles(
        InputArray image, //输入图像,必须是8位的单通道灰度图像
        OutputArray circles, //输出结果,找到的圆信息
        Int method, //方法是HOUGH_GRADIENT或HOUGH_GRADIENT_ALT
        Double dp, //dp = 1或1.5
        Double mindist, //最短距离-可以分辨是两个圆的,否则认为是同心圆
        Double param1, //canny edge detection low threshold,Canny边缘检测的较大阈值
        Double param2, //方法不同,含义不同

Int minradius, //最小半径
        Int maxradius //最大半径

image:8 位、单通道、灰度输入图像
     circles:找到圆的输出向量。每个向量编码为 3 或 4 个元素的浮点向量 $(x,y,radius)(x,y,radius,votes)$
     method:检测方法。目前实现的方法是HOUGH_GRADIENT或HOUGH_GRADIENT_ALT
     dp:累加器分辨率与图像分辨率的反比。例如,如果 dp=1,则累加器具有与输入图像相同的分辨率。如果 dp=2,则累加器的宽度和高度都是一半
     对于HOUGH_GRADIENT_ALT,推荐值为 dp=1.5,除非需要检测一些非常小的圆。
     minDist:检测到圆的中心之间的最小距离。如果参数太小,除了一个真实的圆之外,可能错误地检测到多个相邻的圆圈。如果太大,可能会遗漏一些圆。
     param1:第一个特定方法参数。在HOUGH_GRADIENT和HOUGH_GRADIENT_ALT 的情况下,它是传递给 canny 边缘检测算子的高阀值,而低阀值为高阀值的一半
     注意,HOUGH_GRADIENT_ALT使用Scharr算法计算图像导数,因此阈值通常更高,例如 300 或正常曝光和对比度的图像。
     param2:第二个特定方法参数。在HOUGH_GRADIENT的情况下,它是检测阶段圆心的累加阀值。它越小,可以检测到更多的假圆。它越大,能通过检测的圆就更加接近完美的圆形。
     在HOUGH_GRADIENT_ALT算法的情况下,这是圆形“完美”度量。它越接近 1,形状圆算法选择的越好。在大多数情况下,0.9 应该没问题。
     如果您想更好地检测小圆圈,您可以将其降低到 0.85、0.8 甚至更低。
     minRadius:最小半径
     maxRadius:最大圆半径。如果≤0,则使用最大图像尺寸;如果<0,则返回中心而不查找半径

3、应用

由于HoughCircles函数内是调用Canny函数进行边缘检测,opencv的Canny函数是不包括平滑滤波这一步的,因此为了增强抗干扰能力,在使用HoughCircles函数之前,我们先对原图进行滤波处理,我们使用的是高斯模糊方法。

void hough()
{cv::Mat src, dst;src = cv::imread("d:\\circle.jpg");//中值滤波,因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波cv::Mat mOut;cv::medianBlur(src, mOut, 3);cv::Mat grayImage;cv::cvtColor(mOut, grayImage, cv::COLOR_BGR2GRAY);//对灰度矩阵进行图像平滑处理(高斯模糊)cv::GaussianBlur(grayImage, grayImage, cv::Size(9, 9), 2, 2);//找霍夫圆std::vector<cv::Vec3f> cir;//cv::HoughCircles(grayImage, cir, cv::HOUGH_GRADIENT, 1, 15, 100, 30, 1, 100);cv::HoughCircles(grayImage, cir, cv::HOUGH_GRADIENT_ALT, 1.5, 15, 300, 0.8, 1, 100);src.copyTo(dst);for (size_t i = 0; i < cir.size(); i++){cv::Vec3f cc = cir[i];cv::circle(dst, cv::Point(cc[0], cc[1]), cc[2], cv::Scalar(0, 0, 255), 2, cv::LINE_AA); //圆周cv::circle(dst, cv::Point(cc[0], cc[1]), 2, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);     //圆心}cv::namedWindow("hough", cv::WINDOW_NORMAL);cv::imshow("hough", dst);cv::waitKey(0);
}

OpenCV找圆系列(2)HoughCircles算子新增了HOUGH_GRADIENT_ALT方法,效果好多了相关推荐

  1. 找圆算法((HoughCircles)总结与优化

    Opencv内部提供了一个基于Hough变换理论的找圆算法,HoughCircle与一般的拟合圆算法比起来,各有优势:优势:HoughCircle对噪声点不怎么敏感,并且可以在同一个图中找出多个圆:反 ...

  2. Opencv 找圆的方法

    首先建立一个概念,任何镜头下的圆,很多情况下都不是真正的 pi*r*r 的圆,会因各种物体与镜头之间的非完全平行关系或光线与物体不是完全平行等因素,造成相机中成像的图像不是一直完全意义上的圆,更多的情 ...

  3. Halcon找圆系列(3)找金属表面的圆孔

    我在Halcon学习网发了一个帖子: 请教工件的金属表面圆孔的识别与定位 http://www.ihalcon.com/read-15016-1.html 解决方案有了,源码如下: dev_updat ...

  4. Halcon找圆系列(4)测量圆直径/半径的方法之暴力拟合法 vs 测量工具法

    今天要给大家分享一点关于Halcon测量圆直径(半径)的方法. 首先容我啰嗦两句:之所以要对这个看似很基础的问题进行探讨,主要原因有二,其一是这个问题确实困扰了我一段时间,当然这主要是由于我自己经验不 ...

  5. Halcon找圆系列(6)找多个圆并求圆心间距离

    项目来源:http://www.ihalcon.com/read-6805.html *找多个圆并求圆心间距离 *http://www.ihalcon.com/read-6805.html*方法1 d ...

  6. Halcon中的测量工具(找边找圆等)——Metrology系列

    Halcon中的测量工具(找边找圆等)--Metrology系列 1. Halcon中的工具助手 对于使用Halcon的小伙伴们来说,在菜单栏上的"助手"一栏中可以找到一些可以快捷 ...

  7. OpenCV基础入门系列基本操作——贰

    系列博文第二篇,关于OpenCV4的一些基本操作和使用. 博文主要以实例展示不同的函数使用方法. OpenCV基础入门系列基本操作--壹 前言 下述为本博文需要用到的各类头文件以及全局变量等 读者可根 ...

  8. 利用Python OpenCV进行圆孔检测、计算半径、圆心到四边距离

    先上最终检测视频: OpenCV实时检测圆孔 本文重在实操,就不赘述背景意义等内容. 给定问题:假如有一个配件,此时需要检测配件上的圆孔坐标.半径.个数.圆孔到配件四边的距离. 由于没有实物,就在纸上 ...

  9. Python OpenCV画圆

    Python OpenCV画圆 PS: 也是从网上各个帖子中学习的Python,因此代码的格式以及内容有粘贴网上其他大神的代码,如有侵权请告知删除 在图片中检测圆,并进行标注 #!/usr/bin/p ...

最新文章

  1. 求方程ax2+bx+c的根python_Python,计算 ax^2 + bx + c = 0的根
  2. 《大道至简》第八章读后感
  3. 大数据综合能力测试_如何完成大数据测试?资深测试从功能测试角度为你分析分析...
  4. poe交换机的作用和优点
  5. 使用NVM管理Node - Windows
  6. Onboard,迷人的引导页样式制作库
  7. PaddlePaddle飞桨OCR文本检测——识别图片文字结果并保存为txt(五)
  8. 深度学习文本分类|模型代码技巧
  9. mysql 主从同步原理
  10. SD2.0大会第1天心得
  11. UVA1218 完美的服务 Perfect Service
  12. 上海黑马python培训
  13. git tag (打标签)
  14. 机器人学回炉重造(4):动力学仿真(附牛顿-欧拉递归逆动力学算法matlab代码)
  15. 时间序列中Hurst指数的计算(python代码)
  16. html框架集frame是啥意思,HTML框架frame与iframe详解
  17. 面试:View加载流程setContentView
  18. 不忍舍弃的回忆——我的大学时代
  19. RTX之——时间管理
  20. Proxmox backup server虚机还原测试

热门文章

  1. 我的考博经验总结 CCER
  2. 【经典】Spring aop切面实现异步添加日志—完整版
  3. 黑苹果 看不了电量_黑苹果更换ssd 西数黑盘 三星970 pro 看傻眼了
  4. 安富莱V6供电问题,突然黑屏
  5. ZBrush教程(二):可用雕刻笔刷功能介绍
  6. CVX用户指南之简介
  7. 网络科学导论——1引言
  8. Cocos Creator性能优化---DrawCall
  9. PS 套索选区工具(2) 多边形套索工具 磁性套索工具使用技巧
  10. pos机小票打印机編程