目录

霍夫变换检测

HoughCircles()函数官方:


参考链接:https://blog.csdn.net/qq_40584593/article/details/89299548

方法一:霍夫变换检测

HoughCircles()函数官方:

https://docs.opencv.org/3.4.2/dd/d1a/group__imgproc__feature.html#ga47849c3be0d0406ad3ca45db65a25d2d

实现代码:

/* redball_detect.cpp
Description: the test example for detect the red ball.
Date: 2017/10/12
*/#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;#define SRC_WINDOW_NAME "redball"
#define MID_WINDOWNAME "redball_gray"Mat srcImage,  dstImage;
Mat channel[3];int main()
{// 原图像读取srcImage = imread("redball5.jpg", 1);imshow(SRC_WINDOW_NAME, srcImage);// 提取红色通道图像int g_nHm = 9; // 可利用滑动条调节split(srcImage, channel);channel[0] = channel[0].mul(.1*g_nHm); // B    (mul: per-element matrix multiplication)channel[1] = channel[1].mul(.1*g_nHm); // Gchannel[2] = channel[2] - channel[0] - channel[1]; // Rchannel[2] = 3 * channel[2];imshow(MID_WINDOWNAME, channel[2]);dstImage = channel[2];GaussianBlur(dstImage, dstImage, Size(9, 9), 2, 2); // 用于减少检测噪声// 霍夫圆检测vector<Vec3f> circles; // 3通道float型向量HoughCircles(dstImage, circles, CV_HOUGH_GRADIENT, 1, srcImage.rows / 5, 200, 16, 0, 0);// 结果显示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);cout << circles[i][0] << "\t" << circles[i][1] << "\t" << circles[i][2] << endl;}// cout << circles[0][0] << endl;imshow(SRC_WINDOW_NAME, srcImage);waitKey(0);return 0;
}

代码中的几点说明:
- 因为需要检测的红色球,所以提取RGB图像中的红色通道值更有利于检测;
- g_nHm是可调节参数,可以利用滑动条确定最好的值;
- GaussianBlur()函数用于抑制检测过程中的噪声,可以参考检测结果中使用GaussianBlur前后的对比。

方法二:轮廓查找

使用findContours函数

1.方法一:使用判断外接矩阵是否近似正方形。

fitEllipse()函数

经过多次试验,发现利用OpenCV的霍夫圆变换查找出来的圆,其圆心位置并不准确,而且参数调节较为麻烦。于是想到利用轮廓查找的方式来进行圆检测,我们可以通过判断轮廓的外接矩形的横纵比来判断该轮廓是否为圆形。一般而言,圆的外接矩形肯定近似于一个正方形,因此宽高比接近1.0 。总体思路如下:阈值分割->形态学/滤波降噪->轮廓查找->范围过滤->圆形拟合。代码如下,仅供参考。

         int MinR = 100; int MaxR = 300;Mat src_img, binary_img, dst_img;src_img = imread("test.bmp", IMREAD_GRAYSCALE);//灰度图读入threshold(src_img, binary_img, 158, 255, THRESH_BINARY );imshow("trs", binary_img);//imwrite("trs.bmp", binary_img);//可以根据实际需求选择使用的滤波进行降噪//GaussianBlur(binary_img, binary_img, Size(3, 3), 0, 0);//boxFilter(binary_img, binary_img,-1, Size(3, 3));//blur(binary_img, binary_img, Size(3, 3));vector<vector<Point>> contours;  vector<Vec4i> hireachy;// 形态学操作   Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));// 构建形态学操作的结构元   morphologyEx(binary_img, binary_img, MORPH_CLOSE, kernel, Point(-1, -1));//闭操作  kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));// 构建形态学操作的结构元morphologyEx(binary_img, binary_img, MORPH_OPEN, kernel, Point(-1, -1));//开操作  //imshow("开操作", dst_img);findContours(binary_img, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());imshow("bf", binary_img);//imwrite("bf.bmp", binary_img);Mat result_img = src_img.clone();cvtColor(result_img, result_img, COLOR_GRAY2BGR);//灰度图转为彩色图    for (int i = 0; i < hireachy.size(); i++){//       drawContours(src_img, contours, i, Scalar(0, 0, 255), -1, 8, Mat(), 0, Point());if (contours[i].size() < 5)continue;double area = contourArea(contours[i]);if (area < 2000)continue;//晒选出轮廓面积大于2000的轮廓   double arc_length = arcLength(contours[i], true);double radius = arc_length / (2 * PI);if (!(MinR < radius && radius < MaxR)){continue;}RotatedRect rect = fitEllipse(contours[i]);float ratio = float(rect.size.width) / float(rect.size.height);if (ratio < 1.1 && ratio > 0.9)//因为圆的外接直立矩形肯定近似于一个正方形,因此宽高比接近1.0   {printf("X: %f\n", rect.center.x);printf("Y: %f\n", rect.center.y);printf("圆的面积: %f\n", area);printf("圆的半径: %f\n", radius);ellipse(result_img, rect, Scalar(0,255, 255),2);circle(result_img, rect.center, 2, Scalar(0,255,0), 2, 8, 0);}}imshow("dst", result_img);imwrite("dst.bmp", result_img);waitKey();

