OpenCV支持大量的轮廓、边缘、边界的相关函数,相应的函数有moments、HuMoments、findContours、drawContours、approxPolyDP、arcLength、boundingRect、contourArea、convexHull、fitEllipse、fitLine、isContourConvex、minAreaRect、minEnclosingCircle、mathcShapes、pointPolygonTest。

目标

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

  • 使用OpenCV函数cv :: boundingRect
  • 使用OpenCV函数cv :: minEnclosingCircle

Code

本教程代码如下所示。您也可以从这里下载

下面这个程序用到的函数有,简单介绍其功能如下:

findContours:找到图像中轮廓

approxPolyDP:对多边形曲线做近似

boundingRect:计算并返回包围轮廓点集的最小矩形

minEnclosingCircle:计算并返回包围轮廓点集的最小圆形及其半径

drawContours:根据轮廓点集和轮廓结构画出轮廓

程序代码及详细注释:

#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>using namespace cv;
using namespace std;
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);/// 函数声明
void thresh_callback(int, void* );int main( int argc, char** argv )
{/// 载入原图像, 返回3通道图像src = imread( "boundrect.jpg" );/// 转化成灰度图像并进行平滑cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 创建窗口char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0);
}void thresh_callback(int, void* )
{Mat threshold_output;vector<vector<Point> > contours;    //轮廓数组(非矩形数组),每个轮廓是一个Point型的vectorvector<Vec4i> hierarchy;                 //见下面findContours的解释/// 使用Threshold二值threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );/// 找到轮廓//contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示
//hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],//分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。//CV_RETR_TREE:建立一个等级树结构的轮廓//findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 多边形逼近轮廓 + 获取矩形和圆形边界框vector<vector<Point> > contours_poly( contours.size() );          //近似后的轮廓点集vector<Rect> boundRect( contours.size() );                           //包围点集的最小矩形vectorvector<Point2f>center( contours.size() );                               //包围点集的最小圆形vectorvector<float>radius( contours.size() );                                   //包围点集的最小圆形半径vectorfor( int i = 0; i < contours.size(); i++ ){approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );      //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集boundRect[i] = boundingRect( Mat(contours_poly[i]) );         //计算并返回包围轮廓点集的最小矩形minEnclosingCircle( contours_poly[i], center[i], radius[i] );     //计算并返回包围轮廓点集的最小圆形及其半径}/// 画多边形轮廓 + 包围的矩形框 + 圆形框Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );for( int i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );   //随机颜色//   drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );drawContours( drawing, contours_poly, i, color, 1, 8, hierarchy, 0, Point() );         //根据轮廓点集contours_poly和轮廓结构hierarchy画出轮廓rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );              //画矩形,tl矩形左上角,br右上角circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );                                        //画圆形}/// 显示在一个窗口namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing );
}

说明

主要功能相当简单,如下所述:

  1. 打开图像,将其转换为灰度,并将其模糊以摆脱噪点。

      src = imread( argv[1], IMREAD_COLOR );cvtColor( src, src_gray, COLOR_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );
  2. 创建一个标题为“Source”的窗口,并在其中显示源文件。 
      const char* source_window = "Source";namedWindow( source_window, WINDOW_AUTOSIZE );imshow( source_window, src );
  3. 在source_window上创建一个跟踪栏,并为其分配一个回调函数。一般来说,回调函数用于对某种信号做出反应,在我们的例子中它是跟踪栏的状态变化。 
      createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
    
  4. 显式的一次性电话thresh_callback是必要的同时显示“轮廓”窗口与“源”窗口。
      thresh_callback( 0, 0 );
    
  5. 等待用户关闭窗口。
      waitKey(0);
    

回调函数thresh_callback执行所有有趣的工作。

  • 写入threshold_output灰度图片的阈值(您可以在这里查看阈值)。
  threshold(src_gray,threshold_output,thresh,255,THRESH_BINARY);
  • 找到轮廓并将其保存到向量contourhierarchy
  findContours(threshold_output,contour,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0));
  • 对于每个找到的轮廓,我们现在将逼近逼近具有精度±3的多边形,并表示曲线必须关闭。

