我正在执行一项任务,从 pdf 文件中提取一些信息(印地语)并将其转换为数据框。
我尝试了很多东西,关注了很多文章,以及关于堆栈溢出的答案。我尝试了不同的库,如 easy OCR、paddle OCR 等,但无法获得正确的输出。
这是文档的链接。 链接
我尝试过的事情:
我似乎无法获得创建边界框的确切轮廓。下面你可以看到我得到的输出图像。
我需要的是将这些信息转换为数据框,其中的列为:- नाम: 请注意: मकान संख्याः等等。
下面是我用来获取数据的代码:-
import cv2
import pytesseract
import numpy as np
from pytesseract import Output
image = cv2.imread('pages_new/page3.jpg')
img = image.copy()
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Filter for ROI using contour area and aspect ratio
countour = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
countour = countour[0] if len(countour) == 2 else countour[1]
for c in countour:
area = cv2.contourArea(c)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.05 * peri, True)
x,y,w,h = cv2.boundingRect(approx)
aspect_ratio = w / float(h)
if area > 10000 and aspect_ratio > .5:
mask[y:y+h, x:x+w] = image[y:y+h, x:x+w]
h, w, c = img.shape
boxes = pytesseract.image_to_boxes(img)
for b in boxes.splitlines():
b = b.split(' ')
img = cv2.rectangle(img, (int(b[1]), h - int(b[2])), (int(b[3]), h - int(b[4])), (0, 255, 0), 2)
d = pytesseract.image_to_data(img, output_type=Output.DICT)
n_boxes = len(d['text'])
for i in range(n_boxes):
if int(d['conf'][i]) > 60:
(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
img2 = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# cv2.imshow('img', img)
# cv2.imshow('img2', img2)
# Perfrom OCR with Pytesseract
data = pytesseract.image_to_string(mask, lang='Devanagari', config='--psm 6')
print(data)
# cv2.imshow('thresh', thresh)
# cv2.imshow('mask', mask)
此外,如果页面上的信息发生变化,谁能确认一下,我们是否必须为所有文档编写不同的代码,或者我们可以获得所有文档的通用脚本?
我也在研究同样的概念,从CEO网站下载的选民名单中提取选民信息。我正在为卡纳达的卡纳塔克邦做事。我正在使用在线免费提供的工具将 PDF 转换为图像。然后使用 Matlab 将一整页的图像拆分到每个选民的盒子中。
我这样做是因为没有一个可用的转换器能够很好地处理具有这么多边界框的整页。此外,要提取的最重要数据是列表中的选民编号。这至少在我们的 PDF 中不够清晰,无法提取为英文数字。
所以,我根据文件的行和列来计算数字。对于单独文件中的选民,我手动输入数据。
所以,概念是:
使用任何免费网站手动将一个 pdf 文件转换为多个图像。
将图像转换为黑白图像,这样您就可以在没有任何计算机视觉工具的情况下很容易地分成盒子。 (基于线)。
将每个提取的盒子保存为图像文件以供进一步参考或将其发送到 OCR 库。
史诗号码,姓名,门牌号和父亲,监护人姓名可以轻松提取。但是所需的主要数字(在我的情况下,不确定你的),列表中的数字,需要计算和手动验证,因为它不能被任何可用的库提取。
这里 是我用来转换图像中的 Kanada 文本的库 Tesseract。这是开源库,也可以提取印地语。
因此,无需重新发明轮子,您可以进行一些手动处理,然后使用此工具进行更好的文本提取,从而节省大量时间。
我很快会将我的代码文件上传到公共 github 存储库并在此处共享。使用这些文件,您可以将页面转换为每个用户的图像。您可以根据 Ur 的要求使用它。代码在 Matlab 中。
https://github.com/tesseract-ocr/tesseract
[PS:这可能是为了卡纳塔克邦的选举,我将在商店中发布我的 android/iOS 应用程序。这些应用程序将以英文显示此选民名单。可使用姓名、门牌号码或选民的 EPIC 号码轻松搜索。在上一次卡纳塔克邦议会选举中,我只在谷歌游戏商店中发布了安卓应用程序。由于隐私政策问题,它已被删除。需要明确提及该信息可在免费公共领域获得。]
我可以使用以下代码获取数据:-
import cv2
import numpy as np
import pdf2image
import pytesseract
# Extract page 3 from PDF in proper quality
page_3 = np.array(pdf2image.convert_from_path('ROLL_Download.aspx.pdf',
first_page=3, last_page=3,
dpi=300, grayscale=True)[0])
# Inverse binarize for contour finding
thr = cv2.threshold(page_3, 128, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(thr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts_tables = [cnt for cnt in cnts if cv2.contourArea(cnt) > 10000]
no_tables = cv2.drawContours(thr.copy(), cnts_tables, -1, 0, cv2.FILLED)
data = []
rects = sorted([cv2.boundingRect(cnt) for cnt in cnts_tables], key=lambda r: (r[1], r[0]))
for i_r, (x, y, w, h) in enumerate(rects, start=1):
cnts = cv2.findContours(page_3[y+1:y+h-1, x+1:x+w-1], cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
inner_rects = sorted([cv2.boundingRect(cnt) for cnt in cnts], key=lambda r: (r[1], r[0]))
print('\nExtract texts inside table {}\n'.format(i_r))
for (xx, yy, ww, hh) in inner_rects:
# Set current coordinates w.r.t. full image
xx += x
yy += y
# Get current cell
cell = page_3[yy+2:yy+hh-2, xx+2:xx+ww-2]
# Floodfill rectangles around numbers
ys, xs = np.min(np.argwhere(cell == 0), axis=0)
print("The value for xs:{} and ys:{}".format(xs, ys))
temp = cv2.floodFill(cell.copy(), None, (xs, ys), 255)[1]
mask = cv2.morphologyEx(thr[yy+2:yy+hh-2, xx+2:xx+ww-2].copy(), cv2.MORPH_DILATE, np.full((ww, hh),255))
cnts = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
boxes = sorted([cv2.boundingRect(cnt) for cnt in cnts], key=lambda b: b[0])
# Extract texts from each part of the current cell
for x_b, y_b, w_b, h_b in boxes:
# print("The value for i_b is:",i_b)
text = pytesseract.image_to_string(
temp[y_b:y_b+h_b, x_b:x_b+w_b],
config='--psm 6',
lang='Devanagari')
#text = text.replace('\f', '')
print('x: {}, y: {}, text:\n{}'.format(xx, yy, text))
data.append(text)
下面是输出:-
Extract texts inside table 1
The value for xs:13 and ys:0
x: 103, y: 209, text:
1 WEZ1761006
नाम : भीमसेन
पिता का नाम : बच्चू सिंह
मकान संख्या: देव नगर Photo is
आयु : 33 लिंग : पुरुष Available
The value for xs:13 and ys:0
x: 857, y: 209, text:
2 WEZ1391713
नाम : पूजा कुमारी
पिता का नाम : विपिन सोनी
मकान संख्याः वार्ड नं1 Photo is
आयु : 23 लिग : स्त्री Available
The value for xs:13 and ys:0
x: 1610, y: 209, text:
3 WEZ1781897
नाम : सोनू
पति का नाम : राजू
मकान संख्याः वार्ड नं2 Photo is
आयु : 3 लिग : स्त्री Available
Extract texts inside table 2
The value for xs:13 and ys:41
x: 103, y: 507, text:
#174 WEZ1735174
नाम : रागिणी कुमारी कामत
पिता का नाम : संतोष कामत
मकान संख्याः 31 Photo is
आयु : 19 लिग : स्त्री Available
The value for xs:13 and ys:41
x: 857, y: 507, text:
5 WEZ1766005
नाम : पर्तीक सिंग चिडे
माता का नाम : कुलविंदर कौर
मकान संख्याः देव नगर ,वार्ड नं. 2 Photo is
आयु : 20 लिग : पुरुष Available
The value for xs:13 and ys:41
x: 1610, y: 507, text:
[|] WEZ1755230
नाम : रीता देवी
पति का नाम : प्रेम यादव
मकान संख्या: हाऊस नं. 05 Photo is
आयु : ॐ लिग : स्त्री Available
Extract texts inside table 3
The value for xs:13 and ys:0
x: 103, y: 807, text:
7 WEZ1758721
नाम : विश्व जीत वर्मा
पिता का नाम : राम चद्र
मकान संख्या: हाऊस नं. 10, वार्ड नं. 2 Photo is
आयु : 25 लिंग : पुरुष Available
The value for xs:13 and ys:0
x: 857, y: 807, text:
। | WEZ1758739
नाम : हिम्मत वर्मा
पिता का नाम : राम चद्र
मकान संख्या: हाऊस नं. 10, वार्ड नं. 2 Photo is
आयु : 23 लिंग : पुरुष Available
The value for xs:13 and ys:0
x: 1610, y: 807, text:
[१ WEZ1427087
नाम : सोनू यादव
पिता का नाम : ददन यादव
मकान संख्या: हाऊस नं. 228 Photo is
आयु : 23 लिंग : पुरुष Available
我试着按照上面的代码提取文本。它给出了正确的值。但是一个问题出现了。当它提取单元格 19、20 和 21 时,它同时提供了所有三个单元格的文本。