首页 文章

查找OpenCV轮廓的区域

提问于
浏览
2

在最近的一组图像中,我的OpenCV代码停止找到正确的轮廓区域 . 这似乎发生在轮廓未关闭时 . 我试图确保轮廓关闭无济于事 .

编辑:问题是轮廓中存在间隙 .

Background: 我在一个通道中有一系列胶囊图像,我想测量形状的区域以及瞬间的质心 .

Problem: 轮廓未关闭时,力矩错误 .

编辑:当我有间隙时,轮廓不是整个形状,因此不正确的区域 .

What I do:

  • 读取图像 - > img = cv2.imread(fileName,0)

  • apply Canny过滤器 - > edges = cv2.Canny(img,lowerThreshold,lowerThreshold * 2)

  • find contours - > contours,hierarchy = cv2.findContours(edges,cv2.cv.CV_RETR_LIST,cv2.cv.CV_CHAIN_APPROX_NONE)

  • 找到最长的轮廓

  • 确保轮廓关闭

  • 找时刻 - > cv2.moments(cnt)

可以找到带有测试图像的工作示例here .

有一个question关于关闭轮廓,但这些建议都没有奏效 . 使用cv2.approxPolyDP不会更改结果,但应返回闭合轮廓 . 将轮廓的第一个点添加为最后一个,以使其关闭,也无法解决问题 .

下面是轮廓绘制的图像示例 . 这里,区域被确定为85,而在几乎相同的图像中,它是8660,这应该是它应该是的 .
http://www.negative-probability.co.uk/docs/ImageWContour_0.png

任何建议都会得到满足 .

码:

img =cv2.imread(fileName,0)
edges = cv2.Canny(img,lowerThreshold,lowerThreshold*2)
contours, hierarchy = cv2.findContours(edges,cv2.cv.CV_RETR_LIST,cv2.cv.CV_CHAIN_APPROX_NONE) #cv2.cv.CV_CHAIN_APPROX_NONE or cv2.cv.CV_CHAIN_APPROX_SIMPLE

#Select longest contour as this should be the capsule
lengthC=0
ID=-1
idCounter=-1
for x in contours:
    idCounter=idCounter+1 
    if len(x) > lengthC:
        lengthC=len(x)
        ID=idCounter

if ID != -1:
    cnt = contours[ID]
    cntFull=cnt.copy()

    #approximate the contour, where epsilon is the distance to 
    #the original contour
    cnt = cv2.approxPolyDP(cnt, epsilon=1, closed=True)

    #add the first point as the last point, to ensure it is closed
    lenCnt=len(cnt)
    cnt= np.append(cnt, [[cnt[0][0][0], cnt[0][0][1]]]) 
    cnt=np.reshape(cnt, (lenCnt+1,1, 2))

    lenCntFull=len(cntFull)
    cntFull= np.append(cntFull, [[cntFull[0][0][0], cntFull[0][0][1]]]) 
    cntFull=np.reshape(cntFull, (lenCntFull+1,1, 2))

    #find the moments
    M = cv2.moments(cnt)
    MFull = cv2.moments(cntFull)
    print('Area = %.2f \t Area of full contour= %.2f' %(M['m00'], MFull['m00']))

2 回答

  • 0

    在处理了类似的问题之后,另一种解决方案(并且可以说更简单,开销更少)是使用形态学开放功能,其执行侵蚀,然后进行扩张 . 如果您首先将其转换为二进制图像,请执行打开操作,然后执行Canny检测,这应该执行相同的操作,但不必迭代过滤器 . 您唯一需要做的就是使用内核大小几次来确定合适的大小而不会丢失太多细节 . 我发现这是确保轮廓关闭的一种相当强大的方法 .

    Morphological operations documentation

  • 1

    正如@HugoRune指出的那样,我的问题是,计数器中存在空白 . 解决方案是缩小差距 .

    我发现很难找到一种缩小间隙的通用方法,所以我迭代地改变Canny滤波器的阈值并执行morphological closing直到找到闭合的轮廓 .

    对于那些有相同问题的人,有几个很好的答案如何关闭轮廓,如thisthis

相关问题