spd
spd

Reputation: 354

OpenCV code fail to detect overlapping rectangles in an image

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

enter image description here

Outputs I get

enter image description here enter image description here enter image description here

Not getting the overlapping one's.

Upvotes: 0

Views: 120

Answers (1)

toyota Supra
toyota Supra

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:

enter image description here

There is another way to use movseevent instead of cv2.drawContours. If you want that.

Upvotes: 0

Related Questions