10

I'm trying to detect all the rectangles from the relational database. But some of the boxes are not being detected by my script. Please help me to do that. Thank you.

The Image: This is the image that I want to detect.

My Code:

#!/usr/bin/python
import cv2
import numpy as np

im = cv2.imread("table.png")

image = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(image,0,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

edge = cv2.Canny(thresh,30,200)
cont = cv2.findContours(edge,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]

for j,i in enumerate(cont):
   x,y,w,h = cv2.boundingRect(i)

   if (w*h>900):
     cv2.drawContours(image,[i],0,(0,0,255),3)

cv2.imshow("Image",image)

cv2.waitKey(0)  

OUTPUT:

My output

6
  • Arrows also create some rectangles, detecting them is a problem for you ? Commented Jan 30, 2020 at 6:01
  • which rectangles ? are they always the same, or does it change each try ? Commented Jan 30, 2020 at 6:19
  • Yunus Temurlenk I don't want to detect those arrows.and in some of the rectangle and some the rectangles are incompletely recognized. Commented Jan 30, 2020 at 6:26
  • 1
    @NaveenKumarJ you can use houghline but first you should find a way to get rid of the arrows. Commented Jan 30, 2020 at 7:04
  • Please search this forum or Google for other similar questions and their answers. Commented Jan 30, 2020 at 7:25

1 Answer 1

15

Here's an simple approach using thresholding + morphological operations.

  1. Obtain binary image. Load image, convert to grayscale, then adaptive threshold

  2. Fill rectangular contours. Find contours and fill the contours to create filled rectangular blocks.

  3. Perform morph open. We create a rectangular structuring element and morph open to remove the lines

  4. Draw rectangle. Find contours and draw bounding rectangles.


Here's each step visualized:

Using this screenshotted image (contains more border since the provided image has the rectangles too close to the border). You could add a border to the input image instead of screenshotting for more border area. Take a look at add border to image

Binary image

Filled rectangular contours

Morph open

Result


Code

import cv2

# Load iamge, grayscale, adaptive threshold
image = cv2.imread('1.png')
result = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,51,9)

# Fill rectangular contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (255,255,255), -1)

# Morph open
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=4)

# Draw rectangles
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 3)

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.waitKey()

Note: Depending on the image, you may have to modify the kernel size. For instance, it may be necessary to increase the kernel from (5, 5) to say (11, 11). In addition, you could increase or decrease the number of iterations when performing cv2.morphologyEx(). There is a trade-off when increasing or decreasing the kernel size as you may remove more or less of the lines. Again, it all varies depending on the input image.

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

Comments

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.