Keanu
Keanu

Reputation: 231

Detect white rectangle on black & white image and crop (OpenCV)

I'm struggling with cropping an image to the size of a rectangle, which is placed inside of the image. This is the original image:

this is my original image

So far I was able to input it, convert its colors to a HSV color space and applying threshold on it. This is my code so far:

import cv2

#Read input image
img = cv2.imread('rdm_generated_image.png')

#convert from BGR to HSV color space
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

#get the saturation plane - all black/white/gray pixels are zero, and colored pixels are above zero.
s = hsv[:, :, 1]

#apply threshold on s
ret, thresh = cv2.threshold(s, 8, 255, cv2.THRESH_BINARY)

#invert colors, so every dark spots are now white
image = cv2.bitwise_not(thresh)

cv2.imwrite("image.png", image)

With this being done the program outputs this:

output

Now I want to crop the image to the big box in the middle only, but I'm not able to detect the contours of it.

Crop it to this size

I tried it with cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) and a few other functions, but I was not successful yet. If this should be the wrong way of doing it, please correct me. Help is appreciated, since I'm kind of unexperienced with OpenCV.

Thanks in advance!

Upvotes: 0

Views: 10477

Answers (1)

fmw42
fmw42

Reputation: 53089

Here is one way to do that in Python/OpenCV.

  • Read the image
  • Convert to gray
  • Threshold
  • Find contours
  • Filter on approx expected area
  • Draw contours
  • Save results

Input:

enter image description here

import cv2
import numpy as np

#Read input image
img = cv2.imread('boxes.png')

#convert from BGR to HSV color space
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#apply threshold
thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY)[1]

# find contours and get one with area about 180*35
# draw all contours in green and accepted ones in red
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
#area_thresh = 0
min_area = 0.95*180*35
max_area = 1.05*180*35
result = img.copy()
for c in contours:
    area = cv2.contourArea(c)
    cv2.drawContours(result, [c], -1, (0, 255, 0), 1)
    if area > min_area and area < max_area:
            cv2.drawContours(result, [c], -1, (0, 0, 255), 1)

# save result
cv2.imwrite("box_found.png", result)

# show images
cv2.imshow("GRAY", gray)
cv2.imshow("THRESH", thresh)
cv2.imshow("RESULT", result)
cv2.waitKey(0)


Result:

enter image description here

Upvotes: 6

Related Questions