OpenCV图像的轮廓

本文详细介绍了OpenCV库中查找和处理图像轮廓的方法,包括cvFindContours函数的使用,轮廓的Freeman链码表示,多边形逼近,以及轮廓特征的提取,如长度、边界框和最小包围圆等。此外,还提供了代码示例来演示如何在图像上绘制轮廓。
摘要由CSDN通过智能技术生成

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

查找轮廓

轮廓到底是什么?一个轮廓一般对应一系列的点,也就是图像中的一条曲线.表示的方法可能根据不同情况而有所不同.有多重方法可以表示曲线.在openCV中一般用序列来存储轮廓信息.序列中的每一个元素是曲线中一个点的位置.关于序列表示的轮廓细节将在后面讨论,现在只要简单把轮廓想象为使用CvSeq表示的一系列的点就可以了.

函数cvFindContours()从二值图像中寻找轮廓.cvFindContours()处理的图像可以是从cvCanny()函数得到的有边缘像素的图像,或者是从cvThreshold()及cvAdaptiveThreshold()得到的图像,这时的边缘是正和负区域之间的边界.


图8-2描述了cvFindContours的函数功能,图像的上半部分是神色背景和白色区域(被从A到E标记)的测试图像.下半部分是使用cvFindCountours()函数后会得到的轮廓的说明.这些轮廓被标记为cX或hx,"c"表示"轮廓(contour)","h"表示"孔(hole)","X表述数字".其中一些轮廓用虚划线表示;表明他们是白色区域的外部边界(例如,非0区域).孔(hole)的外部边界(例如,非0区域)即白色区域的内部边界.在图中是用电线表示外部边界的.OpenCV的cvFindContours()函数可区分内部和外部边界.

包含的概念在很多应用中都非常重要.因此.OpenCV允许得到的轮廓被聚合成一个轮廓树,从而把包含关系编码到树结构中.这个测试图的轮廓树在根节点的轮廓叫c0,孔h00和h01是它的字子节点.这些轮廓中直接包含轮廓称为他们的子节点,以此类推.

现在来看cvFindContours()函数

int  cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,                              int header_size CV_DEFAULT(sizeof(CvContour)),                              int mode CV_DEFAULT(CV_RETR_LIST),                              int method CV_DEFAULT(CV_CHAIN_APPROX_SIMPLE),                              CvPoint offset CV_DEFAULT(cvPoint(0,0)))
第一个参数 image是输入图像,图像必须是8位单通道图像,并且应该被转化成二值的(例如,所有非0像素的值都是一个定值).cvFindContours()运行的时候,这个图像会被直接涂改,因此如果是将来还有用的图像,应该复制之后再传给cvFindContours().

storage 是内存存储器,cvFindContours()找到的轮廓记录在此内存里.正如之前所说,这个存储器的空间应该由cvCreateMemStorage()分配.

first_contour 是指向CvSeq*的一个指针firstContour.无需动手,cvFindContours()会自动分配该指针.实际上,只要在这里传一个指针就可以了函数会自动设置.不需要分配和释放(new/delete或者malloc/free).就是这个指针(例如,*firstContour)指向轮廓树的首地址(head).cvFindContours()返回值是,找到的所有轮廓的个数

cvSeq* firstContout = NULL;

cvFindContours(..., &firstContour, ...);

headerSize告诉cvFindContours()更多有关对象分配的信息,它可以被设定为sizeof(CvContour)或者sizeof(CvChain)(当近似方法参数method被设定为CV_ChAIN_CODE时使用后者).最后是mode和method参数,他们分别指定计算方法和如何计算.

mode变量可以被设置为以下四个选项之一: CV_RETR_ExTERNAL, CV_RETR_LIST, CV_RETR_CCOMP或CV_RETR_TREE.mode的值向cvFindeContours()说明需要的轮廓类型,和希望的放回值形式.具体说来,mode的值决定把找到的轮廓如何挂到轮廓树节点变量(h_prev,h_next,v_prev和v_next)上,图8-3展示了四种可能的mode值所得到的结果的拓扑结构.


每中情况下,结构都可以看成是被"横向"连接(h_next和h_prev)联系和被"纵向"连接(v_next和v_prev)不同的"层次".

CV_RETR_EXTERNAL 只检测出最外的轮廓.图8-2中,只有一个最外轮廓,因此图8-3中第一个轮廓指向最外的序列,除此之外没有别的连接

