使用OpenCV从扫描的结构化纸张表格的jpg中检测所有矩形和轮廓

sf6xfgos  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(118)

作为一个OCR新手,我试图检测扫描文档中的所有矩形/框,如x1c 0d1x所示
然而,下面提供的代码片段的输出无法从图像中识别相当多的矩形。

import cv2
import imutils
import warnings
import numpy as np

warnings.filterwarnings('ignore')
import matplotlib.pyplot as plt

img = cv2.imread("example.jpg") 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

threshold = cv2.adaptiveThreshold(
    gray.copy(), 
    255, # maximum value assigned to pixel values exceeding the threshold
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,  # gaussian weighted sum of neighborhood
    cv2.THRESH_BINARY_INV,  # thresholding type 
    301, # block size (5x5 window)
    21) # constant

font = cv2.FONT_HERSHEY_COMPLEX
keypoints = cv2.findContours(threshold.copy(), 
                             cv2.RETR_CCOMP, 
                             cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(keypoints)
working_image = None
idx = 1
cropped_field_images = []

contour_list = list(contours)
contour_list.reverse()
rev_contours = tuple(contour_list)

for contour in rev_contours:   
    x,y,w,h = cv2.boundingRect(contour) 
    area = cv2.contourArea(contour)
    approx = cv2.approxPolyDP(contour, 10, True)
    location = None
    if len(approx) == 4 and area > 1500 : #if the shape size is rectangular
        working_image = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)   
        cv2.putText(img, str(idx), (x, y), font, 1, (0,0,255))
        
        location = approx
        mask = np.zeros(gray.shape, np.uint8) #Create a blank mask
        rect_img = cv2.drawContours(mask, [location], 0, 255, -1) 
        rect_img = cv2.bitwise_and(img, img, mask = mask) 
        
        (x, y) = np.where(mask==255)
        (x1, y1) = (np.min(x), np.min(y))
        (x2, y2) = (np.max(x), np.max(y))
        cropped_rect = gray[x1:x2+1, y1:y2+1]
        
        cropped_field_images.append(cropped_rect)
        
        idx += 1
    
plt.figure(figsize = (11.69*2,8.27*2))
plt.axis('off')
plt.imshow(cv2.cvtColor(working_image, cv2.COLOR_BGR2RGB));

上面的代码的结果是下面的图片。任何左上角没有数字和绿色边界的矩形都不能被上面的代码识别,并被标记为红色星星。我在上面的代码片段中尝试改变opencv 2自适应阈值的类型,块大小和常量,但这些红色星号的矩形总是从输出结果中被忽略。

我错过了什么?我可以考虑什么来确保这些框/区域不会在结果中被忽略?任何优化自适应阈值以确保所有红色星号矩形部分都包含在输出结果中的帮助都将不胜感激。

f0ofjuux

f0ofjuux1#

我会这样解决你的问题:
花一些时间手动获取每个字段的左上角和右下角的位置。这将是您的地面事实,它需要可靠,所以最好这样做三次并平均位置。
运行检测,并获得所有检测到的字段的左上角和右下角的位置(如果没有检测到某些字段,请不要担心)
现在,您需要将检测到的点与地面实况点进行匹配。您可以开始假设文档已完美扫描,因此只需对检测点应用偏移量即可匹配地面实况点。
在现实中,文档可能不是完全垂直扫描的(您需要旋转),或者文档可能来自图片,在这种情况下,您需要应用单应性来校正拍摄图片的Angular 。
当你的点与地面实况匹配时(它们不会完全匹配,所以我建议使用RANSAC进行匹配),你可以使用地面实况点来检测图片中的所有字段,裁剪它们,我想净步骤是对手写字段运行OCR来提取文本。
你可以看一下这个链接,了解如何做到这一点
https://learnopencv.com/image-alignment-feature-based-using-opencv-c-python/
一定要看看官方的OpenCV文档,其中有非常好的例子,比如下面这个
https://docs.opencv.org/3.4/dc/dc3/tutorial_py_matcher.html

相关问题