opencv bounding box issue

Question:

I have an image I need to draw a bounding box around and I’m trying to use the code at bottom of this post.
The issue I have is that I have tried to blur the blue box shape to remove its details e.g.

cv2.blur(img,(20,20)) 

but the blurred image doesnt seem to have a good enough edge to produce a bounding box.

I have found that if I use my code below with a plain blue square with sharp edges of the same size as the image below, it works just fine. It seems the detail within the blue area stops a boundary box being drawn.

I was hoping someone could tell me how to get this to work please.

enter image description here

import cv2

# Load the image - container completely blurred out so no hinges,locking bars , writing etc are visible, just a blank blue square
img = cv2.imread('blue_object.jpg')

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

edged = cv2.Canny(img, 120,890)
# Apply adaptive threshold
thresh = cv2.adaptiveThreshold(edged, 255, 1, 1, 11, 2)
thresh_color = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)

# apply some dilation and erosion to join the gaps - change iteration to detect more or less area's
thresh = cv2.dilate(thresh,None,iterations = 50)
thresh = cv2.erode(thresh,None,iterations = 50)

# Find the contours
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# For each contour, find the bounding rectangle and draw it
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > 50000:
        x,y,w,h = cv2.boundingRect(cnt)
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)


cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

The image below is the yellow container after lower HSV mask range of 8,0,0 and upper range of 78,255,255 . Trees are above and to top right of the container, so hard to separate the tress from the container to put a proper bounding box around it.Happy to move to chat if that helps.enter image description here

Asked By: steve

||

Answers:

You’re converting to gray, throwing all that valuable color information away. You’re also Canny-ing, which is generally a bad idea. Beginners don’t have the judgment to apply Canny sensibly. Best stay away from it.

This can be solved with the usual approach:

  • transform colorspace into something useful, say HSV
  • inRange on well-saturated blue
  • some morphology operations to clean up debris
  • bounding box

That is assuming you are looking for a blue container, or any well-saturated color really.

im = cv.imread("i4nPk.jpg")
hsv = cv.cvtColor(im, cv.COLOR_BGR2HSV)

lower = (90, 84, 0)
upper = (180, 255, 255)
mask1 = cv.inRange(hsv, lower, upper)

mask2 = cv.erode(mask1, kernel=None, iterations=2)

(x, y, w, h) = cv.boundingRect(mask2) # yes that works on masks too

canvas = cv.cvtColor(mask2, cv.COLOR_GRAY2BGR)
cv.rectangle(canvas, (x,y), (x+w, y+h), color=(0,0,255), thickness=3)

output

Answered By: Christoph Rackwitz