首页 > 编程知识 正文

findcounters函数,Python输出向量维度

时间:2023-05-05 01:41:40 阅读:127067 作者:3617

findcontours和drawcontours函数参数,函数原理,源码理解非常详细的讲解

void findContours//用于提取图像轮廓的轮廓提取

输入图像是8位单通道图像,需要转换为2值

OutputArrayOfArrays contours,//检测到的轮廓,每个轮廓表示为点向量

可选输出向量,包括OutputArray hierarchy,//图像的拓扑信息。 在此,要素的数量与检测出的轮廓的数量相等

int mode,//说明所需的配置文件类型和所需返回值的方式

int method,//轮廓近似方法

点offset=point (

void drawContours//绘制用于绘制检测到的图像轮廓的轮廓

InputOutputArray image,//绘制轮廓的图像

InputArrayOfArrays contours,//输入的所有轮廓都存储为每个轮廓的一个点向量

int contourIdx,//指定绘制轮廓的编号,负数时绘制所有轮廓

常数标量颜色,//用于绘制轮廓的颜色

int thickness=1,//绘制轮廓的线宽,负数时填充轮廓内部

int lineType=8,/绘制轮廓的线条连接性

InputArray hierarchy=noArray (),//级别的可选参数仅在绘制轮廓的一部分时使用

int maxLevel=INT_MAX,//绘制轮廓的最高级别。 此参数仅在启用hierarchy时有效

//maxLevel=0,绘制与输入配置文件属于同一级别的所有配置文件,即输入配置文件及其相邻的配置文件

//maxLevel=1,绘制与输入轮廓同一级别的所有轮廓和可承受的店员节点。

//maxLevel=2,绘制与输入配置文件级别相同的所有配置文件和容错店员节点以及子节点的子节点

点offset=point (

Opencv使用findContours函数,只需几个简单的步骤就可以检测出物体的轮廓,非常方便。 它们将继续讨论findContours方法中每个参数的含义和用法。 例如,如何要求只检测最外层的轮廓? contours中的数据结构是什么样的? hierarchy到底是什么鬼? Point ()用于什么?

首先从findContours函数的原型来看。

[ CPP ]视图plain copy

查找内容(inputoutputarrayimage,OutputArrayOfArrays contours,

输出阵列高速缓存,int mode,

int method,Point offset=Point ();

第一个参数: image,单通道图像矩阵可以是灰度图,但更常用的是二值图像,一般为Canny、cjdz等埃

第二个参数: contours定义为“vectorvector contours”,是向量,而且是双向量。 向量内的各要素保持由连续点构成的点集合的向量,各点集为轮廓。 有多少轮廓,向量contours有多少元素?

第三个参数:定义为“向量层次”的层次。 我们先来看看Vec4i的定义。

typedef Vecint,4 Vec4i; Vec4i是Vecint,4的别名,定义“向量中的每个元素包含四个int类型变量”向量。 因此,从定义上讲,hierarchy也是一个向量,向量中的每个元素都包含一个包含四个int整数的数组。 向量hiararchy内的要素和轮廓向量contours内的要素一一对应,向量的容量相同。 hierarchy向量中每个元素的四个int类型变量—— hierarchy [ I ] [0]到hierarchy [ I ] [3]分别为第I个轮廓的下一个轮廓、上一个轮廓、父轮廓和嵌入轮廓的索引如果没有与当前轮廓对应的下一个轮廓、上一个轮廓、父轮廓或嵌入轮廓,则hierarchy [ I ] [0]到hierarchy [ I ] [3]的相应位将设置为默认值-1。 第四个参数: int型模式,定义轮廓搜索模式:

取值CV_RE

TR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略 取值二:CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到 取值三:CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层。两个等级关系:顶层为连通域的外围边界,次层为孔的内层边界(比如后文的h00、h01、h0000、h0100)。 取值四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

两种轮廓:外部轮廓(橙色虚线)或者孔(蓝色点线)。

mode的值决定把找到的轮廓如何挂到轮廓树节点变量(h_prev, h_next, v_prev, v_next)上。图2展示了四种可能的mode值所得到的结果的拓扑结构。

图2 轮廓连接方法

第五个参数:int型的method,定义轮廓的近似方法:

取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内 取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留 取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

第六个参数:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!

下边用效果图对比一下findContours函数中各参数取不同值时,向量contours和hierarchy的内容如何变化,有何异同。

主体程序如下:

[

cpp] view plain copy #include "core/core.hpp" #include "highgui/highgui.hpp" #include "imgproc/imgproc.hpp" #include "iostream" using namespace std; using namespace cv; int main(int argc,char *argv[]) { Mat imageSource=imread(argv[1],0); imshow("Source Image",imageSource); Mat image; GaussianBlur(imageSource,image,Size(3,3),0); Canny(image,image,100,250); vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(image,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point()); Mat imageContours=Mat::zeros(image.size(),CV_8UC1); Mat Contours=Mat::zeros(image.size(),CV_8UC1); //绘制 for(int i=0;i<contours.size();i++) { //contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数 for(int j=0;j<contours[i].size();j++) { //绘制出contours向量内所有的像素点 Point P=Point(contours[i][j].x,contours[i][j].y); Contours.at<uchar>(P)=255; } //输出hierarchy向量内容 char ch[256]; sprintf(ch,"%d",i); string str=ch; cout<<"向量hierarchy的第" <<str<<" 个元素内容为:"<<endl<<hierarchy[i]<<endl<<endl; //绘制轮廓 drawContours(imageContours,contours,i,Scalar(255),1,8,hierarchy); } imshow("Contours Image",imageContours); //轮廓 imshow("Point of Contours",Contours); //向量contours内保存的所有轮廓点集 waitKey(0); return 0; }

程序中所用原始图像如下:

通过调整第四个参数mode——轮廓的检索模式、第五个参数method——轮廓的近似方式和不同的偏移量Point(),就可以得到以下效果。

一、mode取值“CV_RETR_EXTERNAL”,method取值“CV_CHAIN_APPROX_NONE”,即只检测最外层轮廓,并且保存轮廓上所有点:

轮廓:

只有最外层的轮廓被检测到,内层的轮廓被忽略

contours向量内所有点集:

保存了所有轮廓上的所有点,图像表现跟轮廓一致

hierarchy向量:

重温一下hierarchy向量————向量中每个元素的4个整形分别对应当前轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。

本次参数配置下,hierarchy向量内有3个元素,分别对应于3个轮廓。以第2个轮廓(对应向量内第1个元素)为例,内容为[2,0,-1,-1], “2”表示当前轮廓的后一个轮廓的编号为2,“0”表示当前轮廓的前一个轮廓编号为0,其后2个“-1”表示为空,因为只有最外层轮廓这一个等级,所以不存在父轮廓和内嵌轮廓。

二、 mode取值“CV_RETR_LIST”,method取值“CV_CHAIN_APPROX_SIMPLE”,即检测所有轮廓,但各轮廓之间彼此独立,不建立等级关系,并且仅保存轮廓上拐点信息:

检测到的轮廓跟上文“一”中是一致的,不再显示。

contours向量内所有点集:

contours向量中所有的拐点信息得到了保留,但是拐点与拐点之间直线段的部分省略掉了。

hierarchy向量(截取一部分):

本次参数配置下,检测出了较多轮廓。第1、第2个整形值分别指向上一个和下一个轮廓编号,由于本次配置mode取值“RETR_LIST”,各轮廓间各自独立,不建立等级关系,所以第3、第4个整形参数为空,设为值-1。

三、mode取值“CV_RETR_TREE”,method取值“CV_CHAIN_APPROX_NONE”,即检测所有轮廓,轮廓间建立外层、内层的等级关系,并且保存轮廓上所有点。

contours向量内所有点集:

所有内外层轮廓都被检测到,contours点集组成的图形跟轮廓表现一致。

hierarchy向量(截取一部分)

本次参数配置要求检测所有轮廓,每个轮廓都被划分等级,最外围、第一内围、第二内围等等,所以除第1个最后一个轮廓外,其他轮廓都具有不为-1的第3、第4个整形参数,分别指向当前轮廓的父轮廓、内嵌轮廓索引编号。

四、Point()偏移量设置

使用三中的参数配置,设置偏移量Point为Point(45,30)。

此时轮廓图像为:

可以看到轮廓图像整体向右下角有一个偏转,偏转量就是设置的(45,30)。

这个偏移量的设置不能过大或过小(负方向上的过小),若图像上任一点加上该偏移量后超出图像边界,程序会内存溢出报错。

findContours函数的各参数就探讨到此,其他参数配置的情况大同小异。值得关注一下的是绘制轮廓的函数

drawContours中最后一个参数是一个Point类型的offset,这个offset跟findContours函数中的offset含义一致,设置之后所绘制的轮廓是原始轮廓上所有像素点加上该偏移量offset后的效果。

当所分析图像是另外一个图像的ROI的时候,这个offset偏移量就可以大显身手了。通过加减这个偏移量,就可以把ROI图像的检测结果投影到原始图像对应位置上。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。