算法检测出的圆形较为准确,且参数易调。主要根据调节阈值筛选轮廓,也可以采用自适应阈值。根据用户的需求进行半径与圆面积的筛选,最后得到想要的圆。如有不足,还请指正。

出处:https://blog.csdn.net/weixin_44789544/article/details/103626406?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control

1.方法二:使用椭圆来拟合

首先建立一个概念,任何镜头下的圆,很多情况下都不是真正的 pi*r*r 的圆,会因各种物体与镜头之间的非完全平行关系或光线与物体不是完全平行等因素,造成相机中成像的图像不是一直完全意义上的圆,更多的情况下,就是一个椭圆,所以opencv只提供了一个椭圆拟合的方法,其实当长短轴相等时,这就是一个真正的正圆了。

在建立这个观点后,采用众所周知的方法,就可以拟合圆了。

//图像文件名strImgName, canny的低阈值dThreshold1, canny的高阈值dThreshold2, canny的核大小iSize, 筛选圆的条件:圆的最小面积iMinArea, 圆的最小面积int iMaxArea
void findCircles(string strImgName, double dThreshold1, double dThreshold2, int iSize, int iMinArea, int iMaxArea)
{    Mat q_MatImage;  Mat q_MatImageGray;  Mat q_MatImageShow;  q_MatImage=imread(strImgName);//读入一张图片  q_MatImage.copyTo(q_MatImageShow);  //灰度化cvtColor(q_MatImage,q_MatImageGray,CV_RGB2GRAY);  //Canny找边界,也可以阈值二值化Mat cannyEdge;Canny(q_MatImageGray, cannyEdge, dThreshold1, dThreshold2, iSize);//找轮廓vector<vector<Point>> q_vPointContours;  findContours(cannyEdge, q_vPointContours, CV_RETR_EXTERNAL,             CV_CHAIN_APPROX_NONE,Point(0,0));  //drawContours(q_MatImageShow, q_vPointContours, -1, Scalar(0,255,0));//显示轮廓//筛选目标轮廓点vector<Point> vfindContours;size_t q_iAmountContours = q_vPointContours.size();  size_t iIndex = 0;for ( iIndex = 0; iIndex < q_iAmountContours; iIndex++)  { //根据圆的面积判断是否为目标圆double ddarea = contourArea(q_vPointContours[iIndex]);if((iMinArea < ddarea) && (iMaxArea > ddarea)) {break;}}//存储目标圆的轮廓点size_t findCount = q_vPointContours[iIndex].size();for(int i=0; i<findCount; i++)vfindContours.push_back(q_vPointContours[iIndex][i]);//采用椭圆拟合来得到圆RotatedRect rectElli = fitEllipse(vfindContours);float fR = MIN(rectElli.size.width , rectElli.size.height);// 是否为圆,可以比较这两个值,若十分接近或相等,就是一个正圆cout << "fitEllipse 中心: " <<  rectElli.center.x << ", " <<rectElli.center.y << "  半径:"<<fR/2<< endl;  circle(q_MatImageShow, Point(rectElli.center), fR/2, Scalar(0,0,255), 2);//圆周circle(q_MatImageShow, Point(rectElli.center), 5, Scalar(0,0,255), 3);//圆心namedWindow("Test");        //创建一个名为Test窗口  imshow("Test",q_MatImageShow);//窗口中显示图像  waitKey();
}  

