Goal

在本教程中,您将学习如何:

使用 OpenCV 函数 cv::boundingRect

使用 OpenCV 函数 cv::minEnclosureCircle

Theory

Code

本教程代码如下所示。 你也可以从这里下载 https://github.com/opencv/opencv/tree/4.x/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp

/*** @function generalContours_demo1.cpp* @brief 在图像中查找轮廓的演示代码* @author OpenCV team*/#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>using namespace cv;
using namespace std;Mat src_gray;
int thresh = 100;
RNG rng(12345);/// Function header
void thresh_callback(int, void* );/*** @function main*/
int main( int argc, char** argv )
{//! [setup]/// 加载源图像CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "usage: " << argv[0] << " <Input image>" << endl;return -1;}/// 将图像转换为灰度图并模糊它cvtColor( src, src_gray, COLOR_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );//均值滤波//! [setup]//! [createWindow]/// 创建窗口const char* source_window = "Source";namedWindow( source_window );imshow( source_window, src );//显示源图像//! [createWindow]//! [trackbar]const int max_thresh = 255;createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );//创建滑动条thresh_callback( 0, 0 );//回调//! [trackbar]waitKey();return 0;
}/*** @function thresh_callback*/
void thresh_callback(int, void* )
{//! [Canny]/// 使用 Canny 检测边缘 Detect edges using CannyMat canny_output;Canny( src_gray, canny_output, thresh, thresh*2 );//! [Canny]//! [findContours]/// 寻找轮廓 Find contoursvector<vector<Point> > contours;findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );//! [findContours]//! [allthework]/// 近似轮廓到多边形 + 获得边界矩形和圆形 Approximate contours to polygons + get bounding rects and circlesvector<vector<Point> > contours_poly( contours.size() );//近似轮廓多边形vector<Rect> boundRect( contours.size() );//边界矩形vector<Point2f>centers( contours.size() );//边界圆圆心vector<float>radius( contours.size() );//边界圆半径for( size_t i = 0; i < contours.size(); i++ )//遍历轮廓点{approxPolyDP( contours[i], contours_poly[i], 3, true );//对图像轮廓点进行多边形拟合boundRect[i] = boundingRect( contours_poly[i] );//boundingRect来对指定的点集进行包含,使得形成一个最合适的正向矩形框把当前指定的点集都框住.计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的minEnclosingCircle( contours_poly[i], centers[i], radius[i] );//寻找包裹轮廓的最小圆}//! [allthework]//! [zeroMat]Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );//黑色背景图//! [zeroMat]//! [forContour]/// 绘制多边形轮廓+边界矩形+圆形 Draw polygonal contour + bonding rects + circlesfor( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );//随机颜色drawContours( drawing, contours_poly, (int)i, color );//轮廓多边形rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2 );//矩形circle( drawing, centers[i], (int)radius[i], color, 2 );//圆}//! [forContour]//! [showDrawings]/// 显示结果Show in a windowimshow( "Contours", drawing );//! [showDrawings]
}

Explanation

main 函数比较简单,从注释中我们做了如下:

  1. 打开图像,将其转换为灰度并对其进行模糊处理以消除噪点。

CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );

Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );

if( src.empty() )

{

cout << "Could not open or find the image!\n" << endl;

cout << "usage: " << argv[0] << " <Input image>" << endl;

return -1;

}

cvtColor( src, src_gray, COLOR_BGR2GRAY );

blur( src_gray, src_gray, Size(3,3) );

2. 创建一个带有标题“Source”的窗口并在其中显示源文件。

const char* source_window = "Source";

namedWindow( source_window );

imshow( source_window, src );

3.在 source_window 上创建一个跟踪栏并为其分配一个回调函数。 一般来说,回调函数用于对某种信号做出反应,在我们的例子中是滑动条的状态变化。 要同时显示“轮廓”窗口和“源”窗口,需要显式地一次性调用 thresh_callback。

const int max_thresh = 255;

createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );

thresh_callback( 0, 0 );

回调函数完成了所有有趣的工作。

4. 使用 cv::Canny 检测图像中的边缘。

Mat canny_output;

Canny( src_gray, canny_output, thresh, thresh*2 );

