Is it possible to create a polygon from a set of points along a line with rough curvature, such that the points are selected between two values of curvature?
I am attempting to retrieve an approximated curvilinear quadrilateral shape from a given image using python's opencv package (cv2
).
For example: Given an image after edge detection such as this:
and after finding contours with cv2.findContours such as this:
(Sidenote: It would be great if this would actually give a square-ish shape rather than going around the line - an algorithm to close in the gap in this image's shape on it's right side is also required. Dilation/erosion may work but will likely get rid of certain features that may be desired to be kept.)
after that, we can use polyDPApprox on the contours like this:
However, this is not curvature dependent - it's just approximating by use of largest deviance from the lines. If we want to leave out some of the fine detail (the idea being that these are likely from errors) and keep the points with smaller curvature (broad shape) - can we use a function to provide something like this?:
(The red fill in just shows that the shape would be closed in to a curvilinear quadrilateral.)
Related question: Is it possible in OpenCV to plot local curvature as a heat-map representing an object's "pointiness"?
Here is the function used to analyze the input image in case anyone wants it:
# input binary image
def find_feature_points(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.namedWindow('img', WINDOW_NORMAL)
cv2.imshow("img", gray)
cv2.waitKey(0)
contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Draw contours to image
print contours
copy = img.copy()
# img - Image.
# pts - Array of polygonal curves.
# npts - Array of polygon vertex counters.
# ncontours - Number of curves.
# isClosed - Flag indicating whether the drawn polylines are closed or not. If they are closed, the function draws a line from the last vertex of each curve to its first vertex.
# color - Polyline color.
# thickness - Thickness of the polyline edges.
# lineType - Type of the line segments. See the line() description.
# shift - Number of fractional bits in the vertex coordinates.
cv2.polylines(img=copy, pts=contours, isClosed=1, color=(0,0,255), thickness=3)
cv2.namedWindow('contour', WINDOW_NORMAL)
cv2.imshow("contour", copy)
cv2.waitKey(0)
# Find approximation to contours
approx_conts = []
for c in contours:
curve = c
epsilon = 200
closed = True
approx_conts.append(cv2.approxPolyDP(curve, epsilon, closed))
# draw them
cv2.drawContours(img, approx_conts, -1, (0, 255, 0), 3)
cv2.namedWindow('approx', WINDOW_NORMAL)
cv2.imshow("approx", img)
cv2.waitKey(0)
return