如何在不遗漏任何东西的情况下检测所有矩形框python opencv

问题描述

我正在尝试从关系数据库中检测所有矩形.但是我的脚本没有检测到一些盒子.请帮我这样做.谢谢.

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.

图片:

我的代码:

#!/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)  

输出:


解决方案

这是一个使用阈值+形态学运算的简单方法.

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

  1. 获取二值图像.加载图像,转换为灰度,然后自适应阈值

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

填充矩形轮廓.查找轮廓并填充轮廓以创建填充矩形块.

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

执行 morph open.我们创建一个矩形结构元素并 morph open 以移除线条

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

绘制矩形.查找轮廓并绘制边界矩形.

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

二值图像

填充矩形轮廓

变形打开

结果

代码

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()

注意:根据图像,您可能需要修改内核大小.例如,可能需要将内核从 (5, 5) 增加到 (11, 11).此外,您可以在执行 cv2.morphologyEx() 时增加或减少迭代次数.增加或减少内核大小时需要权衡取舍,因为您可能会删除更多或更少的行.同样,这一切都取决于输入图像.

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.

相关文章