How to close a path along a path rather than an edge - OpenCV
Tl; DR: how to measure the area enclosed by a contour, not just the contour line itself
I want to find the outline of an object in the image below and have a code that works most of the time.
Threshold and additive threshold do not work reliably as ligation changes. I use Canny's edge detection and check the area to make sure I found the correct path. However, at times, when there is a gap that cannot be closed by the morphological closure, the shape is correct, but the area is a contour line and not the entire object.
I usually use convexHull as it returns an outline around the object. However, in this case, the object curves inward along the top and convex vertices are no longer a good approximation of area.
I tried using approxPolyDP , but the area returned is a contour line, not an object.
How can I get approxPolyDP to return a similar closed path around the object as the convex function does?
Code to illustrate this using the above image:
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)
Exiting the code
Area = 24.500000 Area after Convec Hull = 3960.500000 Area after apporxPoly = 29.500000
source to share
Here's a very promising ppt from geosensor.net where several algorithms are discussed. My recommendation would be to use the limited radius swing arm method.
Another completely untested wall idea I have is to scan through the image by row and column (more directions increase accuracy) and color in areas between line intersections:
_______
/-------\
/---------\
--------+---------+------ (fill between 2 intersections)
| |
|
--------+---------------- (no fill between single intersection)
\
-------
the maximum error will decrease as the number of lines scanned increases (more than 90 and 45 degrees). Getting the final area will be as easy as counting the pixels.
source to share