从具有不同结构的表单中提取字段
Extracting fields from forms with varying structures
我正在尝试从余额中提取某些字段 sheet。例如,对于以下余额 sheet:
,我希望能够知道 'Inventory' 的值为 1,277,838
目前,我正在使用 Tesseract 将图像转换为文本。但是,这种转换会产生文本流,因此很难将字段与其值相关联(因为这些值并不总是紧挨着相应字段的文本)。
经过一番搜索,我了解到 Tesseract 可以使用 uzn 文件读取图像的区域。但是,余额 sheet 值的特定区域可能会因表格而异,因此我对可以确定 'Inventory' 和 1,277,838 在同一行上的任何解决方案感兴趣。理想情况下,我想要文本的网格结构输出(这样我就可以在空间上分辨出哪些文本块在同一 rows/columns 中)。
谁能帮我解释一下我是怎么做到这个结果的?
我一直在使用 Tesseract 和 Python(pytesseract 库)执行类似的任务。我已经能够使用 Tesseract 的 .hocr 输出文件 (https://en.wikipedia.org/wiki/HOCR) 在页面上找到我的搜索词的位置 (例如 'Inventory'),然后在一小部分上重新 运行 Tesseract页面的位置,使其在该区域具有更高的准确性。这是我用来解析 Tesseract 的 HOCR 输出的代码:
def parse_hocr(search_terms=None, hocr_file=None, regex=None):
"""Parse the hocr file and find a reasonable bounding box for each of the strings
in search_terms. Return a dictionary with values as the bounding box to be used for
extracting the appropriate text.
inputs:
search_terms = Tuple, A tuple of search terms to look for in the HOCR file.
outputs:
box_dict = Dictionary, A dictionary whose keys are the elements of search_terms and values
are the bounding boxes where those terms are located in the document.
"""
# Make sure the search terms provided are a tuple.
if not isinstance(search_terms,tuple):
raise ValueError('The search_terms parameter must be a tuple')
# Make sure we got a HOCR file handle when called.
if not hocr_file:
raise ValueError('The parser must be provided with an HOCR file handle.')
# Open the hocr file, read it into BeautifulSoup and extract all the ocr words.
hocr = open(hocr_file,'r').read()
soup = bs.BeautifulSoup(hocr,'html.parser')
words = soup.find_all('span',class_='ocrx_word')
result = dict()
# Loop through all the words and look for our search terms.
for word in words:
w = word.get_text().lower()
for s in search_terms:
# If the word is in our search terms, find the bounding box
if len(w) > 1 and difflib.SequenceMatcher(None, s, w).ratio() > .5:
bbox = word['title'].split(';')
bbox = bbox[0].split(' ')
bbox = tuple([int(x) for x in bbox[1:]])
# Update the result dictionary or raise an error if the search term is in there twice.
if s not in result.keys():
result.update({s:bbox})
else:
pass
return result
这让我可以在 HOCR 文件中搜索适当的术语和 return 该特定单词的边界框。然后,我可以在页面的一个非常小的子集上将边界框稍微扩展为 运行 Tesseract。这比仅对整个页面进行 OCR 处理具有更高的准确性。显然,这些代码中有一些是我特有的,但它应该为您提供了一个起点。
This page 对于找到合适的论据以提供给 Tesseract 非常有帮助。我发现页面分割模式对于获得图像小部分的准确结果非常重要。
正如gaw89 已经提到的,Tesseract 可以输出比仅作为流的文本更多的信息。 hocr fileformat 还为您提供了每个段落、行、单词的位置(边界框):
$ tesseract 4LV05.png out -l eng hocr
然后你可以通过简单地
找到单词"Inventory"的边界框
$ grep 'Inventory' out.hocr
<span class='ocr_line' id='line_1_5' title="bbox 23 183 112 204; baseline 0 -5; x_size 21; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_15' title='bbox 23 183 112 204; x_wconf 93'>Inventory</span>
因此,这个词的边界框从 183 垂直跨越到 204,对于这个标签的相应值,我们现在必须在同一垂直方向上搜索框 space。例如,这可以通过
实现
$ grep 'bbox [0-9]* 18[0-9]' out.hocr
<p class='ocr_par' id='par_1_4' lang='eng' title="bbox 23 183 112 204">
<span class='ocr_line' id='line_1_5' title="bbox 23 183 112 204; baseline 0 -5; x_size 21; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_15' title='bbox 23 183 112 204; x_wconf 93'>Inventory</span>
<span class='ocr_line' id='line_1_30' title="bbox 1082 183 1178 202; baseline 0 -3; x_size 22; x_descenders 5.5; x_ascenders 5.5"><span class='ocrx_word' id='word_1_82' title='bbox 1082 183 1178 202; x_wconf 93'>1,277,838</span>
<span class='ocr_line' id='line_1_54' title="bbox 1301 183 1379 202; baseline 0 -3; x_size 22; x_descenders 5.5; x_ascenders 5.5"><span class='ocrx_word' id='word_1_107' title='bbox 1301 183 1379 202; x_wconf 95'>953,675</span>
第二个结果包含目标值。您可以比较 bbox
的垂直坐标以确保提取第一列。
命令 grep
在此示例中就足够了,但当然还有其他方法可以做类似的事情。另请注意,根据页面的倾斜程度,正则表达式可能应该替换为其他一些计算。
或者,您可以试用开源 Tabula,它将尝试从 pdf 中提取表格数据。
我正在尝试从余额中提取某些字段 sheet。例如,对于以下余额 sheet:
,我希望能够知道 'Inventory' 的值为 1,277,838目前,我正在使用 Tesseract 将图像转换为文本。但是,这种转换会产生文本流,因此很难将字段与其值相关联(因为这些值并不总是紧挨着相应字段的文本)。
经过一番搜索,我了解到 Tesseract 可以使用 uzn 文件读取图像的区域。但是,余额 sheet 值的特定区域可能会因表格而异,因此我对可以确定 'Inventory' 和 1,277,838 在同一行上的任何解决方案感兴趣。理想情况下,我想要文本的网格结构输出(这样我就可以在空间上分辨出哪些文本块在同一 rows/columns 中)。
谁能帮我解释一下我是怎么做到这个结果的?
我一直在使用 Tesseract 和 Python(pytesseract 库)执行类似的任务。我已经能够使用 Tesseract 的 .hocr 输出文件 (https://en.wikipedia.org/wiki/HOCR) 在页面上找到我的搜索词的位置 (例如 'Inventory'),然后在一小部分上重新 运行 Tesseract页面的位置,使其在该区域具有更高的准确性。这是我用来解析 Tesseract 的 HOCR 输出的代码:
def parse_hocr(search_terms=None, hocr_file=None, regex=None):
"""Parse the hocr file and find a reasonable bounding box for each of the strings
in search_terms. Return a dictionary with values as the bounding box to be used for
extracting the appropriate text.
inputs:
search_terms = Tuple, A tuple of search terms to look for in the HOCR file.
outputs:
box_dict = Dictionary, A dictionary whose keys are the elements of search_terms and values
are the bounding boxes where those terms are located in the document.
"""
# Make sure the search terms provided are a tuple.
if not isinstance(search_terms,tuple):
raise ValueError('The search_terms parameter must be a tuple')
# Make sure we got a HOCR file handle when called.
if not hocr_file:
raise ValueError('The parser must be provided with an HOCR file handle.')
# Open the hocr file, read it into BeautifulSoup and extract all the ocr words.
hocr = open(hocr_file,'r').read()
soup = bs.BeautifulSoup(hocr,'html.parser')
words = soup.find_all('span',class_='ocrx_word')
result = dict()
# Loop through all the words and look for our search terms.
for word in words:
w = word.get_text().lower()
for s in search_terms:
# If the word is in our search terms, find the bounding box
if len(w) > 1 and difflib.SequenceMatcher(None, s, w).ratio() > .5:
bbox = word['title'].split(';')
bbox = bbox[0].split(' ')
bbox = tuple([int(x) for x in bbox[1:]])
# Update the result dictionary or raise an error if the search term is in there twice.
if s not in result.keys():
result.update({s:bbox})
else:
pass
return result
这让我可以在 HOCR 文件中搜索适当的术语和 return 该特定单词的边界框。然后,我可以在页面的一个非常小的子集上将边界框稍微扩展为 运行 Tesseract。这比仅对整个页面进行 OCR 处理具有更高的准确性。显然,这些代码中有一些是我特有的,但它应该为您提供了一个起点。
This page 对于找到合适的论据以提供给 Tesseract 非常有帮助。我发现页面分割模式对于获得图像小部分的准确结果非常重要。
正如gaw89 已经提到的,Tesseract 可以输出比仅作为流的文本更多的信息。 hocr fileformat 还为您提供了每个段落、行、单词的位置(边界框):
$ tesseract 4LV05.png out -l eng hocr
然后你可以通过简单地
找到单词"Inventory"的边界框$ grep 'Inventory' out.hocr
<span class='ocr_line' id='line_1_5' title="bbox 23 183 112 204; baseline 0 -5; x_size 21; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_15' title='bbox 23 183 112 204; x_wconf 93'>Inventory</span>
因此,这个词的边界框从 183 垂直跨越到 204,对于这个标签的相应值,我们现在必须在同一垂直方向上搜索框 space。例如,这可以通过
实现$ grep 'bbox [0-9]* 18[0-9]' out.hocr
<p class='ocr_par' id='par_1_4' lang='eng' title="bbox 23 183 112 204">
<span class='ocr_line' id='line_1_5' title="bbox 23 183 112 204; baseline 0 -5; x_size 21; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_15' title='bbox 23 183 112 204; x_wconf 93'>Inventory</span>
<span class='ocr_line' id='line_1_30' title="bbox 1082 183 1178 202; baseline 0 -3; x_size 22; x_descenders 5.5; x_ascenders 5.5"><span class='ocrx_word' id='word_1_82' title='bbox 1082 183 1178 202; x_wconf 93'>1,277,838</span>
<span class='ocr_line' id='line_1_54' title="bbox 1301 183 1379 202; baseline 0 -3; x_size 22; x_descenders 5.5; x_ascenders 5.5"><span class='ocrx_word' id='word_1_107' title='bbox 1301 183 1379 202; x_wconf 95'>953,675</span>
第二个结果包含目标值。您可以比较 bbox
的垂直坐标以确保提取第一列。
命令 grep
在此示例中就足够了,但当然还有其他方法可以做类似的事情。另请注意,根据页面的倾斜程度,正则表达式可能应该替换为其他一些计算。
或者,您可以试用开源 Tabula,它将尝试从 pdf 中提取表格数据。