vftw
vftw

Reputation: 1697

Split image by color using OpenCV

I am trying to split this image by the gray color of each rectangle.

The idea is to return the coordinate of each corner so I can use it to process what is inside.

I am a OpenCV newbie so I would like to know what is the best approach to do this. Is findContours enough to get these coordinates or is there a better function for this?

Regards

enter image description here

Upvotes: 0

Views: 2109

Answers (1)

Rotem
Rotem

Reputation: 32144

It simple to solve using findContours:

  • Read input image as Grayscale (not as RGB).
  • Apply threshold, and inverse polarity (make all gray pixel white, and background black).
  • Find contours on threshold image.
  • Find bounding rectangle of each contour.

The solution draws a green rectangle around each contour, for testing.

Here is a working code sample:

import numpy as np
import cv2

# Read input image as Grayscale
img = cv2.imread('boxes.png', cv2.IMREAD_GRAYSCALE)

# Convert img to uint8 binary image with values 0 and 255
# All white pixels above 250 goes to 255, and other pixels goes to 0
ret, thresh_gray = cv2.threshold(img, 250, 255, cv2.THRESH_BINARY)

# Inverse polarity
thresh_gray = 255 - thresh_gray


# Find contours in thresh_gray.
contours = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # [-2] indexing takes return value before last (due to OpenCV compatibility issues).

corners = []

# Iterate contours, find bounding rectangles, and add corners to a list
for c in contours:
    # Get bounding rectangle
    x, y, w, h = cv2.boundingRect(c)

    # Append corner to list of corners - format is corners[i] holds a tuple: ((x0, y0), (x1, y1))
    corners.append(((x, y), (x+w, y+h)))

# Convert grayscale to BGR (just for testing - for drawing rectangles in green color).
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# Draw green rectangle (for testing)
for c in corners:
    cv2.rectangle(out, c[0], c[1], (0, 255, 0), thickness = 2)

cv2.imwrite('out.png', out)  #Save out to file (for testing).


# Show result (for testing).
cv2.imshow('out', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:
enter image description here

List of corners:

corners = [((491, 153), (523, 181)),
           ((24, 151), (68, 178)),
           ((231, 123), (277, 158)),
           ((442, 103), (488, 131)),
           ((7, 99), (76, 132)),
           ((211, 75), (285, 110)),
           ((268, 57), (269, 58)),
           ((420, 49), (494, 84)),
           ((5, 47), (58, 83)),
           ((213, 18), (267, 59)),
           ((420, 0), (477, 33))]

Upvotes: 2

Related Questions