I would like to approximate smooth lines with chain of line segments.
cv2.approxPolyDP in OpenCV 3.4 made a good result in the case of closed curve.
Origin close curve: Approximated close curve:
But in the case of open curve, cv2.approxPolyDP did not achieve the desired effect.
Origin open curve: Approximated open curve:
The result I want should be one chain of line segments but not a closed polygon, like this(this picture is created by Photoshop but not Python program):
Is there a way to use cv2.approxPolyDP to approximate open curve?
My Python program is as follow:
import cv2 img = cv2.imread('1.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imshow("gray", gray) cv2.waitKey(0) _, binary = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY) # cv2.imshow("binary", binary) # cv2.waitKey(0) _, contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: epsilon = 0.009 * cv2.arcLength(contour, True) approx = cv2.approxPolyDP(contour, epsilon, closed=True) cv2.drawContours(img, [approx], -1, (0, 255, 255), 1) cv2.imshow("approx", img) cv2.waitKey(0) cv2.destroyAllWindows()
The origin photos used in my program are as follow.
Close curve photo Open curve photo
Advertisement
Answer
Here is how to do that in Python/OpenCV using cv2.approxPolyDP
Input (cropped off screen snap title bar)
import numpy as np import cv2 # read input img = cv2.imread('curve.png') hh, ww = img.shape[:2] # convert to grayscale gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # threshold thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)[1] # get points points = np.column_stack(np.where(thresh.transpose() != 0)) # list points for pt in points: ptx = pt[0] pty = pt[1] print(ptx,pty) # approximate polygon poly = cv2.approxPolyDP(points, 0.02 * ww, False) # list polygon points for p in poly: px = p[0] py = p[0] print(px,py) # draw polygon on copy of input result = img.copy() cv2.polylines(result, [poly], False, (0,0,255), 1) # save results cv2.imwrite('curve_polygon.png', result) cv2.imshow("thresh", thresh) cv2.imshow("result", result) cv2.waitKey(0)