CV_RETR_LIST 检测所有的轮廓并将他们保存到表(list)中.图8-3描绘了从图8-2样图中得到的表.在这个例子中,有8条轮廓被找到,他们相互之间有h_prev和h_next连接(这里并没有使用v_prev和v_next)

CV_RETR_CCOMP 检出所有的轮廓并将他们组织成双层结构(two-level hierarchy),顶层边界是所有成份的外界边界,第二层边界是空的边界.图8-3中,我们能看到5个外部边界,其中3个包含孔.孔被v_next和v_prev可以只包括一个值,此节点可以只有一个子节点.c0中有两个孔,因为v_next可以值包括一个值,次节点可以只有一个子节点.c0之内的所有孔相互间有h_prev和h_next指针连接.

CV_RETR_TREE 检出所有轮廓并且重新建立网状的轮廓结构.在我们给出的例子中(图8-2和8-3中),这意味着根节点是最外的轮廓c0.c0之下是空h00,在同一层次中与另一个孔h01相连接.同理,每个孔都有子节点(相对应的是c000和c010),这些子节点与父节点被垂直连接起来.这个步骤一直持续到图像最内层的轮廓,这些轮廓会成为树叶节点.

以下的五个值与方法相关(例如轮廓会如何被近似).

 CV_CHAIN_CODE 用freeman链码输出轮廓,其他方法输出多边形(顶点的序列)

CV_CHAIN_APPROX_NONE 将链码编码中的所有点转换为点

CV_CHAIN_APPROX_SIMPLE 压缩水平,垂直或斜的部分,只保存最后一个点

CV_CHAIN_APPROX_TC89_L1或CV_CHAIN_APPROX_TC89_KCOS使用Ten-Chin链逼近算法中的一个

CV_LINK_RUNS 与上述算法完全不同的算法,连接所有水平层次的轮廓.此方法只可与Cv_RETR_LIST搭配使用.

使用序列表示轮廓

当调用cvFindContours函数的时候,返回多个序列.序列的类型依赖与调用cvFindContours时 所传递的参数.默认情况下使用CV_RETR_LIST和CV_CHAIN_APPROX_SIMPLE参数.

序列中保存一系列的点,这些点构成轮廓,轮廓是本章的重点.轮廓只是序列所能表示物体的一种.轮廓的点的序列,可以用来表示图像空间中的曲线.这种点的序列很常用,所有需要有专门的函数来帮助我们对他进行处理.下面是一组这样的处理函数.

int  cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,                              int header_size CV_DEFAULT(sizeof(CvContour)),                              int mode CV_DEFAULT(CV_RETR_LIST),                              int method CV_DEFAULT(CV_CHAIN_APPROX_SIMPLE),                              CvPoint offset CV_DEFAULT(cvPoint(0,0)))
CvContourScanner  cvStartFindContours( CvArr* image, CvMemStorage* storage,                             
OpenCV图像轮廓是指在图像中连续的边界线。根据引用中的示例代码,我们可以使用OpenCV库来实现图像轮廓的查找和计算。 首先,我们需要读取图像并将其转换为灰度图像。可以使用cv2.imread()函数读取图像,然后使用cv2.cvtColor()函数将图像转换为灰度图像。 接下来,我们可以使用cv2.threshold()函数将灰度图像二值化,得到一个二值图像,其中只有两个像素值,一种是白色(255),一种是黑色(0)。函数中的阈值参数可以根据具体应用进行调整。 然后,我们可以使用cv2.findContours()函数查找图像中的轮廓。该函数返回两个结果,第一个结果是轮廓的列表,第二个结果是层级信息。轮廓是一系列坐标点的集合,描述了对象的边界。 接着,我们可以使用cv2.drawContours()函数将轮廓绘制在图像上。这个函数会直接修改原图像,如果想保持原图像不变,可以先复制一份。通过指定轮廓的索引,我们可以绘制特定的轮廓。 最后,我们可以使用cv2.contourArea()函数计算轮廓的面积,使用cv2.arcLength()函数计算轮廓的周长。这两个函数都需要传入一个轮廓参数。 所以,OpenCV图像轮廓的实现步骤可以总结为以下几个步骤: 1. 读取图像并将其转换为灰度图像。 2. 使用阈值函数将灰度图像二值化。 3. 使用findContours函数查找图像中的轮廓。 4. 绘制轮廓图像上。 5. 计算轮廓的面积和周长。 希望这个回答能帮到你!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [opencv 图像轮廓的实现示例](https://download.csdn.net/download/weixin_38681736/12849896)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [OpenCv图像轮廓](https://blog.csdn.net/weixin_64443786/article/details/131796588)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值