Reputation: 354
I am using OpenCV to detect rectangles in an image based on their color. The code works well for non-overlapping rectangles, but it fails to detect overlapping rectangles. Here's code I am using
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([130, 255, 255])
mask = cv2.inRange(image_hsv, lower_blue, upper_blue)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for index, contour in enumerate(contours):
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
if len(approx) == 4:
(x, y, w, h) = cv2.boundingRect(approx)
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
Overlapping rectangles are either not detected at all or are detected as a single merged shape. This is problematic because I need to individually detect and crop each rectangle, even if they overlap.
I’ve Tried:
For eg. Sample Input Image
Outputs I get
Not getting the overlapping one's.
Upvotes: 0
Views: 120
Reputation: 4543
Overlapping rectangles are either not detected at all or are detected as a single merged shape. This is problematic because I need to individually detect and crop each rectangle, even if they overlap.
Your problem can be fixed.
On line 12, change this:
cv2.RETR_EXTERNAL
# It will not detect some parts of blue.
to:
cv2.RETR_TREE
#It will detect overlap.
On line 18, change this:
if len(approx) == 4:
to:
if contours:
#So we going to use cv2.drawContours
Comment out from line 19 to 23.
Add cv2.drawContours(img, contours, -1, (0,255,0), 3)
on line 25.
Snippet minor change:
import cv2
import numpy as np
# Load the image
img = cv2.imread('i.png')
# convert to grayscale
image_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([130, 255, 255])
mask = cv2.inRange(image_hsv, lower_blue, upper_blue)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for index, contour in enumerate(contours):
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
if contours:
#(x, y, w, h) = cv2.boundingRect(approx)
#cv2.rectangle(img,
#(x,y),(x+w,y+h),
#(0,255,0),
#2)
cv2.drawContours(img, contours, -1, (0,255,0), 3)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Screenshot:
There is another way to use movseevent
instead of cv2.drawContours
. If you want that.
Upvotes: 0