0

I have some images with objects whose bounding boxes are somewhat rotated. I am trying to determine the angle of rotation, and midpoints along the width and height of each object in an image and count the objects if possible. This work was pretty easy for just one object in an image but becomes challenging when there are multiple objects in an image. I have tried my level best, however, the disadvantage of this method is that the angle appears to be the came 89.37 for all the bounding boxes as shown in the results below. Here are my codes and I look forward to any suggestions on how to go through the task.

codes

a = 45
count = 0
kernel_size = 11
image = cv2.imread(path+'camera1'+str(a)+'.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
erosion = cv2.erode(thresh, kernel = np.ones((kernel_size, kernel_size), np.uint8))
contours = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
result = image.copy()
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
    x,y,w,h = cv2.boundingRect(cntr)
    #cv2.rectangle(result, (x, y), (x+w, y+h), (0, 0, 255), 2)
    rect = cv2.minAreaRect(cntr)
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    M = cv2.moments(contours[0])
    center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
    theta = 0.5*np.arctan2(2*M["mu11"],M["mu20"]-M["mu02"])
    angle = degrees(theta)
    
    output = [(x, y) for (x, y),in zip(box)]
    midupper = (int((output[0][0]+output[1][0])/2),int((output[0][1]+output[1][1])/2))
    midlower = (int((output[3][0]+output[2][0])/2),int((output[3][1]+output[2][1])/2))
    midleft = (int((output[0][0]+output[3][0])/2),int((output[0][1]+output[3][1])/2))
    midright = (int((output[1][0]+output[2][0])/2),int((output[1][1]+output[2][1])/2))
    def line_intersection(line1, line2):
        xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
        ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])

        def det(a, b):
            return a[0] * b[1] - a[1] * b[0]

        div = det(xdiff, ydiff)
        if div == 0:
            raise Exception('lines do not intersect')

        d = (det(*line1), det(*line2))
        x = det(d, xdiff) / div
        y = det(d, ydiff) / div
        return x, y
    Cx, Cy = line_intersection((midupper, midlower), (midleft, midright))
    ## Distance between the center of mass and centroid
    distance = math.sqrt((int(center[0]) - int(Cx))**2 + (int(center[1]) - int(Cy))**2) 
    cv2.circle(image, midleft, 2, (0,0,0), 4)
    cv2.circle(image, midright, 2, (255,255,255), 4)
    cv2.line(image, midupper,midlower, (0, 255, 0), 2)
    cv2.line(image, midleft,midright, (0, 255, 0), 2)
    cv2.putText(image, "w={},h={}".format(w,h), (x,y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
    cv2.putText(image, "angle={}".format(round(angle,2)), (x + 200,y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
    cv2.putText(image, "Cx={},Cy={}".format(int(Cx),int(Cy)), (int(Cx),int(Cy)+40), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
    cv2.drawContours(image,[box],0,(255,0,0),2) 
    #cv2.drawContours(result, [box], 0, (255, 10, 10), 2)
cv2.imshow('image', image)
#cv2.imshow('thresh', thresh)
cv2.waitKey(0)

input image

results from the codes

expected image with different angles

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Kimwaga Makono
  • 121
  • 1
  • 8
  • Doesn't that just mean your `angle = ...` computation from the moments is incorrect? – AKX Aug 30 '22 at 12:49
  • 1
    Does https://stackoverflow.com/a/34285205/51685 help? – AKX Aug 30 '22 at 12:50
  • 1
    After cv2.minAreaRect(cntr) you should have a RotatedRect object and no need to calculate an angle because it should already be there as a variable in that object. – Micka Aug 30 '22 at 13:08
  • I think I need to read more, about this case because when I trace the `rect` object as see the information for just one object in an image and not all 3 objects like for this image `rect = ((x,y), (w,h), angle)` I don't see the information for all objects ina an image – Kimwaga Makono Aug 31 '22 at 00:22

1 Answers1

1

Your theta depends only on M and M only on contours[0]. Did you mean to put in cntr there since you are iterating over the elements of contours.

Flow
  • 11
  • 1