Python 如何改进印地语文本提取?

Python 如何改进印地语文本提取?,python,python-tesseract,pdf-extraction,Python,Python Tesseract,Pdf Extraction,我试图从PDF中提取印地语文本。我尝试了所有从PDF中提取的方法,但没有一种有效。有人解释了为什么它不起作用,但没有这样的答案。因此,我决定将PDF转换为图像,然后使用pytesseract提取文本。我已经下载了印地语训练的数据,但是这也会给出非常不准确的文本 这是PDF()中的实际印地语文本: 这是我目前的代码: import fitz filepath = "D:\\BADI KA BANS-Ward No-002.pdf" doc = fitz.open(file

我试图从PDF中提取印地语文本。我尝试了所有从PDF中提取的方法,但没有一种有效。有人解释了为什么它不起作用,但没有这样的答案。因此,我决定将PDF转换为图像,然后使用
pytesseract
提取文本。我已经下载了印地语训练的数据,但是这也会给出非常不准确的文本

这是PDF()中的实际印地语文本:

这是我目前的代码:

import fitz

filepath = "D:\\BADI KA BANS-Ward No-002.pdf"

doc = fitz.open(filepath)
page = doc.loadPage(3)  # number of page
pix = page.getPixmap()
output = "outfile.png"
pix.writePNG(output)
from PIL import Image
import pytesseract

# Include tesseract executable in your path
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

# Create an image object of PIL library
image = Image.open('outfile.png')

# pass image into pytesseract module
# pytesseract is trained in many languages
image_to_text = pytesseract.image_to_string(image, lang='hin')

# Print the text
print(image_to_text)
这是一些输出示例:

कार बिता देवी व ०... नाम बाइुनान िक०क नाक तो
पति का नाव: रवजी लात. “50९... पिला का सामशामाव.... “पति का नाम: बादुलल
कान सब: 43 लसमनंध्या: 93९. मकान ंब्या: 3९
आप: 29 _ लिंग सी. | आइ 57 लिंग पुरुष आप: 62 लिंग सी
एजगल्णब्णस्य (बन्द जगाख्मिणण्य
नमः बायगी बसों ०४... नि बयावर्णो ०५०... निफर सनक नी
चिता का नामजबूजल वर्ष.“ ००० | पिला का नामब्राइलाल वर्षो... 0 2... | पिता कामामशुल चब्द .... “20०
|सकानसंब्या: 43९ बसवकंब्या: 43९. कान संब्या: 44
जाए: 27 लिंग सो कई: 27 नि खी मा लिंग पुरुष
这个问题有一个答案,它似乎告诉我们如何做,但没有提供任何解释


除了自己训练语言模型之外,还有其他方法吗?

似乎模块
pdfplumber
完成了以下工作:

import pdfplumber

pdf = pdfplumber.open('BADI KA BANS-Ward No-002.pdf')

pages = pdf.pages
text = ""

for page in pages:
    text += page.extract_text()

pdf.close()

with open('output.txt', 'w', encoding="utf8") as f:
    f.write(text)
输出(片段):

输入(第一页):

但我对印地语一无所知。我不明白输出是否足够好

要安装模块(Windows 7、Python 3.8),请执行以下操作:


据推测,该模块甚至可以处理表。不过我还没有试过。

似乎模块
pdfplumber
起作用了:

import pdfplumber

pdf = pdfplumber.open('BADI KA BANS-Ward No-002.pdf')

pages = pdf.pages
text = ""

for page in pages:
    text += page.extract_text()

pdf.close()

with open('output.txt', 'w', encoding="utf8") as f:
    f.write(text)
输出(片段):

输入(第一页):

但我对印地语一无所知。我不明白输出是否足够好

要安装模块(Windows 7、Python 3.8),请执行以下操作:


据推测,该模块甚至可以处理表。不过,我还没有试过。

如果您想从这些“卡片”中获取文本,我已经通过模块
表格
在第3页上实现了这一点:

import tabula

pdf_file = "BADI KA BANS-Ward No-002.pdf"
page = 3

x = 30      # left edge of the table
y = 160     # top edge of the table
w = 173     # width of a card
h = 73      # height of a card
photo = 61  # width of a photo

rows = 8    # number of rows of the table
cols = 3    # number of columns of the table

counter = 1

def get_area(row, col):
    ''' return area of the card in given position in the table '''
    top    = y + h * row
    left   = x + w * col
    bottom = top + h
    right  = left + w - photo
    return (top, left, bottom, right)

for row in range(rows):
    for col in range(cols):
        file_name = "card_" + str(counter).zfill(3) + ".txt"
        tabula.convert_into(pdf_file, file_name,
        pages=page,
        output_format = "csv",
        java_options = "-Dfile.encoding=UTF8",
        lattice = False,
        area = get_area(row, col))
        counter += 1
输入:

输出

24个txt文件:

card_001.txt
card_002.txt
card_003.txt
card_004.txt
.
.
.
card_023.txt
card_024.txt
卡片_001.txt:

1 RBP2469583
नरम: आरतल चररलर
नपतर कर नरम:लरलर ररम चररल
मकरन सखजर: १९
आज:  21 ललग: सल
卡片_002.txt

2 MRQ3101367
नरम: सरज दरल
नपतर कर नरम:ररमररतरर
मकरन सखजर: रल /18
आज:  44 ललग: सल
卡片_024.txt

24 RBP0230979
नरम: सनमतकरर
पनत कर नरम: हररलसह
मकरन सखजर: 13
आज:  41 ललग: सल
据我所知,所有的“卡片”都有相同的尺寸。该解决方案可以应用于所有看起来相似的页面。不幸的是,这些页面存在差异。因此,每个页面的初始变量都必须更改。我认为没有办法自动进行更改。除此之外,卡片的号码可以从卡片上取下,而不是从简单的计数器上取下


如果您想从这些“卡片”中获取文本,我已经设法通过模块
表格
在第3页这样做:

import tabula

pdf_file = "BADI KA BANS-Ward No-002.pdf"
page = 3

x = 30      # left edge of the table
y = 160     # top edge of the table
w = 173     # width of a card
h = 73      # height of a card
photo = 61  # width of a photo

rows = 8    # number of rows of the table
cols = 3    # number of columns of the table

counter = 1

def get_area(row, col):
    ''' return area of the card in given position in the table '''
    top    = y + h * row
    left   = x + w * col
    bottom = top + h
    right  = left + w - photo
    return (top, left, bottom, right)

for row in range(rows):
    for col in range(cols):
        file_name = "card_" + str(counter).zfill(3) + ".txt"
        tabula.convert_into(pdf_file, file_name,
        pages=page,
        output_format = "csv",
        java_options = "-Dfile.encoding=UTF8",
        lattice = False,
        area = get_area(row, col))
        counter += 1
输入:

输出

24个txt文件:

card_001.txt
card_002.txt
card_003.txt
card_004.txt
.
.
.
card_023.txt
card_024.txt
卡片_001.txt:

1 RBP2469583
नरम: आरतल चररलर
नपतर कर नरम:लरलर ररम चररल
मकरन सखजर: १९
आज:  21 ललग: सल
卡片_002.txt

2 MRQ3101367
नरम: सरज दरल
नपतर कर नरम:ररमररतरर
मकरन सखजर: रल /18
आज:  44 ललग: सल
卡片_024.txt

24 RBP0230979
नरम: सनमतकरर
पनत कर नरम: हररलसह
मकरन सखजर: 13
आज:  41 ललग: सल
据我所知,所有的“卡片”都有相同的尺寸。该解决方案可以应用于所有看起来相似的页面。不幸的是,这些页面存在差异。因此,每个页面的初始变量都必须更改。我认为没有办法自动进行更改。除此之外,卡片的号码可以从卡片上取下,而不是从简单的计数器上取下


我将给出一些如何处理图像的想法,但我将仅限于给定文档的第3页,即问题中显示的页面

为了将PDF页面转换为一些图像,我使用了

对于OCR,我使用的是
pytesseract
,但我使用的不是
lang='hin'
,而是
lang='Devanagari'
,参见。通常,请确保从Tesseract文档,特别是

以下是对整个过程的(冗长)描述:

  • 对图像进行反向二值化以查找轮廓:黑色背景上的白色文本、形状等
  • 找到所有轮廓,过滤掉两个非常大的轮廓,即这两个表格
  • 提取两个表之外的文本:
  • 屏蔽二值化图像中的表
  • 进行形态闭合以连接剩余的文本行
  • 查找这些文本行的轮廓和边界矩形
  • 运行
    pytesseract
    提取文本
  • 提取两个表中的文本:
  • 从当前表中提取单元格,更好:它们的边界矩形
  • 对于第一个表:
  • 运行
    pytesseract
    按原样提取文本
  • 关于第二个表:
  • 填充数字周围的矩形,以防止OCR输出错误
  • 遮住左(印地语)和右(英语)部分
  • 使用左侧的
    lang='Devaganari'
    和右侧的
    lang='eng'
    运行
    pytesseract
    ,以提高两者的OCR质量
  • 这就是全部代码:

    导入cv2
    将numpy作为np导入
    导入PDF2图像
    导入pytesseract
    #以适当的质量从PDF中提取第3页
    第3页=np.array(pdf2image.convert_from_path('BADI KA BANS Ward No-002.pdf'),
    第一页=3,最后一页=3,
    dpi=300,灰度=真)[0])
    #轮廓搜索的逆二值化
    thr=cv2.阈值(第3页,第128页,第255页,cv2.阈值二进制输入)[1]
    #在OpenCV版本中查找等高线w.r.t
    cnts=cv2.找到的孔(thr、cv2.外部翻新、cv2.链约无)
    如果len(cnts)==2个其他cnts[1],则cnts=cnts[0]
    #步骤1:提取两个表之外的文本
    #把这两张桌子遮住
    cnts_表=[cv2.contourArea(cnt)>10000时cnt中cnt的cnt]
    no_tables=cv2.drawContours(thr.copy(),cnts_tables,-1,0,cv2.FILLED)
    #在两个表之外查找文本的边界矩形
    no_tables=cv2.morphologyEx(no_tables,cv2.MORPH_CLOSE,np.full((21,51),255))
    cnts=cv2.查找到的对象(无表,cv2.RETR\u外部,cv2.链约无)
    如果len(cnts)==2个其他cnts[1],则cnts=cnts[0]
    rects=sorted([cv2.boundingRect(cnt)用于cnt中的cnt],key=lambda r:r[1])
    #从每个边框中提取文本
    打印('\n两个表之外的跟踪文本\n')
    对于矩形中的(x,y,w,h):
    text=pytesseract.image_to_字符串(第3页[y:y+h,x:x+w],
    配置='--psm 6',lang='Devanagari')
    text=text.replace('\n','').replace('\f','')
    打印('x:{},y:{},文本:{}'。格式(x,y,文本))
    #步骤2:从两个表的内部提取文本
    rects=已排序