2011-05-17 48 views
14

這已經被問過,但我真的不知道答案是否對我有幫助。這是我的問題:我有一堆(10,000左右)的pdf文件。有些是使用Adobe的打印功能保存的文本文件(所以文本是完美的,我不想冒險搞砸它們)。還有一些是掃描圖像(所以他們沒有任何文字,我必須解決OCR)。這些文件在同一個目錄下,我不知道哪個是哪個。最終我想把它們變成.txt文件,然後對它們進行字符串處理。所以我想要最精確的OCR。針對PDF的批量OCR計劃

好像人建議:

  1. 的Adobe PDF(我沒有這個許可副本等等......再加上如果ABBYY finereader什麼是更好的,何必爲它付出,如果我贏了(不使用它)
  2. ocropus(我不知道如何使用這個東西),
  3. Tesseract(這似乎在1995年是偉大的,但我不知道是否有更準確的東西加上它doesn我本來不用做pdf,我必須轉換爲TIFF,這會引發它自己的問題,因爲我沒有授權的acrobat副本,所以我不知道如何將10,000個文件轉換爲tiff。plu我不希望10,000 30頁文件變成30,000個單獨的tiff圖像)。
  4. wowocr
  5. pdftextstream(這是自2009年)
  6. ABBYY FineReader(顯然是其$$$,但我會花$ 600完成這件事,如果這件事是顯著較好,即有更精確的OCR)。

此外,我是編程的n00b,所以如果要花幾周時間來學習如何做某件事情,我寧可支付$$$。 Thx用於輸入/體驗。

順便說一句,我正在運行Linux Mint 11 64位和/或Windows 7 64位。

這裏有其他線程:

Batch OCRing PDFs that haven't already been OCR'd

Open source OCR

PDF Text Extraction Approach Using OCR

​​

回答

6

只是把你的一些誤解,直...

「我沒有acrobat的授權副本,所以我不知道如何將10,000個文件轉換爲tiff。」

你可以在免費(如在自由)和免費(如啤酒)Ghostscript的幫助下將PDF轉換爲TIFF。如果你想這樣做對Linux Mint的或在Windows 7中的Linux命令行您的選擇是:

gs \ 
-o input.tif \ 
-sDEVICE=tiffg4 \ 
    input.pdf 

「我不想萬個30頁文檔變成了30000個個人TIFF圖像」

您可以輕鬆擁有「多頁」TIFF。以上命令確實創建了這種TIFFs的G4(傳真tiff)味道。如果你甚至想單頁TIFF,而不是,您可以修改命令:

gs \ 
-o input_page_%03d.tif \ 
-sDEVICE=tiffg4 \ 
    input.pdf 

輸出文件名的%03d部分將自動轉化爲一系列001002003

注意事項:

  1. tiffg4輸出設備的默認分辨率爲204x196 dpi。你可能想要更好的價值。要獲得720dpi,您應該在命令行中添加-r720x720
  2. 此外,如果您的Ghostscript安裝使用字母作爲其默認介質尺寸,則可能需要對其進行更改。您可以使用-gXxY在設備點中設置widthxheight。因此,要獲取橫向輸出頁面尺寸,您可以添加-g8420x5950參數。

所以控制這兩個參數,以在縱向上A4 720dpi的輸出完整的命令,會讀:

gs \ 
-o input.tif \ 
-sDEVICE=tiffg4 \ 
-r720x720 \ 
-g5950x8420 \ 
    input.pdf 
4

這是一個有趣的問題。如果您願意在.NET中使用Windows,那麼可以使用dotImage(免責聲明,我爲Atalasoft工作並編寫大部分OCR引擎代碼)執行此操作。讓我們來分析這個問題分解成塊 - 首先是遍歷所有的PDF文件:

​​

此獲取結束.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頁面轉換爲圖像,並把它變成一個形式,是可口的engine.Translate。這並不是嚴格按照這種方式完成的 - 人們可以通過調用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

最簡單的方法是使用ABBYY FineReader,Omnipage等單一工具在一批中處理圖像,而無需將其分爲掃描圖像和非掃描圖像。無論如何,我相信FineReader會在執行OCR之前將PDF轉換爲圖像。

使用OCR引擎將爲您提供諸如自動糾偏,頁面方向檢測,圖像閾值處理,去斑等功能。這些功能您必須爲自己購買圖像處理庫並進行編程,這可能很難找到爲您的10,000 PDF的一組最佳參數。

使用自動OCR方法會根據輸入圖像產生其他副作用,如果您對圖像進行排序併爲每種類型的圖像設置最佳參數,您會發現更好的結果。爲了提高準確性,使用合適的PDF文本提取例程來提取具有完美文本的PDF文件會更好。

在一天結束時,它會降低時間和金錢與您需要的結果的質量。在一天結束時,商業OCR計劃將是最快最簡單的解決方案。如果你只有純文本的文檔,那麼便宜的OCR程序就可以工作,同時也是一個昂貴的解決方案。您的文檔越複雜,您將需要花費更多的錢來處理它們。

我會嘗試尋找一些商業OCR引擎的演示/試用版本,並只看到他們在花費太多時間和金錢之前如何執行您的不同文檔類型。

5

想通過回答我自己的問題(已經爲自己寫了一些很好的代碼,並且在沒有此板的幫助下完成它)來嘗試做出貢獻。如果你用unix(好吧,osx爲我)下載pdf文件,那麼帶有文本的pdf文件將在它們中包含單詞「字體」(作爲一個字符串,但與其他文本混合)b/c就是這樣文件告訴Adobe需要顯示哪些字體。

bash中的cat命令似乎與在python中以二進制模式讀取文件的輸出相同(當打開文件而不是'w'或'r'或'a'時使用'rb'模式)。所以我假設所有包含文本的pdf文件在二進制輸出中都有「字體」一詞,並且沒有圖像文件。如果情況總是如此,那麼這段代碼將在單個目錄中列出所有包含文本和單獨列表的僅包含圖像的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。

0

我寫了Abbyy OCR4LINUX CLI引擎(恕我直言,不花那麼多)和Tesseract 3的小包裝。

的包裝可以批量轉換文件,如:
$ pmocr.sh --batch --target=pdf --skip-txt-pdf /some/directory

腳本使用pdffonts確定一個PDF文件已經進行光學字符識別跳過他們。此外,該腳本可以作爲系統服務工作來監視目錄,並在文件進入目錄後立即啓動OCR操作。

腳本可以在這裏找到:
https://github.com/deajan/pmOCR

希望這可以幫助別人。