首页 > 解决方案 > OpenCV:从给定图像中分割每个数字。数字写在行矩阵的每个单元格中。每个单元格都以边距为界

问题描述

我一直在尝试从表单文档中识别手写字母(数字/字母)。众所周知,表单文档有 1d 行单元格,申请人必须在这些有界单元格中填写他们的信息。但是,我无法从边界框中分割数字(目前我的输入仅包含数字)。

我经历了以下步骤:

  1. 通过 opencv2 的“imread”方法读取图像(作为灰度图像)。初始图像尺寸:19 x 209(以像素为单位)。
pic = "crop/cropped000.jpg"
newImg = cv2.imread(pic, 0)
  1. 通过 opencv2 的“resize”方法将图像大小调整为原始大小的 200%。我使用了 INTER_AREA 插值。调整大小的图像尺寸:38 x 418(以像素为单位)
h,w = newImg.shape
resizedImg = cv2.resize(newImg, (2*w,2*h), interpolation=cv2.INTER_AREA)
  1. 应用 Canny 边缘检测。
v = np.median(resizedImg)
sigma = 0.33
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edgedImg = cv2.Canny(resizedImg, lower, upper)
  1. 裁剪轮廓并将它们保存为“BB”目录中的图像。
im2, contours, hierarchy = cv2.findContours(edgedImg.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

num = 0
for c in contours:
    x, y, w, h = cv2.boundingRect(c)
    num += 1
    new_img = resizedImg[y:y+h, x:x+w]
    cv2.imwrite('BB/'+str(num).zfill(3) + '.jpg', new_img)

整个代码总结:

pic = "crop/cropped000.jpg"
newImg = cv2.imread(pic, 0)

h,w = newImg.shape
print(newImg.shape)
resizedImg = cv2.resize(newImg, (2*w,2*h), interpolation=cv2.INTER_AREA)
print(resizedImg.shape)

v = np.median(resizedImg)
sigma = 0.33
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edgedImg = cv2.Canny(resizedImg, lower, upper)

im2, contours, hierarchy = cv2.findContours(edgedImg.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

num = 0
for c in contours:
    x, y, w, h = cv2.boundingRect(c)
    num += 1
    new_img = resizedImg[y:y+h, x:x+w]
    cv2.imwrite('BB/'+str(num).zfill(3) + '.jpg', new_img)

产生的图像张贴在这里: https ://imgur.com/a/GStIcdj

我不得不将图像尺寸加倍,因为 Canny 边缘检测正在为一个对象产生双边缘(但是,它仍然如此)。我也玩过其他 openCV 功能,如阈值、高斯模糊、扩张、侵蚀,但都是徒劳的。

标签: python-3.xopencvcanny-operatorhandwriting-recognition

解决方案


# 我们还需要一个日期单元格宽度参数:因为这对于 diff bank 可能有所不同
def crop_image_data_from_date_field(图像,new_start_h,new_end_h,new_start_w,new_end_w,cell_width):
    #for date 每个单元格具有相同的高度和宽度:此处宽度:25 px,因此线将根据宽度进行更改
    裁剪图像列表 = []
    起始宽度 = new_start_w
    for i in range(1,9): # as date 只有 8 个字段:DD/MM/YYYY
cropped_img = 图像[new_start_h:new_end_h, new_start_w + 1 :new_start_w+22] new_start_w = 起始宽度 + (i*cell_width)

cropped_img = cv2.resize(cropped_img, (28, 28)) image_name = 'cropped_date/cropped_'+ str(i) + '.png' cv2.imwrite(image_name, cropped_img) cropped_image_list.append(image_name) # print('cropped_image_list : ',cropped_image_list,len(cropped_image_list)) # rec_value = handwritten_digit_recog.recog_digits(cropped_image_list) recvd_value = custom_predict.predict_digit(cropped_image_list) # print('recvd val : ',recvd_value) return recvd_value

您需要指定每个单元格的宽度,它是 x、y、w、h。我想这会对你有所帮助。


推荐阅读