How do I differentiate individual objects in an image, when they are clustered together and calculate object size

66 Views Asked by At

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)

0

There are 0 best solutions below