5. 查找轮廓并将它们保存到向量轮廓和层次结构中。

vector<vector<Point> > contours;

findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );

6. 对于每个找到的轮廓,我们现在将近似值应用于精度为 +-3 的多边形,并声明曲线必须是闭合的。 之后,我们为每个多边形找到一个边界矩形并将其保存到 boundRect。 最后,我们为每个多边形找到一个最小包围圆,并将其保存到中心和半径向量。

vector<vector<Point> > contours_poly( contours.size() );

vector<Rect> boundRect( contours.size() );

vector<Point2f>centers( contours.size() );

vector<float>radius( contours.size() );

for( size_t i = 0; i < contours.size(); i++ )

{

approxPolyDP( contours[i], contours_poly[i], 3, true );

boundRect[i] = boundingRect( contours_poly[i] );

minEnclosingCircle( contours_poly[i], centers[i], radius[i] );

}

我们找到了我们需要的一切,我们所要做的就是画画。

7. 创建新的无符号 8 位字符 Mat,用零填充。 它将包含我们要制作的所有图纸(矩形和圆圈)。

Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );

8. 对于每个轮廓:选择一种随机颜色,用它绘制轮廓、边界矩形和最小的封闭圆。

for( size_t i = 0; i< contours.size(); i++ )

{

Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );

drawContours( drawing, contours_poly, (int)i, color );

rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2 );

circle( drawing, centers[i], (int)radius[i], color, 2 );

}

9. 显示结果:创建一个新窗口“轮廓”并在其上显示我们添加到图纸中的所有内容。

imshow( "Contours", drawing );

Result

参考:

cv.approxPolyDP多边拟合函数

 cv.approxPolyDP() 的参数1是源图像的某个轮廓;参数2(epsilon)是一个距离值,表示多边形的轮廓接近实际轮廓的程度,值越小,越精确;参数3表示是否闭合。

C++: void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)

参数详解;

InputArray curve:一般是由图像的轮廓点组成的点集

OutputArray approxCurve:表示输出的多边形点集,当前点集是能最小包容指定点集的。draw出来即是一个多边形;

double epsilon:主要表示输出的精度,也即是原始曲线与近似曲线之间的最大距离。

bool closed:表示输出的多边形是否封闭

openCV之approxPolyDP()多边拟合函数_zhangweiwei1516的博客-CSDN博客_approxpolydp 获取四个角点

寻找包裹轮廓的最小圆:minEnclosingCircle 函数

返回圆应满足:① 轮廓上的点均在圆形空间内。② 没有面积更小的满足条件的圆。

void minEnclosingCircle(InputArray points, Point2f& center, float& radius);

points,输入的二维点集,可以是 vector 或 Mat 类型。

center,圆的输出圆心。

radius,圆的输出半径。

opencv —— minEnclosingCircle、fitEllipse 寻找包裹轮廓的最小圆、点集拟合椭圆 - 老干妈就泡面 - 博客园 (cnblogs.com)

OpenCV—Python 轮廓检测 绘出矩形框(findContours\ boundingRect\rectangle)_javastart的博客-CSDN博客_findcontours 矩形

Opencv视觉学习--Rect、RotatedRect类与boundingRect( )、minAreaRect( )、fitEllipse( )函数_佳佳鸽的博客-CSDN博客

minAreaRect( )函数返回参数如图:

角点顺序是固定以最下面的点为P[0],顺时针依次递增编号的。将水平轴逆时针旋转,最先与水平轴平行的边作为宽width,另外一条边则为高height,并非长的就是height,短的就是width。而角度则直接取最先与水平轴平行的边与水平轴的夹角,取值范围[-90~0]。

fitEllipse( )函数返回参数如图:

角度参数angle 是椭圆中心center发出的平行于x轴的射线,顺时针旋转,与椭圆短轴的夹角,取值范围 [ 0 ~ 180 ]。椭圆的短轴为参数宽width,长轴为参数长height。

