opencv中findContours 和drawContours画图函数
来源:互联网 发布:步态分析数据 编辑:程序博客网 时间:2024/05/18 01:29
由于小博出来游玩,最近还几天没有发帖了,没事在这看看opencv3.1版本的samples,在运行contours时,发现这个小例子还挺有趣的,不多说,我先贴出图,待会儿再细细讲解,各位请自行玩耍
首先我么导入库文件
#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <math.h>#include <iostream>
使用opencv命名空间
using namespace cv;using namespace std;
几行解释,让读者更好的了解你的目的,演示什么样的事例(opencv自带):
static void help(){ cout << "\nThis program illustrates the use of findContours and drawContours\n" << "The original image is put up along with the image of drawn contours\n" << "Usage:\n" << "./contours2\n" << "\nA trackbar is put up which controls the contour level from -3 to 3\n" << endl;}
接下来我们分别定义了这个鬼脸的个数(不知道怎么称呼这个图,叫鬼脸吧),调节滚轮,createTrackbar
窗口中快速创建一个滑动控件,用于手动调节阈值,具有非常直观的效果。
函数原型:
int createTrackbar(const string& trackbarname, const string& winname,
int* value, int count,
TrackbarCallback onChange = 0,
void* userdata = 0);
参数说明:
trackbarname:滑动空间的名称;
winname:滑动空间用于依附的图像窗口的名称;
value:初始化阈值;
count:滑动控件的刻度范围;
TrackbarCallback是回调函数。存储轮廓的点集向量以及hierarchy;我们可以先了解一下findContours这个函数才能往后继续学习,findContours函数,这个函数的原型为:
void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierar-
chy, int mode, int method, Point offset=Point())
参数说明
输入图像image必须为一个2值单通道图像(一般用这个函数的时候是对二值化图像操作的)
contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示(这也就是为啥定义一个courtours了)
hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。
mode表示轮廓的检索模式
CV_RETR_EXTERNAL表示只检测外轮廓CV_RETR_LIST检测的轮廓不建立等级关系CV_RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。CV_RETR_TREE建立一个等级树结构的轮廓。具体参考contours.c这个demo
method为轮廓的近似办法
CV_CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1CV_CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
offset表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。
findContours后会对输入的2值图像改变,所以如果不想改变该2值图像,需创建新mat来存放,findContours后的轮廓信息contours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似
contourArea函数可以得到当前轮廓包含区域的大小,方便轮廓的筛选
findContours经常与drawContours配合使用
static void on_trackbar(int, void*){ Mat cnt_img = Mat::zeros(w, w, CV_8UC3); int _levels = levels - 3; drawContours(cnt_img, contours, _levels <= 0 ? 3 : -1, Scalar(128, 255, 255), 3, LINE_AA, hierarchy, std::abs(_levels)); imshow("contours", cnt_img);}
ellipse()画椭圆弧函数
功能: 函数ellipse()使用当前绘图色画一椭圆弧。
用法: 该函数调用方式为void ellipse(int x,int y,int startangle,int endangle,
int xradius,int yradius);
说明: 参数x,y为椭圆中心坐标,startangle和endangle为给定的起始角和终止角,xradius与yradius为椭圆的x轴半径与y轴半径,如果startangle为0 ,endangle等于360度,那么画出的是个完整的椭圆。ellipse()函数不同于arc()和circle()函数,屏显纵横比不能自动调节。若需要的是成比例的半径而不是特定的像素距离,则y轴距离必须调节为yradius*aspectratio(y轴半径乘以纵横比)。
此函数对应的头文件为graphics.h
返回值: 无
例: 在屏幕上画一个鸡蛋形的椭圆。
#include<graphics.h>void main(){ int driver,mode; driver=DETECT; mode=0; initgraph(&driver,&mode,""); ellipse(200,100,0,360,80,40); getch(); restorecrtmode();}
接下来我们上程序吧
int main(int argc, char** argv){ cv::CommandLineParser parser(argc, argv, "{help h||}"); if (parser.has("help")) { help(); return 0; } Mat img = Mat::zeros(w, w, CV_8UC1); //(定义一个500*500的图像) //我们先画一个原图吧,六个鬼脸 for (int i = 0; i < 6; i++) { int dx = (i % 2) * 250 - 30; int dy = (i / 2) * 150; const Scalar white = Scalar(255); const Scalar black = Scalar(0);// int cvRound (double value) opencv里的一个函数,对一个double型的数进行四舍五入,并返回一个整型数! if (i == 0) { for (int j = 0; j <= 10; j++) { double angle = (j + 5)*CV_PI / 21; line(img, Point(cvRound(dx + 100 + j * 10 - 80 * cos(angle)), cvRound(dy + 100 - 90 * sin(angle))), Point(cvRound(dx + 100 + j * 10 - 30 * cos(angle)), cvRound(dy + 100 - 30 * sin(angle))), white, 1, 8, 0); } } ellipse(img, Point(dx + 150, dy + 100), Size(100, 70), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 115, dy + 70), Size(30, 20), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 185, dy + 70), Size(30, 20), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 115, dy + 70), Size(15, 15), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 185, dy + 70), Size(15, 15), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 115, dy + 70), Size(5, 5), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 185, dy + 70), Size(5, 5), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 150, dy + 100), Size(10, 5), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 150, dy + 150), Size(40, 10), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 27, dy + 100), Size(20, 35), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 273, dy + 100), Size(20, 35), 0, 0, 360, white, -1, 8, 0); } //show the faces namedWindow("image", 1); imshow("image", img); //提取轮廓 vector<vector<Point> > contours0; findContours(img, contours0, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); contours.resize(contours0.size()); for (size_t k = 0; k < contours0.size(); k++) approxPolyDP(Mat(contours0[k]), contours[k], 3, true);/*opencv中利用函数approxPolyDP来对指定的点集进行逼近,其逼近的精度是可设置的,void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);InputArray curve:输入的点集OutputArray approxCurve:输出的点集,当前点集是能最小包容指定点集的。draw出来即是一个多边形;double epsilon:指定的精度,也即是原始曲线与近似曲线之间的最大距离。bool closed:若为true,则说明近似曲线是闭合的,它的首位都是相连,反之,若为false,则断开。*/ namedWindow("contours", 1); createTrackbar("levels+3", "contours", &levels, 7, on_trackbar); on_trackbar(0, 0); waitKey(); return 0;}
接下来我们把所有代码放上来吧,大家自行copy吧:
#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <math.h>#include <iostream>using namespace cv;using namespace std;static void help(){ cout << "\nThis program illustrates the use of findContours and drawContours\n" << "The original image is put up along with the image of drawn contours\n" << "Usage:\n" << "./contours2\n" << "\nA trackbar is put up which controls the contour level from -3 to 3\n" << endl;}const int w = 500;int levels = 3;vector<vector<Point> > contours;vector<Vec4i> hierarchy;static void on_trackbar(int, void*){ Mat cnt_img = Mat::zeros(w, w, CV_8UC3); int _levels = levels - 3; drawContours(cnt_img, contours, _levels <= 0 ? 3 : -1, Scalar(128, 255, 255), 3, LINE_AA, hierarchy, std::abs(_levels)); imshow("contours", cnt_img);}int main(int argc, char** argv){ cv::CommandLineParser parser(argc, argv, "{help h||}"); if (parser.has("help")) { help(); return 0; } Mat img = Mat::zeros(w, w, CV_8UC1); //Draw 6 faces for (int i = 0; i < 6; i++) { int dx = (i % 2) * 250 - 30; int dy = (i / 2) * 150; const Scalar white = Scalar(255); const Scalar black = Scalar(0); if (i == 0) { for (int j = 0; j <= 10; j++) { double angle = (j + 5)*CV_PI / 21; line(img, Point(cvRound(dx + 100 + j * 10 - 80 * cos(angle)), cvRound(dy + 100 - 90 * sin(angle))), Point(cvRound(dx + 100 + j * 10 - 30 * cos(angle)), cvRound(dy + 100 - 30 * sin(angle))), white, 1, 8, 0); } } ellipse(img, Point(dx + 150, dy + 100), Size(100, 70), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 115, dy + 70), Size(30, 20), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 185, dy + 70), Size(30, 20), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 115, dy + 70), Size(15, 15), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 185, dy + 70), Size(15, 15), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 115, dy + 70), Size(5, 5), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 185, dy + 70), Size(5, 5), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 150, dy + 100), Size(10, 5), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 150, dy + 150), Size(40, 10), 0, 0, 360, black, -1, 8, 0); ellipse(img, Point(dx + 27, dy + 100), Size(20, 35), 0, 0, 360, white, -1, 8, 0); ellipse(img, Point(dx + 273, dy + 100), Size(20, 35), 0, 0, 360, white, -1, 8, 0); } //show the faces namedWindow("image", 1); imshow("image", img); //Extract the contours so that vector<vector<Point> > contours0; findContours(img, contours0, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); contours.resize(contours0.size()); for (size_t k = 0; k < contours0.size(); k++) approxPolyDP(Mat(contours0[k]), contours[k], 3, true); namedWindow("contours", 1); createTrackbar("levels+3", "contours", &levels, 7, on_trackbar); on_trackbar(0, 0); waitKey(); return 0;}
- opencv中findContours 和drawContours画图函数
- opencv findContours和drawContours使用方法
- OPENCV轮廓提取findContours和drawContours
- OPENCV轮廓提取findContours和drawContours
- OPENCV轮廓提取findContours和drawContours
- OpenCV Tutorial: 輪廓(findContours、drawContours)
- findContours和drawContours的使用
- findContours && drawContours
- 提取图像轮廓--findContours函数、drawContours函数
- Opencv drawContours函数用于绘制和填充
- 轮廓提取--findContours()和drawContours()
- Opencv drawContours函数
- OpenCV学习笔记(23)findContours与drawContours
- OpenCV中findContours函数的使用
- Opencv中 findContours 函数参数说明
- 輪廓(findContours、drawContours)
- opencv.cv2.findContours()函数
- OpenCV - findContours函数使用
- u-boot移植--3、DM9000网卡移植
- Elastic Search权威指南 第五章 结构化查询
- 不要62
- 设计模式之装饰者模式
- Oracle之使用proc查询多行数据
- opencv中findContours 和drawContours画图函数
- Elastic Search权威指南 第七章 分布式搜索
- ReentrantLock的lock-unlock流程详解
- Java设计模式之迭代器模式
- 老罗:我的奋斗
- 最近一段时间的计划(个人)
- 字典和选择器
- 二叉树的创建|非递归遍历
- python实现KD树模型