之后,我们为每个多边形找到一个边界,并将其保存boundRect。

最后,我们发现每一个多边形的最小封闭圈,并保存到center和radius载体

  for( size_t i = 0; i < contours.size(); i++ ){approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );boundRect[i] = boundingRect( Mat(contours_poly[i]) );minEnclosingCircle( contours_poly[i], center[i], radius[i] );}

我们发现了我们需要的一切,我们所要做的就是绘制。

  • 创建新的无符号8位字符的Mat,填充零。它将包含我们要制作的所有图纸(直角和圆圈)。
  Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
  • 对于每个轮廓:选择随机颜色,绘制轮廓,边界矩形和最小包围圆,
  for( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours_poly, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );}
  • 显示结果:创建一个新窗口“轮廓”,并显示我们添加到图纸上的所有内容。
  namedWindow( "Contours", WINDOW_AUTOSIZE );imshow( "Contours", drawing );

结果  运行结果:

轮廓查找与绘制——正外接矩形

转载 http://www.cnblogs.com/little-monkey/p/7429381.html

一、简介

二、外接矩形的查找绘制

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 void main()
 4 {
 5     //外接矩形的查找绘制
 6     Mat srcImg =imread("E://12.jpg");
 7     imshow("src",srcImg);
 8     Mat dstImg = srcImg.clone();  //原图备份
 9     cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图
10     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
11
12     vector<vector<Point>> contours;
13     vector<Vec4i> hierarcy;
14     findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
15     vector<Rect> boundRect(contours.size()); //定义外接矩形集合
16     //drawContours(dstImg, contours, -1, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
17     int x0=0, y0=0, w0=0, h0=0;
18     for(int i=0; i<contours.size(); i++)
19     {
20         boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
21         drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
22         x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
23         y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
24         w0 = boundRect[i].width; //获得第i个外接矩形的宽度
25         h0 = boundRect[i].height; //获得第i个外接矩形的高度
26         rectangle(dstImg, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
27     }
28     imshow("boundRect", dstImg);
29     waitKey(0);
30 }

三、分割硬币轮廓并计数

 1 #include "opencv2/opencv.hpp"
 2 #include<iostream>
 3 using namespace cv;
 4 using namespace std;
 5 void main()
 6 {
 7     //分割硬币轮廓
 8     Mat srcImg =imread("E://33.png");
 9     imshow("src", srcImg);
10     Mat dstImg = srcImg.clone();  //原图备份
11     cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图
12     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
13     Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); //获得结构元素
14     dilate(srcImg, srcImg, element); //膨胀操作
15     imshow("dilate",srcImg);
16
17     vector<vector<Point>> contours;
18     vector<Vec4i> hierarcy;
19     findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
20     vector<Rect> boundRect(contours.size()); //定义外接矩形集合
21     int x0=0, y0=0, w0=0, h0=0,num=0;
22     for(int i=0; i<contours.size(); i++)
23     {
24         boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
25         drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
26         x0 = boundRect[i].x;
27         y0 = boundRect[i].y;
28         w0 = boundRect[i].width;
29         h0 = boundRect[i].height;
30         if(w0>30 && h0>30)//筛选
31         {
32             rectangle(dstImg, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
33             num++;
34         }
35     }
36     cout<<"硬币数量:"<<num;
37     imshow("boundRect", dstImg);
38     waitKey(0);
39 }

四、简单车牌字符分隔

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 void main()
 4 {
 5     //---简单车牌字符分隔
 6     Mat srcImg =imread("E://Car2.jpg");
 7     Mat dstImg = srcImg.clone();  //原图备份
 8     medianBlur(srcImg, srcImg, 5);  //中值滤波
 9     cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图
10     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
11     imshow("threshold", srcImg);
12     imwrite("F://car0.jpg", srcImg);
13
14     vector<vector<Point>> contours;
15     vector<Vec4i> hierarcy;
16     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CHAIN_APPROX_NONE); //查找所有轮廓
17     vector<Rect> boundRect(contours.size()); //定义外接矩形集合
18     int x0=0, y0=0, w0=0, h0=0;
19     for(int i=0; i<contours.size(); i++)
20     {
21         boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
22         x0 = boundRect[i].x;
23         y0 = boundRect[i].y;
24         w0 = boundRect[i].width;
25         h0 = boundRect[i].height;
26         if(w0>srcImg.cols/12 && w0<srcImg.cols/5 && h0>srcImg.rows/6 && h0<srcImg.rows*5/6)
27         {
28             char pic_name[10];
29             sprintf(pic_name, "F:\\%d.bmp", i);
30             Mat ROI = dstImg(Rect(x0, y0, w0, h0));
31             imwrite(pic_name, ROI);
32             rectangle(dstImg, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
33         }
34     }
35     imshow("boundRect", dstImg);
36     waitKey(0);
37 }

灰度图上进行透明彩色绘制

为了提取有效的信息并且显示,需要将有效区域用其他颜色画出来

使用opencv circle函数 
首先将单通道灰度图转化成3通道的彩色图像 
实例如下:

  // read imagecv::Mat img_gray = imread(path,0);// create 8bit color image. IMPORTANT: initialize image otherwise it will result in 32Fcv::Mat img_rgb(img_gray.size(), CV_8UC3);// convert grayscale to color imagecv::cvtColor(img_gray, img_rgb, CV_GRAY2RGB);circle(img_rgb, Point(100,100), 30, Scalar(100, 250, 100), -1);//Point圆心中心点,30,半斤,Scalar画笔的参数,-1表示画成实心状态imshow("test", img_rgb);
  • 接下来我们如何能让画的圈为透明的,不遮挡重点显示的区域呢

接下来我们要使用addWeighted函数来实现这个功能,通过实现两张图片进行叠加

Mat overlay;
rgb_img.copyTo(overlay);
circle(overlay, p, 50, Scalar(100, 250, 100), -1);
addWeighted(overlay, 0.3, img_rgb, 0.7, 0, img_rgb);
imshow("test", img_rgb);
waitKey();
  • 最后实现的效果如下:

16位图片转化成为8位图形 ---convertScaleAbs函数

在将RealSense提取的深度图片进行显示时,由于是16位图片,想将图片转化成为8位图形进行显示 
Opencv中有一个函数convertScaleAbs可以实现这种功能 
C++: void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0) 
Parameters: 
src: input array 
dst: output array 
alpha: optional scale factor 
beta: optional delta added to the scaled values 
the governmental definition for the function is : 
On each element of the input array, the function covertScaleAbs performs three operations sequentially: scaling, taking an absolute value, conversion to an unsigned 8-bit type: 
 
接下来示例代码:

cv::Mat map = cv::imread("C:/Users/Lee_gc/Desktop/try.png", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);//read a 16bits depth pictures
double min;
double max;
cv::minMaxIdx(map, &min, &max);
cv::Mat adjMap();
cv::convertScaleAbs(map, adjMap, 255 / max);
imshow("8bitPic", adjMap);//the picture can be showed and converted to 8bits pic
waitKey();

【学习OpenCV】给轮廓画出矩形和圆形边界相关推荐

  1. 给轮廓画出矩形和圆形边界

    OpenCV支持大量的轮廓.边缘.边界的相关函数,相应的函数有moments.HuMoments.findContours.drawContours.approxPolyDP.arcLength.bo ...

  2. OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试

    在图像中寻找轮廓 目标 在这个教程中你将学到如何: 使用OpenCV函数 findContours 使用OpenCV函数 drawContours 原理 例程 教程的代码在下面给出. 你也可以从 这里 ...

  3. 【OpenCV 】计算物体的凸包/创建包围轮廓的矩形和圆形边界框/createTrackbar添加滑动条/

    目录 topic 1:模板匹配 topic 2:图像中寻找轮廓 topic 3:计算物体的凸包 topic 4:轮廓创建可倾斜的边界框和椭圆¶ topic 5:轮廓矩¶ topic 6:为程序界面添加 ...

  4. 检测视频中的人脸,并画出矩形框

    检测视频中的人脸,并画出矩形框,这是一个测试程序,由于很多人经常会用到,写下以备不时之需. #include"stdafx.h" #include <opencv2/core ...

  5. html中矩形坐标,js怎么根据坐标在图片上画出矩形框?

    如图本地上传的图片,并点击获取到这个图片里每个地方的坐标,根据4个角坐标在图片上画出矩形框,该怎么画?大神支招. 我图片是显示在div里的,是不是应该用canvas显示图片? 代码: Document ...

  6. Canvas的使用,根据坐标在图片中画出矩形,框图

    Canvas简介: 是HTML5提供的一种新标签, ie9才开始支持的,Canvas是一个矩形区域的画布,可以用JS控制每一个像素在上面绘画.canvas 标签使用 JavaScript 在网页上绘制 ...

  7. 根据参数,画出矩形。

    试题描述 根据参数,画出矩形. 输入格式 输入一行,包括四个参数:前两个参数为整数,依次代表矩形的高和宽(高不少于3行不多于10行,宽不少于5列不多于10列):第三个参数是一个字符,表示用来画图的矩形 ...

  8. opencv 图像上画出目标运动的轨迹_OpenCV视频分析-Meanshift、Camshift运动轨迹绘制...

    基于均值迁移的对象移动分析(Meanshift) ✏️ ⛳️ 概述 本质: ✔️ Mean Shift均值漂移算法是无参密度估计理论的一种,无参密度估计不需要事先知道对象的任何先验知识,完全依靠训练数 ...

  9. Codeblocks 利用GLUT 画出矩形,直线,三角形,圆形图案并实现翻转,镜像,变色放大缩小等功能

    实验要求:开发一个画图程序,用户可以用鼠标绘制线段.矩形.圆和三角形等.通过菜单让用户选择需要绘制的图元. 注意:一定要加上<windows.h>库否则无法通过编译 #include &l ...

最新文章

  1. 12张PPT看懂中国虚拟数字人产业现状:应用不止于虚拟偶像,2030年市场达2700亿|量子位智库(附下载)...
  2. 盘点“逆市上涨”BZ第一季度回购亮点
  3. (20):数据的准备工作
  4. linux操作命令等积累
  5. 算法—振兴中华(C语言版)
  6. Java虚拟机(JVM)默认字符集详解
  7. 预测分析算法的设计与实现_基于LD(编辑距离算法)的单词速记数据库分析设计与实现...
  8. lib和dll的区别
  9. 饿了么订单--快到碗里来
  10. 工作没做好,别人指出时最好装聋作哑
  11. Atitit mybatis使用简明教程 目录 1.1. Mybatis.xml 配置文件 1 1.2. Datamp.xml mapper文件主要作用是分模块放sql语句 2 1.3. 查询
  12. zigbee协议栈学习(0)
  13. 二十年驷之过隙,互联网归来仍是少年
  14. python 字典类型 get 参数_python如何利用urllib解析url参数成字典
  15. WSJ新闻标题的中心词提取
  16. HTML5 2D平台游戏开发#9蓄力技
  17. 在成都,30岁的人最焦虑
  18. 计算机程序ui设计员工资,ui设计师工资一般多少,发展前景怎么样
  19. miui android系统 流量,小米4 MIUI6系统怎么设置流量功能?小米4 MIUI6流量管理设置?...
  20. FDM3D打印机结构类型总结

热门文章

  1. 如此优秀的你,字节跳动凭什么不给offer?
  2. 【iOS】苹果登录Sign in with Apple
  3. 图解在EXCEL中,通过身份证自动获得出生日期和性别。
  4. 看完牛客网19年测试全部面筋,有了这篇测试面试100问的博客
  5. 乱七八糟之处理器天梯图
  6. openwrt屏蔽广告不生效
  7. 家用洗地机实用吗?家用洗地机款式推荐
  8. Mac OS开发之icns文件
  9. Excel打印不完整
  10. 看云上 ClickHouse 如何做计算存储分离