You are trying to do "color detection" and then draw a bounding box around it.
The easiest way:
Step 1: Implement color detection.
I implemented the following code to find the right values for the mask for your image. Play with the trackbars and when you are satisfied with the results, press q and the values for the mask ??will be printed for you.
Note: it's ok that you find more small contours besides your goal.
I found this values working great:
h_min, h_max, s_min, s_max, v_min, v_max: 0 179 0 15 223 255
import cv2
import numpy as np
def empty():
pass
while True:
img = cv2.imread(Path to your image)
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
lower = np.array([h_min, s_min, v_min])
upper = np.array([h_max, s_max, v_max])
mask = cv2.inRange(imgHSV, lower, upper)
imgResult = cv2.bitwise_and(img, img, mask=mask)
# for OpenCV 4
contours, _ = cv2.findContours(mask, cv2.RETR_TREE,
cv2.CHAIN_APPROX_NONE)
# ---For OpenCV 3---
# _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE,
# cv2.CHAIN_APPROX_NONE)
# ---For OpenCV 3---
for contour in contours:
cv2.drawContours(img, contour, -1, (0, 255, 0), 3)
cv2.imshow("Original", img)
cv2.imshow("Result", imgResult)
if cv2.waitKey(27) & 0xFF == ord('q'):
print(h_min, h_max, s_min, s_max, v_min, v_max)
break
Step 2: Draw the bounding box only around your goal. (2 drawing Options)
The code is similar to before but now we know the right values and we will draw the line around the contour that we want. Our goal is the biggest contour so we can use the contourArea() method to extract the size of the contour and then draw the "bounding box" only if the contour is big enough. It's a little different implementation from your code but you can adjust it to your logic (sorting the sizes of the areas of the contours and draw only on the biggest one).
For example:
import cv2
import numpy as np
while True:
frame = cv2.imread("stackoverflow2pic.jpeg")
blurred_frame = cv2.GaussianBlur(frame, (5, 5), 0)
hsv = cv2.cvtColor(blurred_frame, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 223])
upper = np.array([179, 15, 255])
mask = cv2.inRange(hsv, lower, upper)
# for OpenCV 4
contours, _ = cv2.findContours(mask, cv2.RETR_TREE,
cv2.CHAIN_APPROX_NONE)
# ---For OpenCV 3---
# _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE,
# cv2.CHAIN_APPROX_NONE)
# ---For OpenCV 3---
for contour in contours:
area = cv2.contourArea(contour)
if area > 5000:
# -- Draw Option 1 --
cv2.drawContours(frame, contour, -1, (0, 255, 0), 3)
# -- Draw Option 2--
# rect = cv2.boundingRect(contour)
# x, y, w, h = rect
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Mask", mask)
cv2.imshow("Frame", frame)
cv2.waitKey(1)
Result (Drawing Option 1):
Result (Drawing Option 2):