【opencv 450 Image Processing】Creating Bounding boxes and circles for contours为轮廓创建边界框和圆相关推荐

  1. OpenCV为轮廓创建边界框和圆

    OpenCV为轮廓创建边界框和圆 为轮廓创建边界框和圆 目标 代码 解释 结果 为轮廓创建边界框和圆 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: boundingRect 使用O ...

  2. OpenCV为轮廓创建边界旋转框和椭圆

    OpenCV为轮廓创建边界旋转框和椭圆 为轮廓创建边界旋转框和椭圆 目标 代码 结果 为轮廓创建边界旋转框和椭圆 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: minAreaRec ...

  3. 【opencv 450 Image Processing】Image Moments 图像矩

    Goal 在本教程中,您将学习如何: 使用 OpenCV 函数 cv::moments 使用 OpenCV 函数 cv::contourArea 使用 OpenCV 函数 cv::arcLength ...

  4. 【opencv 450 Image Processing】Periodic Noise Removing Filter周期性去噪滤波器

    Periodic Noise Removing Filter 周期性去噪滤波器 OpenCV: Periodic Noise Removing Filter Goal 在本教程中,您将学习:    如 ...

  5. 【opencv 450 Image Processing】Hit-or-Miss

    Goal 在本教程中,您将学习如何使用 Hit-or-Miss 变换(也称为 Hit-and-Miss 变换)在二进制图像中找到给定的配置或模式(-1对应背景,1对应前景.找到邻域与内核模式一样的像素 ...

  6. 【opencv 450 Image Processing】Anisotropic image segmentation by a gradient structure tensor

    Anisotropic image segmentation by a gradient structure tensor 梯度结构张量的各向异性图像分割 Goal 在本教程中,您将学习: 梯度结构张 ...

  7. 【NIPS 2020】Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for...译读笔记

    论文名称 Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Dete ...

  8. (NeurIPS 2019) Learning Object Bounding Boxes for 3D Instance Segmentation on Point Clouds

    Abstract 我们提出了一种新颖的.概念上简单的通用框架,用于在3D点云上进行实例分割.我们的方法称为3D-BoNet,遵循每点多层感知器(MLP)的简单设计理念.该框架直接回归点云中所有实例的3 ...

  9. [GFL]Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Dete

    Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Detection ...

  10. 目标、物体识别(检测)object detection 中的 bounding boxes 是什么? 边界区域、边界框、边界盒

    边界区域.边界框.边界盒 参考文章:人脸检测中的bounding box regression详解

最新文章

  1. 生物信息学 Python 入门之源码安装
  2. SpringSecurity实战:基于mysql自定义SpringSecurity权限认证规则
  3. 7 种常用的排序算法直观感受
  4. java getaccessflags_Java Method.getAccessFlags方法代码示例
  5. 【IM】关于监督降维的理解
  6. 创建和准备Oracle样例数据库
  7. 关于Unable to execute dex: Java heap space 解决办法
  8. 高斯白噪声下基于EM的多径时延估计
  9. 前端学习(1152):let经典面试题2
  10. java 序列化保存_保存到二进制/序列化Java
  11. celery-01-异步任务模块-解决发送邮件的延时问题
  12. PHP-Open Flash Chart注意事项
  13. cisco 基本命令
  14. Akamai:三季度DDoS攻击总数同比上涨138% 规模超100 Gbps
  15. 计算机专业窗体的事件何时触发,高三计算机专业VB试题(六)1
  16. 医学生学计算机建议,医学生计算机能力的培养
  17. Java基础 DAY15
  18. 基于js的网页计算器实现
  19. Lenovo Thinkpad BIOS中开启VT虚拟化后无法生效?
  20. 计算机打字手怎么放,打字时如何正确放置手指

热门文章

  1. Vue 开源项目库汇总
  2. python - 啃书 第八章 正则表达式
  3. magedu第一天学习(计算机基础部分)
  4. 上午在改BUG,下午就通知被裁了
  5. 十大超越人类极限的未来技术
  6. 利用 Maxima 求解常微分方程
  7. 微信端input输入框在ios手机上连续输入卡顿
  8. python 删除特定列_pandas删除某一列的方法(drop函数)
  9. 嘿~全流程带你基于Pytorch手撸图片分类“框架“--HuClassify
  10. 【JAVA笔记】JAVA调用同一个包里的不同类的方法: