1

image with rectangles

Hello! Mastering OpenCV, I encountered a problem: I can't find any of these boxes to them then cut. Tell me, please, what filters and logic to use?

#!/usr/bin/env python
import cv2
import os

img_path = os.path.join('img', '1.jpg')
image = cv2.imread(img_path)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 11, 17, 17)
edged = cv2.Canny(gray, 30, 200)

cv2.imshow('gray', gray)
cv2.waitKey(0)

cv2.imshow('edged', edged)
cv2.waitKey(0)


(_, cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)

    if len(approx) == 4:
        cv2.drawContours(image, [approx], -1, (0, 255, 0), 3)


cv2.imshow('result', image)
cv2.waitKey(0)

This example finds a lot of garbage, and all rectangles (not just those with background)

EDIT: OpenСV duplicates rectangle contours. How can i cut off duplicates?

4
  • I just started to learn opencv. there is an urgent task. I tried to use canny filter, then findContours Commented Jun 13, 2017 at 13:51
  • Post your code (edit it into your post) - show us where it's going wrong. Commented Jun 13, 2017 at 13:52
  • this done. i edit my post Commented Jun 13, 2017 at 13:59
  • if you are getting a lot of garbage it could be due to the canny thresholds that you are using, try tweaking them a little to get the edges of your rectangles. You may try removing the background noise or binarizing the image using a threshold in the grey image to remove impurities in the scanned image Commented Jun 13, 2017 at 14:07

2 Answers 2

1

You can use adaptive thresholding as a pre-processing step followed by gaussian blur before applying canny edge detection.

import cv2
import numpy as np

img = cv2.imread('image with boxes.jpg')
blur = cv2.GaussianBlur(img,(7,7),0)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
mask = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
canny = cv2.Canny(mask, 30, 200)
(_, cnts, _) = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)

    if len(approx) == 4:
        cv2.drawContours(img, [approx], -1, (0, 0, 255), 1)

cv2.imshow('result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

final image

As you can see no rectangles are allocated which do not have any background

Sign up to request clarification or add additional context in comments.

Comments

0

You are very close to the solution, while iterating the contours in for c in cnts: you are filtering contours on the basis of number of sides of polygon approximated from the contour, You just need to add filter for contour area as well in order to remove the smaller rectangles being detected, which can be done as:

for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)

    if len(approx) == 4 and cv2.contourArea(c) > 200:
        cv2.drawContours(image, [approx], -1, (0, 255, 0), 3)

1 Comment

thx, all the trash cleaned, but the question remains how to not allocate rectangles with no background

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.