介绍 早在2009年,我就写过一篇关于如何索引只支持图像的PDF文件的文章。当时的任务只是从iFilter中仅包含图像的PDF文件中提取文本,以便在WIndows环境中对这些文件进行索引。这次任务有些不同——向PDF文件中添加文本信息。这种方法的好处是,文件可以通过标准的Adobe/Microsoft iFilters进行索引,但文本也可以通过可视化工具(Adobe Reader、Chome、Edge等)进行选择。 背景 我需要添加OCR信息到数千个PDF文件(存储在SQL服务器中)。我想创建一个脚本/实用程序,可以执行每天索引任何新的PDF文件,不包含可搜索文本。搜索了一段时间后,我找到了一个食谱: 使用ghostscript提取个别页面从PDF到图像(JPG)文件使用Tesseract提取OCR从图像存储提取的文本回PDF 用1 显然,自从我在2009年最后一次使用Tesseract以来,他们增加了一个新功能:图像和OCR文本将被导出为PDF文件。我认为你需要Tesseract版本4+。所以解决方案看起来很简单,接下来的批处理文件出现在20分钟内(见附件项目中的ocrate .bat): 隐藏,收缩,复制Code
set gs="C:Program Filesgsgs9.52ingswin64c.exe" set tesseract="Program FilesTesseract-OCR esseract.exe" if '%1'=='' goto :badParams if '%2'=='' goto :badParams mkdir %temp%ocr set nm=%~n1 SETLOCAL ENABLEDELAYEDEXPANSION rem split pdf into multiple jpeg %gs% -dSAFER -dBATCH -dNOPAUSE -sDEVICE=jpeg -r300 -dTextAlphaBits=4 -o "%temp%ocrocr_%nm%_%%04d.jpg" -f "%1" rem ocr each jpeg for %%i in (%temp%ocrocr_%nm%_*.jpg) do %tesseract% -l eng "%%i" %%~pni pdf del %temp%ocrocr_%nm%_*.jpg rem combine pdfs set ff=# for %%i in (%temp%ocrocr_%nm%_*.pdf) do set ff=!ff! %%i set ff=%ff:#=% %gs% -dNOPAUSE -dQUIET -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -o "%2" %ff% del %temp%ocrocr_%nm%_*.pdf goto :eof :badParams echo usage %0 pdf-In pdf-Out
如您所见,该脚本执行如下操作 使用GhostScript将单个页面提取到%temp%ocr####. JPG文件中,为每个JPG文件运行Tesseract创建一个%temp%ocr####. PDF文件使用ghost script将所有PDF文件合并到输出文件中。 1的问题 很快,解决方案1的问题出现在大型PDF文件(10+页)上。 非常慢。但我想,既然它是作为后台进程运行,只对新文件,也许我可以接受这个。输出文件要比源文件大很多很多很多倍。成千上万的文件-成为了节目的终结者。 采取2 - HOCR2PDF 其他人也有同样的问题。进入HOCR2PDF (https://archive.codeplex.com/?p=hocrtopdf)。显然,Tesseract除了输出文本或PDF格式的OCR外,还可以输出HOCR文件——有效编码的HTML文件。所以任务稍微改变了一下 使用GhostScript将PDF文件拆分为多个JPGs使用tesseract将JPGs转换为HOCR文件解析HOCR文件使用PDF库(iTextShart)添加文本信息到输出的PDF Take 2 -问题 嗯,HOCR2PDF和我原来的脚本有类似的问题。它仍然很慢,文件仍然很大,尽管只有解决方案1的一半大小。 选3 -期末考试 所以我继续创建了我自己的项目。 在进行了一些故障排除和性能改进(比如启用压缩、为整个页面使用单一字体)之后,我发现大小膨胀归结为一次iTextShart函数调用 隐藏,复制Code
stamp.GetImportedPage(stamp.Reader, pg)
单是这通电话,每页就增加了3万美元。唯一需要它的原因是为了获得页面高度。将此调用替换为 隐藏,复制Code
stamp.Reader.GetPageSizeWithRotation(pg).Height
尺寸膨胀消失了,令我惊讶的是,输出文件实际上比源文件更小(可能是由于启用了压缩和删除未使用的对象)。 为了解决性能问题,我决定使用ThreadPool对每个页面并发运行Tesseract。对于较大(10+页)的文件,性能的提升是非常显著的。 , 使用的代码 该项目包含一个带有公共方法OcrFile的PdfOcr类。用法如下: 隐藏,复制Code
string txt = new PdfOcr().OcrFile(fileIn, fileOut);
这段代码将对fileIn pdf文件进行OCR,创建fileOut并返回OCR文本。该类可能需要通过改变/分配以下静态变量来定制: ,,,,GhostScript - GhostScript可执行文件的位置,,,Tesseract可执行文件的位置。,,,,将生成临时文件的文件夹。,,,tmpPrfx -所有临时文件的前缀 类和主程序一起存储在program .cs文件中,主程序有两个参数——源文件名和目标文件名。,,,,,,,,,,, ,,,,,,,,, 的兴趣点 https://github.com/UB-Mannheim/tesseract/wiki https://www.ghostscript.com/download/gsdnld.html - GhostScript二进制文件下载。https://archive.codeplex.com/?p=hocrtopdf - HOCR2PDF .NET实用程序 历史 最初版本 本文转载于:http://www.diyabc.com/frontweb/news1636.html