My purpose is to check whether these cubes are in one column or not. Having problem with detecting objects properly. not sure why numbers are placed there like that. My main questions:
- How to compare two point of two objects to check if they are fit well or not?
- How can I improve detecting objects?
Thanks in advance.
import cv2
image = cv2.imread('test1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(
thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow('Canny Edges', thresh)
for (i, c) in enumerate(contours):
((x, y), _) = cv2.minEnclosingCircle(c)
cv2.putText(image, "#{}".format(i 1), (int(x) 0, int(y) 0),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
cv2.imshow('Contours', image)
cv2.waitKey(0)
CodePudding user response:
Since the boxes are touching each other, watershed algorithm works well in this cases to extract the box contours. Then the x coordinates position of the rectangle contours can be used to say whether they are aligned or not.
Steps:
- Watershed algorithm to get markers.
- Filter out boxes(rectangles)
- To see if its aligned or not using standard deviation of all the boxes x coordinates. (the threshold can be set accordingly)
Code:
import cv2
import numpy as np
def watershed_algorithm(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY cv2.THRESH_OTSU)
# noise removal
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)
# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# Finding unknown regio3
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)
# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers 1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0
markers = cv2.watershed(image,markers)
return markers
def is_rect_contour(contour):
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.04 * peri, True)
if len(approx) == 4:
return True
else:
return False
def get_rectangle_contours(markers, shape):
rectangle_contours = []
for marker in np.unique(markers):
if marker == 0 or marker==-1:
continue
mask = np.zeros(shape, dtype="uint8")
mask[markers == marker] = 255
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
c = max(cnts[0], key=cv2.contourArea)
if is_rect_contour(c):
rectangle_contours.append(c)
return rectangle_contours
def draw_and_display_contours(contours, image):
for i,c in enumerate(contours):
(x, y, w, h) = cv2.boundingRect(c)
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
cv2.putText(image, "#{}".format(i 1), (int(x) - 10, int(y)),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cv2.imshow('Contours', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
def is_boxes_aligned(rectangle_contours):
x_coord_list = []
for c in rectangle_contours:
(x, y, w, h) = cv2.boundingRect(c)
x_coord_list.append(x)
threshold_std_deviation_in_X_coordinates = 10
if np.std(x_coord_list) < threshold_std_deviation_in_X_coordinates:
print("Box are aligned in same column with a standard deviation of {}".format(np.std(x_coord_list)))
else:
print("Box are not aligned in same column")
image = cv2.imread("./cubes.jpg")
markers = watershed_algorithm(image)
rectangle_contours = get_rectangle_contours(markers, image.shape[:2])
draw_and_display_contours(rectangle_contours,image)
is_boxes_aligned(rectangle_contours)
Output:
Box are aligned in same column with a standard deviation of 4.027681991198191



