I want to draw a line across the center of a curved object.As an example: an image of a banana is given, the orientation might change with different images and also there might be more than one curve in the object, but the task is the same.To determine the length of the object, its required to calculate (interpolate) the center line of the contour of the object from start to end, then i can calculate the length of the interpolated line. This is what i thought so far.
But now there is the tricky part, determining the contour of the object using python and cv2 is no problem, this works like a charme. but calculating the center line to determine its length is the struggle now.
please can someone help me with this?
EDIT:
Goal of the script should be to measure the length and area of the worm, so I dont have to measure the values manually for hundreds of images.
Input image:
My computation so far for the contour (green line)
What I want:only drawn by hand as an example.
Code used so far (without the "center line" i want, because I dont have any idea how to start). My idea using the convex hull, building the skeleton and using it does not work as expected, because the convex hull is to large (caused by the concave part), combining it with polyDP also does not work because the polyDP often misses parts of the worm and the combined result is also bad.
import numpy as npimport cv2import osdraw_windows = True ## change fo False for no windows only calcdef calc_values(filename): img = cv2.imread(filename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (7, 7), 0) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) drawWindow('thresh', thresh) edged = cv2.Canny(gray, 50, 100) edged = cv2.dilate(edged, None, iterations=1) edged = cv2.erode(edged, None, iterations=1) drawWindow('edged', edged) contours, _ = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # Assume the largest contour corresponds to the worm if contours: largest_contour = max(contours, key=cv2.contourArea) # Draw the contour on the original image image_with_contour = cv2.cvtColor(edged, cv2.COLOR_GRAY2BGR) cv2.drawContours(image_with_contour, [largest_contour], -1, (0, 255, 0), 2) cv2.drawContours(image_with_contour, contours, -1, color=(255, 255, 255), thickness=cv2.FILLED) # Display the original image with the detected contour drawWindow('Worm with Contour', image_with_contour)def drawWindow(window_name, image): if draw_windows: cv2.imshow(window_name, image) cv2.waitKey(0) cv2.destroyAllWindows()def main(): directory = "input" for filename in os.listdir(directory): file = os.path.join(directory, filename) calc_values(file)if __name__ == "__main__": main()
(I know code quality is not the best so far, but it started as a quick and dirty "project" :D)