OpenCV2马拉松第23圈——圆检测与通用Hough变换

计算机视觉讨论群162501053


收入囊中
  • Hough圆检测
  • 通用Hough变换

葵花宝典

我们在之前利用Hough变换实现了直线的检测,因为两个特征(k,b)或者(theta,r)就能确定一条直线,所以我们的Hough空间是二维的。一个圆由3个特征组成,分别是圆心的横坐标,纵坐标,以及圆的半径,因此我们的Hough空间是三维的。

圆的方程:(x-a)^2 + (y-b)^2 = r^2

过一点(x0,y0),a,b,r的关系就是:(x0-a)^2 + (y0-b)^2 = r^2

因此,我们的Hough空间[a是横坐标,b是纵坐标,r是竖坐标]
我们要用一个二重循环去填充Hough空间
跟直线检测一样,我们现在是在三维数组里找局部最大值,确定圆的(x,y,r)
听完之后是不是觉得方法很简单,跟检测直线没什么区别,也用不到极坐标。

但是,三维累加器中会产生许多噪声并且使得结果不稳定的稀疏分布!
因此,由Hough梯度法来改进这个算法。

Hough梯度法
  1. 利用canny检测提取边缘
  2. 对每一个边缘点,我们可以计算出梯度[其实就是圆心和边缘点连线方向]
  3. 计算出梯度后,我们就可以得到一条垂直于该点切线的直线,我们就有一个二维数组H,用来填充这条直线上所有点
  4. H中出现频率最高的肯定就是圆心
  5. 对于得到的圆心中的每一个,计算那些边缘点到该圆心的距离,若某个距离很充分出现次数足够,就可以认为这是一个合格的圆


初识API
C++:  void  HoughCircles (InputArray  image, OutputArray  circles, int  method, double  dp, double  minDist, double  param1=100, double  param2=100, int  minRadius=0, int  maxRadius=0  )
 
  • image – 8比特单通道灰度图
  • circles – 是一个向量,每个都是3元素的浮点数 (x, y, radius) .
  • method – 唯一的方法是CV_HOUGH_GRADIENT
  • dp – 如果dp=1 , Hough空间的叠加器就和输入图片的分辨率一致. 如果dp=2 , Hough空间叠加器就只有一半大小.
  • minDist – 检测的圆心最小距离间隔。如果设置太小,一些旁边的圆可能就被错误的检测,而正确的就没检测出来。如果设置太大,可能就漏掉很多圆。
  • param1 –它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半
  • param2 –它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了
  • minRadius – 圆最小半径
  • maxRadius – 圆最大半径

荷枪实弹
因为算法和直线检测类似,所以自己就不实现了
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace cv;

/** @function main */
int main(int argc, char** argv)
{
  Mat src, src_gray;

  /// Read the image
  src = imread( argv[1], 1 );

  if( !src.data )
    { return -1; }

  /// Convert it to gray
  cvtColor( src, src_gray, CV_BGR2GRAY );

  /// Reduce the noise so we avoid false circle detection
  GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );

  vector<Vec3f> circles;

  /// Apply the Hough Transform to find the circles
  HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );

  /// Draw the circles detected
  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 center
      circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
      // circle outline
      circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
   }

  /// Show your results
  namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
  imshow( "Hough Circle Transform Demo", src );

  waitKey(0);
  return 0;
}


举一反三
下面我来稍微讲解一下广义Hough变换

假如我们有一张模版函数




在模版图像中,我们有3种基本图形,我们也确定了一个中心,每种基本图形相对于中心都产生了一些偏移向量

左边是一张测试图片

仔细看下面的广义Hough变换图,每张图都对每一个基本图形运用了之前的偏移向量,再在一个二维Hough空间叠加

    下面是第二张图,原图太大不支持上传   

最右边的圆圈处二维叠加器最大,于是就找到原来的模版图像

再举个例子

左图,我们提取圆的偏移向量

然后,在测试图片中就能找到, 是不是很有趣

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值