识别opencv的开放和封闭形状

Fah*_*lik 16 c++ opencv image-processing shape-recognition

如何在opencv中检测打开和关闭的形状.

在此输入图像描述

这些是我想要检测的简单样本形状.我已经检测到矩形使用findContoursapproxPolyDP检查矢量之间的角度.

现在我想检测打开的形状,approxPolyDP函数有关闭形状设置为true的bool,并且还检查isCounterConvex返回的点数,加上contourArea限制.

任何想法我应该如何继续检测这些图像.

Har*_*ris 26

只需在图像中使用findContours(),然后通过检查传递给findContours()函数的层次结构来确定轮廓是否关闭.从第二个图可以清楚地看出,与第一个图像相比,没有轮廓具有子轮廓,您将从层次参数获得此数据,该参数是可选的输出向量,包含有关图像拓扑的信息.它具有与轮廓数量一样多的元素.

这里我们将使用层次结构

vector< Vec4i > hierarchy
Run Code Online (Sandbox Code Playgroud)

在哪里为第i个轮廓

hierarchy[i][0] = next contour at the same hierarchical level
hierarchy[i][1] = previous contour at the same hierarchical level
hierarchy[i][2] = denotes its first child contour
hierarchy[i][3] = denotes index of its parent contour
Run Code Online (Sandbox Code Playgroud)

如果轮廓i没有下一个,前一个,父级或嵌套轮廓,则相应的元素hierarchy[i]将为负数.有关更多详细信息,请参阅findContours()函数.

因此,通过检查值,hierarchy[i][2]您可以确定轮廓属于是否为闭合,如果hierarchy[i][2] = -1当时没有孩子并且它属于打开,则为轮廓.

还有一件事是,在findContours()函数中,您应该使用CV_RETR_CCOMP来检索所有轮廓并将它们组织成两级层次结构.

这是C++代码如何实现它.

    Mat tmp,thr;
    Mat src=imread("1.png",1);
    cvtColor(src,tmp,CV_BGR2GRAY);
    threshold(tmp,thr,200,255,THRESH_BINARY_INV);

    vector< vector <Point> > contours; // Vector for storing contour
    vector< Vec4i > hierarchy;
    findContours( thr, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    for( int i = 0; i< contours.size(); i=hierarchy[i][0] ) // iterate through each contour.
    {
        Rect r= boundingRect(contours[i]);
        if(hierarchy[i][2]<0) //Check if there is a child contour
          rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,0,255),2,8,0); //Opened contour
        else
          rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,255,0),2,8,0); //closed contour
    }
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述


小智 7

Python 实现如下。

import cv2


src = cv2.imread('test.png', cv2.IMREAD_COLOR)

#Transform source image to gray if it is not already
if len(src.shape) != 2:
    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
else:
    gray = src

ret, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]

for i, c in enumerate(contours):
    if hierarchy[i][2] < 0 and hierarchy[i][3] < 0:
        cv2.drawContours(src, contours, i, (0, 0, 255), 2)
    else:
        cv2.drawContours(src, contours, i, (0, 255, 0), 2)
#write to the same directory
cv2.imwrite("result.png", src)
Run Code Online (Sandbox Code Playgroud)


小智 5

在纠正所提出的问题的同时,不应将@Haris有用的回答作为使用findContours()识别闭合轮廓的一般解决方案。

原因之一是填充的对象将没有内部轮廓,因此将返回hierarchy[i][2] = -1,这意味着该测试本身会将这样的轮廓错误地标记为“开放”。

填充对象的轮廓在轮廓层次中应该没有子级或父级,即在顶层。因此,要检测填充对象的闭合轮廓,至少需要进行其他测试:if(hierarchy[i][2] < 0 && hierarchy[i][3] < 0)

我认为@Haris的回答可能已经倾斜了这一点,但我认为值得对像我这样正在学习如何使用opencv的人进行澄清。