2

I have python code which is detecting a color. Once the color is detected, I am finding the contours and drawing them. Below is the original image:

enter image description here

and below is the image with contours & bounding box on it:

enter image description here

As you can see there are lot of contours detected and thus there are multiple bounding box. Is there a way to merge these bounding box into one. Below is the code

import cv2
import imutils
import numpy as np

image = cv2.imread("L00001.png")
image = imutils.resize(image, width=800)

hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_bound = np.array([45, 150, 20])
upper_bound = np.array([75, 305, 255])
origMask = cv2.inRange(hsv, lower_bound, upper_bound)
contours, h = cv2.findContours(origMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
    new = np.vstack(contours)
    area = cv2.contourArea(c)
    if area > 10:
        x, y, w, h = cv2.boundingRect(c)
        cv2.rectangle(image, (int(x), int(y)), (int(x + w), int(y + h)), (0, 0, 255), 2)

cv2.imshow("FRAME", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
3
  • I would suggest that you view your origMask and see if you can adjust the color bounds. Failing that, perhaps use some morphology to close up and gaps before getting your contours. Commented Jun 28, 2022 at 16:21
  • I like @fmw42 suggestions. The brute force way would be to search through contour bounding boxes for min(x), min(y) and max(x), max(y) and that will give you the corners. Commented Jun 28, 2022 at 18:09
  • I have been able to do this by using connected component analysis. Will answer and post code soon Commented Jun 28, 2022 at 18:33

1 Answer 1

1

I have been able to do this using connected component analysis. I also applied dilation before that and the output looks satisfactory

import cv2
import imutils
import numpy as np
from skimage import measure
from imutils import contours

image = cv2.imread("L00001.png")
image = imutils.resize(image, width=800)

hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_bound = np.array([45, 150, 20])
upper_bound = np.array([75, 305, 255])
origMask = cv2.inRange(hsv, lower_bound, upper_bound)
thresh = cv2.threshold(origMask, 200, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.erode(thresh, None, iterations=1)
thresh = cv2.dilate(thresh, None, iterations=6)

labels = measure.label(thresh, neighbors=4, background=0)
mask = np.zeros(thresh.shape, dtype="uint8")
for label in np.unique(labels):
    if label == 0:
        continue
    labelMask = np.zeros(thresh.shape, dtype="uint8")
    labelMask[labels == label] = 255
    numPixels = cv2.countNonZero(labelMask)
    if numPixels > 30:
        mask = cv2.add(mask, labelMask)

cnts, h = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for (i, c) in enumerate(cnts):
    area = cv2.contourArea(c)
    if area > 10:
        x, y, w, h = cv2.boundingRect(c)
        cv2.rectangle(image, (int(x), int(y)), (int(x + w), int(y + h)), (0, 0, 255), 2)

cv2.imshow("FRAME", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.