1
votes

I am trying to write some easy code in python to produce bounding rectangles around objects in a binary image, where there may be 1 or more objects. This is fairly easy to achieve with cv2.boundingRect for a single object, or to draw a single rectangle around 2 objects, but it does not seem to handle the multiple separate objects case. For example see the image below: enter image description here

I would like to get 2 bounding boxes that define the x/y/width/height (or alternatively x1/x2/y1/y2) for EACH object separately. Does anyone know how to do this? Thanks!

1
How do you define an object? Does it have to be a specific shape? Does it has to have connectivity between pixels? There are many solutions I can think of, but if it is just blobs you can use blob detector: learnopencv.com/blob-detection-using-opencv-python-cOr b
It doesn't have to be a specific shape, but they will all be roughly circular/oval like the objects shown above. I think you're right, what I'm looking for is blobs. All individual objects will be fully connected. However for some reason, the blob detector is not working on this image above. The image consists of a numpy ndarray of uint8 0's and 1's, and this code: pixels = cv2.imread(seg, 0) detector = cv2.SimpleBlobDetector_create() keypoints = detector.detect(pixels) returns an empty [] for keypointsRobert Harris

1 Answers

4
votes

The simplest way to do that in Python/OpenCV is to get the contours. Then loop over each contour and get its bounding box and draw it on the image and print it.

Input:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('two_blobs.jpg')

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray,128,255,cv2.THRESH_BINARY)[1]

# get contours
result = img.copy()
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
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)
    print("x,y,w,h:",x,y,w,h)
 
# save resulting image
cv2.imwrite('two_blobs_result.jpg',result)      

# show thresh and result    
cv2.imshow("bounding_box", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bounding boxes image:

enter image description here

Texual results:

x,y,w,h: 262 267 37 45
x,y,w,h: 212 143 97 55