广东省建设局网站,下载app下载,公司网页制作官网,适合做网页的主题OpenCV学习笔记#xff08;十七#xff09;#xff1a;查找并绘制轮廓#xff1a;findContours()
1、findContours() 函数
该函数使用Suzuki85算法从二值图像中检索轮廓。轮廓线是一种用于形状分析、目标检测和识别的有效工具。 opencv轮廓检测之FindContours函数算法解释…OpenCV学习笔记十七查找并绘制轮廓findContours()
1、findContours() 函数
该函数使用Suzuki85算法从二值图像中检索轮廓。轮廓线是一种用于形状分析、目标检测和识别的有效工具。 opencv轮廓检测之FindContours函数算法解释 该函数从二值图像中检索轮廓并返回检索到的轮廓数。函数将填充指针first_contour。它将包含指向第一个最外层轮廓的指针如果没有检测到轮廓则为空(如果图像是完全黑色的)。可以使用h_next和v_next链接从first_contour到达其他轮廓。绘制等值线讨论中的示例说明了如何使用等值线进行连接组件检测。轮廓还可以用于形状分析和对象识别-请参阅OpenCV示例目录中的squares.c。
void findContours(
InputOutputArray image, // 要绘制轮廓的图像,8位单通道的图像256级灰度图
OutputArrayOfArrays contours, // 所有输入的轮廓找到的轮廓其中每个轮廓会被存储为vectorPoint,// 所以contours的类型就是vectorvectorPoint。
OutputArray hierarchy, // 层次结构可选的输出向量包含关于图像的拓扑结构信息。// 其具有跟轮廓数相同的元素个数,类型为vectorVec4i// 后一个轮廓、前一个轮廓、第一个子轮廓、父轮廓的索引编号如果没有对应项该值设置为-1
int mode, // 检索轮廓的模式分别表示
int method, // 为轮廓的近似办法
Point offsetPoint() // 代表轮廓点的偏移量可以设置为任意值。
);
mode
RETR_EXTERNAL 表示只检测外轮廓
RETR_LIST 检测的轮廓不建立等级关系
RETR_CCOMP 建立两个等级的轮廓上面的一层为外边界里面的一层为内孔的边 界信息。如果内孔内还有一个连通物体这个物体的边界也在顶层。
RETR_TREE 建立一个等级树结构的轮廓。具体参考contours.c这个demo
method
CHAIN_APPROX_NONE 存储所有的轮廓点相邻的两个点的像素位置差不超过1即maxabsx1-x2absy2-y11
CHAIN_APPROX_SIMPLE 压缩水平方向垂直方向对角线方向的元素只保留该方向的终点坐标例如一个矩形轮廓只需4个点来保存轮廓信息
CHAIN_APPROX_TC89_L1CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法 2、drawContours()函数
该函数使用算法从二值图像中检索轮廓。绘制轮廓线或填充轮廓线。如果厚度≥0该函数在图像中绘制轮廓轮廓;如果厚度0则填充轮廓边界区域。 参考博客 轮廓的层级关系详解 OpenCV中findcontours函数hierarchy轮廓层级详解
void drawContours(
InputOutputArray image, // 要绘制轮廓的图像
InputArrayOfArrays contours, // 所有输入的轮廓每个轮廓被保存成一个point向量(vectorvectorPoint)
int contourIdx, // 指定要绘制轮廓的编号如果是负数则绘制所有的轮廓
const Scalar color, // 绘制轮廓所用的颜色
int thickness1, // 绘制轮廓的线的粗细如果是负数则轮廓内部被填充(CV_FILLED 填充内部)
int lineType8, // 绘制轮廓的线的连通性(LINE_AA 抗锯齿线形)
InputArray hierarchynoArray(), // 关于层级的可选参数只有绘制部分轮廓时才会用到hierarchyhierarchy绘制所有轮廓
int maxLevelINT_MAX, // 绘制轮廓的最高级别这个参数只有hierarchy有效的时候才有效
Point offsetPoint() // 代表轮廓点的偏移量可以设置为任意值
)
maxLevel
maxLevel0绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓
maxLevel1, 绘制与输入轮廓同一等级的所有轮廓与其子节点。
maxLevel2绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点3、approxPolyDP()函数
以指定的精度近似生成多边形曲线。 函数逼近一条曲线或另一条曲线/顶点较少的多边形使它们之间的距离小于或等于指定的精度。它使用Douglas-Peucker算法
void approxPolyDP(
InputArray curve, // 输入的点集存储在std::vector或Mat中的二维点的输入向量
OutputArray approxCurve, // 输出的点集当前点集是能最小包容指定点集的。draw出来即是一个多边形
double epsilon, // 指定的精度也即是原始曲线与近似曲线之间的最大距离。
bool closed // 若为true,则说明近似曲线是闭合的它的首位都是相连反之若为false则断开。
);4、示例一
#include opencv2/opencv.hppusing namespace cv;
using namespace std;int main()
{QCoreApplication a(argc, argv);// 1、加载源图像//Mat srcImage imread( F:/C/2. OPENCV 3.1.0/TEST/a.jpg, 1 );Mat srcImage imread( F:/C/2. OPENCV 3.1.0/TEST/test3.png, 1 );if(!srcImage.data ) { printf(读取图片错误请确定目录下是否有imread函数指定图片存在~ \n); return false; }cvtColor(srcImage,srcImage,CV_BGR2GRAY);// 2、初始化结果图Mat dstImage Mat::zeros(srcImage.size(), CV_8UC3);Mat dstImage1 dstImage.clone();// 3、srcImage取大于阈值119的那部分//threshold(srcImage,srcImage,119,255,THRESH_BINARY);srcImage srcImage 119; // 取 阈值大于119imshow( 取阈值后的原始图, srcImage );// 4、定义轮廓和层次结构// 储存所有轮廓每个轮廓为一个点向量集// 储存每个轮廓的层次元素hierarchy[i][0]~hierarchy[i][1] 分别表示后一个、前一个、父轮廓、内嵌轮廓的索引编号vectorvectorPoint contours;vectorVec4i hierarchy;// 5、查找轮廓// RETR_EXTERNAL 表示只检测外轮廓// RETR_LIST 检测的轮廓不建立等级关系// RETR_CCOMP 建立两个等级的轮廓上面的一层为外边界里面的一层为内孔的边 界信息。如果内孔内还有一个连通物体这个物体的边界也在顶层。// RETR_TREE 建立一个等级树结构的轮廓。具体参考contours.c这个demo// CHAIN_APPROX_NONE 存储所有的轮廓点相邻的两个点的像素位置差不超过1即maxabsx1-x2absy2-y11// CHAIN_APPROX_SIMPLE 压缩水平方向垂直方向对角线方向的元素只保留该方向的终点坐标例如一个矩形轮廓只需4个点来保存轮廓信息// CHAIN_APPROX_TC89_L1CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法findContours( srcImage, contours, hierarchy,CV_RETR_CCOMP ,CV_CHAIN_APPROX_SIMPLE );cout轮廓数量contours.size()endl;// 6、遍历所有顶层的轮廓 以随机颜色绘制出每个连接组件颜色// hierarchy[index][0] 表示该某轮廓点集的后一个轮廓点集 索引号// hierarchy[index][1] 表示该某轮廓点集的前一个轮廓点集 索引号// hierarchy[index][2] 表示该某轮廓点集的第一个子轮廓内嵌点集 索引号// hierarchy[index][3] 表示该某轮廓点集的父轮廓点集 索引号for( int index 0; index 0; index hierarchy[index][0] ) // 绘制轮廓//for( int index 0; index contours.size(); index ) // 绘制所有内外轮廓{Scalar color( rand()255, rand()255, rand()255 );drawContours( dstImage, contours, index, color, 1, 8,hierarchy ); //CV_FILLED}// // 7、检测到的所有轮廓分别用不同颜色画出来
// for(size_t j0; jcontours.size(); j)
// {
// Scalar color( rand()255, rand()255, rand()255 ); // 为每个轮廓新建随机颜色
// for (size_t i 0; i contours[j].size(); i)
// {
// // 绘制边缘
// line(dstImage1, contours[j][i], contours[j][(i 1) % contours[j].size()], color, 1, 8);
// }
// }// 8、显示最后的轮廓图imshow( 轮廓图, dstImage );//imshow( 边缘图, dstImage1 );waitKey(0);return 0;
}结果 分析 1“0轮廓的下一条轮廓是1轮廓”“1轮廓的下一条3轮廓” 22轮廓和3轮廓的下一条没有 30轮廓和2轮廓上一条是-1表示没有 4“1轮廓的子轮廓是2轮廓”其他的轮廓没有子轮廓。1轮廓包含2轮廓 50、1、3轮廓没有父轮廓说明其为最外层轮廓且为同级轮廓 PS轮廓层次关系 看hierarchy[index][2]和hierarchy[index][3]的值
5、示例二
#include opencv2/opencv.hppusing namespace cv;
using namespace std;int levels 3; // 精度等级
Mat img;
RNG g_rng(12345);
vectorvectorPoint contours,contours0;
vectorVec4i hierarchy;int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 1、 读取图片img imread( F:/C/2. OPENCV 3.1.0/TEST/face.png, 0 );if(!img.data ) { printf(读取图片错误请确定目录下是否有imread函数指定图片存在~ \n); return false; }imshow( image, img );// // 绘制6个人脸用于测试
// // 创建 500*500 单通道矩阵 灰度图
// Mat img Mat::zeros(w, w, CV_8UC1);
// 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 (j5)*CV_PI/21;
// line(img, Point(cvRound(dx100j*10-80*cos(angle)),
// cvRound(dy100-90*sin(angle))),
// Point(cvRound(dx100j*10-30*cos(angle)),
// cvRound(dy100-30*sin(angle))), white, 1, 8, 0);
// }
// }
// ellipse( img, Point(dx150, dy100), Size(100,70), 0, 0, 360, white, -1, 8, 0 );
// ellipse( img, Point(dx115, dy70), Size(30,20), 0, 0, 360, black, -1, 8, 0 );
// ellipse( img, Point(dx185, dy70), Size(30,20), 0, 0, 360, black, -1, 8, 0 );
// ellipse( img, Point(dx115, dy70), Size(15,15), 0, 0, 360, white, -1, 8, 0 );
// ellipse( img, Point(dx185, dy70), Size(15,15), 0, 0, 360, white, -1, 8, 0 );
// ellipse( img, Point(dx115, dy70), Size(5,5), 0, 0, 360, black, -1, 8, 0 );
// ellipse( img, Point(dx185, dy70), Size(5,5), 0, 0, 360, black, -1, 8, 0 );
// ellipse( img, Point(dx150, dy100), Size(10,5), 0, 0, 360, black, -1, 8, 0 );
// ellipse( img, Point(dx150, dy150), Size(40,10), 0, 0, 360, black, -1, 8, 0 );
// ellipse( img, Point(dx27, dy100), Size(20,35), 0, 0, 360, white, -1, 8, 0 );
// ellipse( img, Point(dx273, dy100), Size(20,35), 0, 0, 360, white, -1, 8, 0 );
// }// 显示
// namedWindow( image, 1 );
// imshow( image, img );// 2、提取轮廓findContours( img, contours0, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);// 3、对轮廓进行逼近 获得多边形曲线轮廓向量点集contours.resize(contours0.size());for( size_t k 0; k contours0.size(); k )approxPolyDP(Mat(contours0[k]), contours[k], 0.1, true);// 4、滑动条调用// 设置轨迹条控制从-3到3的轮廓等级namedWindow( contours, 1 );createTrackbar( levels3, contours, levels, 7, on_trackbar );on_trackbar(0,0);// 初次调用waitKey(0);return a.exec();
}轮廓控制回调函数
static void on_trackbar(int, void*)
{// 1、创建目标图像Mat cnt_img Mat::zeros(img.rows, img.cols, CV_8UC3);// 2、处理参数int _levels levels - 3;// 3、绘制轮廓// _levels 0 ? 3 : -1Scalar color Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//任意值drawContours( cnt_img, contours,_levels 0 ? 3 : -1, Scalar(128,255,255),1, LINE_AA, hierarchy, std::abs(_levels) ); imshow(contours, cnt_img);
}结果