如何在轮廓而不是边缘上关闭轮廓 - OpenCV

时间:2015-07-08 12:35:15

标签: python opencv

Tl; DR:如何测量轮廓所包围的区域而不仅仅是轮廓线本身

我想在下面的图像中找到对象的轮廓,并且有一个适用于大多数情况的代码。 Original Image

阈值和自适应阈值处理不能可靠地工作。我使用Canny边缘检测并检查区域以确保我找到了正确的轮廓。但是,偶尔会有一个间隙无法通过形态学闭合来闭合,形状是正确的,但该区域是轮廓线而不是整个物体。

Canny Contour Output

我通常使用convexHull,因为它返回对象周围的轮廓。然而,在这种情况下,物体沿顶部向内弯曲并且凸出的船体不再是该区域的良好近似。

Contour after Convex Hull

我尝试使用approxPolyDP,但返回的区域是轮廓线而不是对象。

如何让approxPolyDP在对象周围返回类似的闭合轮廓,就像使用convexHull函数一样?

使用上图说明这个代码:

import cv2
img = cv2.imread('Img_0.jpg',0)
cv2.imshow('Original', img)

edges = cv2.Canny(img,50,150) 
cv2.imshow('Canny', edges)

contours, hierarchy = cv2.findContours(edges,cv2.cv.CV_RETR_EXTERNAL,cv2.cv.CV_CHAIN_APPROX_NONE)

cnt = contours[1] #I have a function to do this but for simplicity here by hand

M = cv2.moments(cnt) 
print('Area = %f \t' %M['m00'], end="")

cntHull = cv2.convexHull(cnt, returnPoints=True)
cntPoly=cv2.approxPolyDP(cnt, epsilon=1, closed=True)
MHull = cv2.moments(cntHull)
MPoly = cv2.moments(cntPoly)
print('Area after Convec Hull = %f \t Area after apporxPoly = %f \n' %(MHull['m00'], MPoly['m00']), end="")

x, y =img.shape
size = (w, h, channels) = (x, y, 1)
canvas = np.zeros(size, np.uint8)
cv2.drawContours(canvas, cnt, -1, 255)
cv2.imshow('Contour', canvas)

canvas = np.zeros(size, np.uint8)
cv2.drawContours(canvas, cntHull, -1, 255)
cv2.imshow('Hull', canvas)

canvas = np.zeros(size, np.uint8)
cv2.drawContours(canvas, cntPoly, -1, 255)
cv2.imshow('Poly', canvas)

代码的输出是

Area = 24.500000    Area after Convec Hull = 3960.500000     Area after apporxPoly = 29.500000 

1 个答案:

答案 0 :(得分:1)

这是来自geosensor.net的非常有前途的ppt,它讨论了几种算法。我的建议是使用半径有限的摆臂法。

另一个完全没有经过测试的离墙概念是按行和列扫描图像(更多方向增加精度)和线交叉点之间区域的颜色:

          _______
         /-------\
        /---------\
--------+---------+------ (fill between 2 intersections)     
        |         |
        |
--------+---------------- (no fill between single intersection)
         \
          -------

随着扫描的线方向数量增加(超过90度和45度),最大误差将减小。获得最终区域就像像素数一样简单。