计算机视觉应用-圆或者圆点检测相关推荐

  1. 计算机视觉、图像分类、目标检测、人脸比对、人脸识别、语义分割、实例分割、图像搜索

    计算机视觉.图像分类.目标检测.人脸比对.人脸识别.语义分割.实例分割.图像搜索 目录

  2. 计算机视觉:单阶段目标检测模型YOLO-V3

    计算机视觉:单阶段目标检测模型YOLO-V3 单阶段目标检测模型YOLO-V3 YOLO-V3 模型设计思想 产生候选区域 生成锚框 生成预测框 对候选区域进行标注 标注锚框是否包含物体 标注预测框的 ...

  3. 机器学习与计算机视觉入门项目——视频投篮检测(一)

    机器学习与计算机视觉入门项目--视频投篮检测(一) 随着机器学习.深度学习技术的迅猛发展,计算机视觉无疑是近年来发展最快的AI领域之一.正因如此,互联网上有关计算机视觉和机器学习.深度学习的社区.博文 ...

  4. 机器学习与计算机视觉入门项目——视频投篮检测(二)

    机器学习与计算机视觉入门项目--视频投篮检测(二) 一.手工特征与CNN特征 在上一次的博客中,介绍了计算机视觉和机器学习的关系.篮球进球检测的基本问题和数据集的制作.这次的我们主要介绍如何从原始图像 ...

  5. 机器学习与计算机视觉入门项目——视频投篮检测(三)

    机器学习与计算机视觉入门项目--视频投篮检测(三) 分类器的设计和选择 几种损失函数 Logistic回归 基本原理 损失函数 Logistic回归的求解--梯度下降法 损失函数的梯度计算 在第二部分 ...

  6. 计算机视觉:图像分类、物体检测、图像语义分割、实例分割和全景分割

    计算机视觉 图像分类 Image Classification 物体检测 Object Detection/ Object Localization 语义分割 Semantic Segmentatio ...

  7. 计算机视觉:两个旋转检测框bbox的IoU计算

    计算机视觉:两个旋转检测框bbox的IoU计算 IoU简介 两个旋转检测框bbox的IoU计算 IoU简介 在目标检测中,经常会使用到IoU.IoU 的全称为交并比(Intersection over ...

  8. 「曼孚科技」揭开计算机视觉的神秘面纱——物体检测技术

    计算机视觉是当前人工智能最热门的领域之一,在其快速发展中,物体检测发展发挥了关键作用.本文旨在详解物体检测基本概念.衍生技术及其社会化应用,揭开计算机视觉的神秘面纱,深刻理解人工智能的独特魅力. 什么 ...

  9. 基于计算机视觉的食物新鲜度分级检测

    聊到计算机视觉,估计大家肯定会想到图像分类.目标检测.图像语义分割等等经典问 题.其实计算机视觉已经开始在各行业得到应用了,比如用CV技术对食物新鲜度进行分级 检测,下面我一一娓娓道来. 说起caff ...

最新文章

  1. UA OPTI570 量子力学 原子结构基础 公式与结论总结
  2. 微软:软件帝王的复兴之路
  3. 往java里输入坐标值_java.让用户输入x坐标,和y坐标。当用户输入完x坐标(比如200),敲enter,...
  4. mysql+一致性非锁定读_MySQL探秘(六):InnoDB一致性非锁定读
  5. ssm架构 开源项目_6个开源架构项目签出
  6. 【BZOJ4247】挂饰,又一个奇特的背包
  7. 导出csv文件数字会自动变科学计数法的解决方式
  8. metasploit联动beef启动
  9. Nginx静态文件路径配置
  10. MySQL 5.7临时表空间
  11. c#学习笔记---BackgroundWorker 详解
  12. 第六章-网络可靠性设计
  13. 全球及中国汽车节能减排行业投资可行性及十四五发展趋势研究报告2021-2027年
  14. 域名转入Godaddy教程
  15. COOC+VOSviewer可取代任何文献计量与知识图谱软件
  16. 在JDK1.8中,ArrayList扩容机制Increments modCount与起始化讲解
  17. 一种新型分割图像中人物的方法,基于人物动作辨认
  18. 【MATLAB统计分析与应用100例】案例016:matlab读取Excel数据,进行样品系统聚类分析
  19. 关于如何用WORD实现图片转文字
  20. 迈向“5G智慧校园”的第一步,启用人脸识别门禁设备

热门文章

  1. 计算机室安全排查表,律师问答网
  2. 微信小程序引用echarts,微信PC端打开小程序不显示canvas
  3. [OpenGL] 曲面细分特性实践
  4. vc6.0 点击鼠标获取mysql数据库所在行_VC6.0中对MySQL数据库的操作
  5. springboot+vue中小学生课外知识学习网站
  6. issue no route to host 为什么 jmeter 分布式测试,一定要设置 java.rmi.server.hostname--(有效)
  7. 染色问题(n个格子,3种颜色)
  8. H.264/AVC 的分层结构与画面划分
  9. Matlab画图plot(x1,y1,‘ro‘,x1,y1)
  10. angular框架简介基础与使用(全文2w8字)前端框架angular