I am trying to identify the boundaries of plant wells in a tray in an image such as this one:
When I run my thresholding process, the image looks like this:
However, when I try to draw the contours onto the original image, the output is incomplete. I believe this image is clear enough to work well, but I can't find where I am going wrong. Here is my code:
def angle_cos(p0, p1, p2):
d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
def find_squares(img):
img = cv2.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv2.split(img):
for thrs in range(0, 255, 26):
if thrs == 0:
bina = cv2.Canny(gray, 0, 50, apertureSize=5)
bina = cv2.dilate(bina, None)
else:
_retval, bina = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
contours = cv2.findContours(bina, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours[1]:
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in range(4)])
if max_cos < 0.1:
squares.append(cnt)
return squares
squares = find_squares(ct2)
newim = cv2.drawContours(dupimage, squares, -1, (0, 0, 255), 3)
plt.figure()
plt.imshow(newim)
There are no errors, it is just producing an image that is not correctly identifying all of the very clear squares. Can anyone see the mistake I'm making?
The updated image looks like this: