如何从图像中提取不同的边缘强度的矩形?(How to extract rectangles of v

2019-09-30 00:58发布

我试图从检查的图像中提取的账户号码。 我有逻辑是,我试图找到包含账号的矩形,切片边框,然后喂片到OCR来获取文本出来。

我现在面临的问题是当矩形并不是很突出,颜色浅,我不能够得到矩形轮廓,因为边缘未完全连接。

如何克服呢? 事情我试过,但没有工作的

  1. 我不能增加侵蚀迭代,更侵蚀,因为然后边缘与周围的黑色像素连接,并形成不同的形状。
  2. 降低阈值偏移可能有帮助,但是,它似乎效率不高。 由于代码必须与多种类型的图像的工作。 我可以开始偏移10和不断递增的偏移和检查,如果我发现了矩形或没有。 这将增加很多时间用于检查与突出的矩形能很好的偏移量为20以上。 而且,由于我没有一个条件,以检查是否矩形的边缘是突出与否,循环在所有的检查得到应用。

记住以上几点。 有人可以帮助我解决这个问题呢?

使用图书馆和版本

scikit-image==0.13.1
opencv-python==3.3.0.10

from skimage.filters import threshold_adaptive, threshold_local
import cv2

第1步

image = cv2.imread('cropped.png')

第2步

从skimage使用自适应阈值来去除背景,这样我就可以得到账号的矩形框。 这工作得很好了检查,其中矩形是比较明显的,但是当矩形边缘薄,或颜色较淡,门槛导致未连接的边缘,因为它的,我无法找到的轮廓。 我重视这样的例子在问题进一步下跌。

account_number_block = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
account_number_block = threshold_adaptive(account_number_block, 251, offset=20)
account_number_block = account_number_block.astype("uint8") * 255

第3步

侵蚀图像有点要尽量小断开的边缘连接

kernel = np.ones((3,3), np.uint8)

account_number_block = cv2.erode(account_number_block, kernel, iterations=5)

查找轮廓

(_, cnts, _) = cv2.findContours(account_number_block.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# cnts = sorted(cnts, key=cv2.contourArea)[:3]
rect_cnts = [] # Rectangular contours 
for cnt in cnts:
    approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
    if len(approx) == 4:
        rect_cnts.append(cnt)


rect_cnts = sorted(rect_cnts, key=cv2.contourArea, reverse=True)[:1]

工作实例

步骤1:原稿图像

步骤2:阈值处理后去除背景。

第3步:查找轮廓找账号的矩形框。

故障工作实例 -光矩形边界。

第1步:查看原图

步骤2:阈值处理后去除背景。 请注意,矩形的边缘不连接的,因为它的,我不能够得到轮廓出来。

第3步:查找轮廓找账号的矩形框。

Answer 1:

import numpy as np
import cv2
import pytesseract as pt
from PIL import Image


#Run Main
if __name__ == "__main__" :

    image = cv2.imread("image.jpg", -1)

    # resize image to speed up computation
    rows,cols,_ = image.shape
    image = cv2.resize(image, (np.int32(cols/2),np.int32(rows/2)))

    # convert to gray and binarize
    gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    binary_img = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9)

    # note: erosion and dilation works on white forground
    binary_img = cv2.bitwise_not(binary_img)

    # dilate the image to fill the gaps
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
    dilated_img = cv2.morphologyEx(binary_img, cv2.MORPH_DILATE, kernel,iterations=2)

    # find contours, discard contours which do not belong to a rectangle
    (_, cnts, _) = cv2.findContours(dilated_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    rect_cnts = [] # Rectangular contours 
    for cnt in cnts:
        approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
        if len(approx) == 4:
            rect_cnts.append(cnt)

    # sort contours based on area
    rect_cnts = sorted(rect_cnts, key=cv2.contourArea, reverse=True)[:1]

    # find bounding rectangle of biggest contour
    box = cv2.boundingRect(rect_cnts[0])
    x,y,w,h = box[:]

    # extract rectangle from the original image
    newimg = image[y:y+h,x:x+w]

    # use 'pytesseract' to get the text in the new image
    text = pt.image_to_string(Image.fromarray(newimg))
    print(text)

    cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
    cv2.imshow('Image', newimg)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

结果:03541140011724

结果:34785736216



文章来源: How to extract rectangles of varying edge intensity from images?