import cv2
import pytesseract
import numpy as np
from pytesseract import Output
import re
from pytesseract import image_to_string
import matplotlib.pyplot as plt
kernel = np.ones((5,5),np.uint8)
# 去除噪声
# 这对日期有效
image = cv2.imread('1.Chase Bank_test.jpg')
result = image.copy()
gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# 移除水平线
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1))
remove_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(remove_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(result, [c], -1, (255,255,255), 5)
# 移除垂直线
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,40))
remove_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(remove_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(result, [c], -1, (255,255,255), 5)
date_list= []
d = pytesseract.image_to_data(thresh, output_type=Output.DICT)
#d = pytesseract.image_to_data(thresh)
keys = list(d.keys())
#日期模式 = '([\d]+\/[\d]+)'
#使用正则表达式获取日期
date_pattern = '^(0[1-9]|[12]|[1-9]|3[02])/'
description = ''
n_boxes = len(d['text']) # 制作边界框直到文本长度,将n_boxes放入循环中
for i in range(n_boxes):
if int(d['conf'][i]) > 10:
if re.match(date_pattern, d['text'][i]):
(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
detect_img = cv2.rectangle(result, (x, y), (x + w, y + h), (0, 300, 0), 2) # 对日期的检测效果很好
# 裁剪检测到的日期并添加到date_list
#for i in range(n_boxes):
# crop_detect_img = detect_img[y:y+h+8, x:x+w+8]
# test_list=(image_to_string((crop_detect_img)))
# print(test_list)
#date_list.append(crop_detect_img)
#print(test_list)
crop_detect_img = detect_img[y:y+h+10, x:x+w+10]
crop_date_gray = cv2.cvtColor(crop_detect_img,cv2.COLOR_BGR2GRAY)
crop_date_thresh = cv2.threshold(crop_date_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
date=(image_to_string((crop_date_thresh)))
print(date)
plt.figure(figsize = (20,20))
plt.imshow(crop_date_thresh)
#plt.imshow()
plt.imshow(result)
#print(result)
contours = contours[1] if imutils.is_cv3() else contours[0]
ROI_number = 0
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
ROI = image[y:y+h, x:x+w]
cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
cv2.rectangle(result,(x,y),(x+w,y+h),(36,255,12),2)
ROI_number += 1
plt.imshow('thresh', thresh)
**
我无法弄清楚如何在一个循环中从图像中裁剪检测到的日期,以便我可以将裁剪后的图像传递给Tesseract OCR并添加到日期列表中。请建议我使用Python的更好的免费OCR软件,这样我可以生成更好的结果。我使用OpenCV和正则表达式来解决这个问题。
**如您所见,它正在从图像中查找所有日期并制作边界框
回答:
您可以绘制边界框但不知道如何裁剪它?这很奇怪。
无论如何,我在下面添加了相关的代码。如果这不是正确的循环,至少您现在知道如何在numpy中裁剪图像:
n_boxes = len(d['text']) # 制作边界框直到文本长度,将n_boxes放入循环中
for i in range(n_boxes):
if int(d['conf'][i]) > 10:
if re.match(date_pattern, d['text'][i]):
(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
# 裁剪ROI并保存到文件
cropped = gray[y : y+h, x : x+w]
imwrite('crop_' + str(i) + '.png', cropped)
detect_img = cv2.rectangle(result, (x, y), (x + w, y + h), (0, 300, 0), 2)