I'm currently trying to measure the size of woodchips within an image using openCV and a reference object(the coin) (https://i.stack.imgur.com/GpdJE.jpg). It mostly works but when the woodchips are close to one another find countours recognizes it as one larger contour. I recently read about the watershed algorithm which can be used to segment the objects more efficiently. However how do I implementent it and simulatanously calculate the height and with of each object relative to the reference object?
Here is my code for measuring the woodchip size
# Read image and preprocess (read an image and convert it it no grayscale)
image = cv2.imread(img_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#Blur the image using Gaussian Kernel to remove un-necessary edges
#blur = cv2.GaussianBlur(gray, (9, 9), 0)
#blur = cv2.medianBlur(gray, 7)
blur = cv2.bilateralFilter(thresh,11, 125, 125)
#nbw = cv2.fastNlMeansDenoising(image, None, 10, 7, 21)
#Edge detection using Canny edge detector
edged = cv2.Canny(blur, 50, 100)
edged = cv2.dilate(edged, None, iterations=2)
edged = cv2.erode(edged, None, iterations=2)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (6,6))
closing = cv2.morphologyEx(edged, cv2.MORPH_CLOSE, kernel)
#show_images([blur, edged])
# Find contours
cnts = cv2.findContours(closing.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
# Sort contours from left to right as leftmost contour is reference object
(cnts, _) = contours.sort_contours(cnts)
# Remove contours which are not large enough , Perform morphological closing operation to remove noisy contours
cnts = [x for x in cnts if cv2.contourArea(x) > 400]
# Reference object dimensions
# Here for reference I have used a 2cm x 2cm square
ref_object = cnts[0]
box = cv2.minAreaRect(ref_object)
box = cv2.boxPoints(box)
box = np.array(box, dtype="int")
box = perspective.order_points(box)
(tl, tr, br, bl) = box
dist_in_pixel = euclidean(tl, tr)
dist_in_cm = 2
pixel_per_cm = dist_in_pixel/dist_in_cm
# Draw remaining contours
measurement=[]
for cnt in cnts:
box = cv2.minAreaRect(cnt)
box = cv2.boxPoints(box)
box = np.array(box, dtype="int")
box = perspective.order_points(box)
(tl, tr, br, bl) = box
cv2.drawContours(image, [box.astype("int")], -1, (0, 0, 255), 2)
mid_pt_horizontal = (tl[0] + int(abs(tr[0] - tl[0])/2), tl[1] + int(abs(tr[1] - tl[1])/2))
mid_pt_verticle = (tr[0] + int(abs(tr[0] - br[0])/2), tr[1] + int(abs(tr[1] - br[1])/2))
wid = euclidean(tl, tr)/pixel_per_cm
ht = euclidean(tr, br)/pixel_per_cm
measurement.append((wid,ht))
cv2.putText(image, "{:.1f}cm".format(wid), (int(mid_pt_horizontal[0] - 15), int(mid_pt_horizontal[1] - 10)),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)
cv2.putText(image, "{:.1f}cm".format(ht), (int(mid_pt_verticle[0] + 10), int(mid_pt_verticle[1])),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)
cv2_imshow(image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result: (https://i.stack.imgur.com/nmaW3.jpg)