以前曾经问过,但我真的不知道这些答案是否对我有帮助。这是我的问题:我得到了一堆(10,000左右)pdf文件。有些是使用adobe的打印功能保存的文本文件(所以他们的文本是完美的,我不想冒险搞砸它们)。有些是扫描图像(所以他们没有任何文字,我将不得不接受OCR)。文件在同一目录中,我无法分辨哪个是哪个。最终我想将它们转换为.txt文件,然后对它们进行字符串处理。所以我希望最准确的OCR成为可能。
似乎有人建议:
另外,我是编程的n00b,所以如果要花几周时间学习如何做某事,我宁愿支付$$$。感谢输入/体验。
顺便说一句,我正在运行Linux Mint 11 64位和/或Windows 7 64位。
以下是其他主题:
Batch OCRing PDFs that haven't already been OCR'd
PDF Text Extraction Approach Using OCR
https://superuser.com/questions/107678/batch-ocr-for-many-pdf-files-not-already-ocred
答案 0 :(得分:6)
只是把你的一些误解直接......
“我没有acrobat的许可副本,因此我不知道如何将10,000个文件转换为tiff。”
你可以在免费(如自由)和免费(如啤酒)Ghostscript的帮助下将PDF转换为TIFF。您可以选择在Linux Mint或Windows 7上执行此操作.Linux的命令行是:
gs \
-o input.tif \
-sDEVICE=tiffg4 \
input.pdf
“我不希望10,000个30页的文档变成30,000个单独的tiff图像”
您可以轻松拥有“多页”TIFF。上面的命令确实创建了 G4 (传真tiff)风格的这种TIFF。如果你甚至想要单页TIFF,你可以修改命令:
gs \
-o input_page_%03d.tif \
-sDEVICE=tiffg4 \
input.pdf
输出文件名的%03d
部分会自动转换为一系列001
,002
,003
等。
警告:
tiffg4
输出设备的默认分辨率为204x196 dpi。你可能想要更好的价值。要获得720 dpi,您应该在命令行中添加-r720x720
。 -gXxY
在设备点中设置widthxheight。因此,要在横向中获取 ISO A4 输出页面尺寸,您可以添加-g8420x5950
参数。因此,控制这两个参数的完整命令,以纵向方式在A4上产生720 dpi输出,将显示为:
gs \
-o input.tif \
-sDEVICE=tiffg4 \
-r720x720 \
-g5950x8420 \
input.pdf
答案 1 :(得分:5)
想通过回答我自己的问题,我会尝试做出贡献(为自己编写了一些很好的代码,如果没有这个板的帮助就无法完成它)。如果你在unix中使用pdf文件(好吧,对我来说是osx),那么有文本的pdf文件中会包含单词“Font”(作为字符串,但与其他文本混合在一起)b / c这是怎么回事文件告诉Adobe要显示的字体。
bash中的cat命令似乎与在python中以二进制模式读取文件的输出相同(在打开文件而不是'w'或'r'或'a'时使用'rb'模式)。所以我假设所有包含文本的pdf文件在二进制输出中都有“Font”字样,并且不会出现只有图像的文件。如果总是如此,则此代码将列出单个目录中包含文本的所有pdf文件以及仅包含图像的单独列表。它将每个列表保存到单独的.txt文件中,然后您可以使用bash中的命令将pdf文件移动到相应的文件夹中。
一旦将它们放在自己的文件夹中,就可以在images_only文件夹中的pdf文件上运行批处理ocr解决方案。我还没有那么远(显然)。
import os, re
#path is the directory with the files, other 2 are the names of the files you will store your lists in
path = 'C:/folder_with_pdfs'
files_with_text = open('files_with_text.txt', 'a')
image_only_files = open('image_only_files.txt', 'a')
#have os make a list of all files in that dir for a loop
filelist = os.listdir(path)
#compile regular expression that matches "Font"
mysearch = re.compile(r'.*Font.*', re.DOTALL)
#loop over all files in the directory, open them in binary ('rb'), search that binary for "Font"
#if they have "Font" they have text, if not they don't
#(pdf does something to understand the Font type and uses this word every time the pdf contains text)
for pdf in filelist:
openable_file = os.path.join(path, pdf)
cat_file = open(openable_file, 'rb')
usable_cat_file = cat_file.read()
#print usable_cat_file
if mysearch.match(usable_cat_file):
files_with_text.write(pdf + '\n')
else:
image_only_files.write(pdf + '\n')
要移动文件,我在bash shell中输入了这个命令:
cat files_with_text.txt | while read i; do mv $i Volumes/hard_drive_name/new_destination_directory_name; done
另外,我没有重新运行上面的python代码,我只是手工编辑了这个东西,所以它可能是错误的,Idk。
答案 2 :(得分:4)
这是一个有趣的问题。如果您愿意在.NET上使用Windows,可以使用dotImage(免责声明,我为Atalasoft工作并编写大部分OCR引擎代码)。让我们把问题分解成碎片 - 第一个是迭代你的所有PDF:
string[] candidatePDFs = Directory.GetFiles(sourceDirectory, "*.pdf");
PdfDecoder decoder = new PdfDecoder();
foreach (string path in candidatePDFs) {
using (FileStream stm = new FileStream(path, FileMode.Open)) {
if (decoder.IsValidFormat(stm)) {
ProcessPdf(path, stm);
}
}
}
这将获得以.pdf结尾的所有文件的列表,如果文件是有效的pdf,则调用例程来处理它:
public void ProcessPdf(string path, Stream stm)
{
using (Document doc = new Document(stm)) {
int i=0;
foreach (Page p in doc.Pages) {
if (p.SingleImageOnly) {
ProcessWithOcr(path, stm, i);
}
else {
ProcessWithTextExtract(path, stm, i);
}
i++;
}
}
}
这会将文件作为Document对象打开,并询问每个页面是否仅为图像。如果是这样,它将OCR页面,否则它将文本提取:
public void ProcessWithOcr(string path, Stream pdfStm, int page)
{
using (Stream textStream = GetTextStream(path, page)) {
PdfDecoder decoder = new PdfDecoder();
using (AtalaImage image = decoder.Read(pdfStm, page)) {
ImageCollection coll = new ImageCollection();
coll.Add(image);
ImageCollectionImageSource source = new ImageCollectionImageSource(coll);
OcrEngine engine = GetOcrEngine();
engine.Initialize();
engine.Translate(source, "text/plain", textStream);
engine.Shutdown();
}
}
}
这样做是将PDF页面光栅化为图像,并将其放入一个适合引擎的形式。翻译。这并不一定要以这种方式完成 - 可以通过调用Recognize从AtalaImage获取引擎中的OcrPage对象,但是然后由客户端代码循环结构并写出文本。
你会注意到我遗漏了GetOcrEngine() - 我们提供4个OCR引擎供客户使用:Tesseract,GlyphReader,RecoStar和Iris。您可以选择最适合您需求的那个。
最后,您需要使用代码从已经包含完美文本的页面中提取文本:
public void ProcessWithTextExtract(string path, Stream pdfStream, int page)
{
using (Stream textStream = GetTextStream(path, page)) {
StreamWriter writer = new StreamWriter(textStream);
using (PdfTextDocument doc = new PdfTextDocument(pdfStream)) {
PdfTextPage page = doc.GetPage(i);
writer.Write(page.GetText(0, page.CharCount));
}
}
}
这将从给定页面中提取文本并将其写入输出流。
最后,您需要GetTextStream():
public Stream GetTextStream(string sourcePath, int pageNo)
{
string dir = Path.GetDirectoryName(sourcePath);
string fname = Path.GetFileNameWithoutExtension(sourcePath);
string finalPath = Path.Combine(dir, String.Format("{0}p{1}.txt", fname, pageNo));
return new FileStream(finalPath, FileMode.Create);
}
这是100%的解决方案吗?不,当然不是。您可以想象PDF页面包含一个单独的图像,并在其周围绘制一个框 - 这显然会使图像无法测试,但不会返回任何有用的文本。可能更好的方法是只使用提取的文本,如果没有返回任何内容,那么尝试使用OCR引擎。从一种方法转向另一种方法是写一个不同的谓词。
答案 3 :(得分:3)
最简单的方法是使用单一工具,如ABBYY FineReader,Omnipage等,一批处理图像,而不必将它们分类为扫描图像而非扫描图像。我相信FineReader无论如何都会在执行OCR之前将PDF转换为图像。
使用OCR引擎将为您提供诸如自动校正,页面方向检测,图像阈值处理,去斑点等功能。这些功能您必须购买图像处理库并自行编程,这可能很难找到10,000 PDF的最佳参数集。
使用自动OCR方法会产生其他副作用,具体取决于输入图像,如果您对图像进行排序并为每种类型的图像设置最佳参数,您会发现效果会更好。为了准确起见,使用适当的PDF文本提取例程来提取具有完美文本的PDF会更好。
在一天结束时,它将归结为时间和金钱与您所需结果的质量。在一天结束时,商业OCR计划将是最快捷,最简单的解决方案。如果你只有干净的文本文件,那么廉价的OCR程序将起作用,而且价格昂贵。您的文档越复杂,处理它们所需的资金就越多。
我会尝试找一些商业OCR引擎的演示/试用版本,看看它们在花费太多时间和金钱之前如何在不同的文档类型上执行。
答案 4 :(得分:0)
我为Abbyy OCR4LINUX CLI引擎编写了一个小包装器(恕我直言,费用不高)和Tesseract 3。
包装器可以批量转换文件,如:
$ pmocr.sh --batch --target=pdf --skip-txt-pdf /some/directory
该脚本使用pdffonts
来确定PDF文件是否已被OCR以跳过它们。此外,该脚本可以作为系统服务来监视目录,并在文件进入目录后立即启动OCR操作。
脚本可以在这里找到:
https://github.com/deajan/pmOCR
希望这有助于某人。