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
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.