1. 程式人生 > >基於Tesseract實現圖片文字識別

基於Tesseract實現圖片文字識別

一.簡介

   Tesseract是一個開源的文字識別【OCR】引擎,可通過Apache 2.0許可獲得。它可以直接使用,或者使用API從影象中提取列印的文字,支援多種語言。該軟體包包含一個ORC引擎【libtesseract】和一個命令列程式【tesseract】。Tesseract4添加了一個新的基於LSTM的OCR引擎,該引擎專注於行識別,但仍支援Tesseract 3的傳統Tesseract OCR引擎,該引擎通過識別字符模式進行工作。通過使用傳統OCR引擎模式【--oem 0】,可以與Tesseract 3相容。它還需要訓練好的資料檔案對舊引擎進行支援,例如tessdata目錄下的資料檔案。

  特點:

    1.具有Unicode【UTF-8】支援,並且可以“開箱即用”地識別100多種語言。

    2.支援各種輸出格式,純文字,hOCR【HTML】,PDF,僅不可見文字的PDF,TSV。Master分支還對ALTO【XML】輸出提供實驗性支援。

    3.在許多情況下,要想獲得更好的OCR結果,需要提高提供給Tesseract的影象的質量。

二.在python環境中安裝pytesseract

  

  安裝成功!

三.在Windows系統下安裝Tesseract

  

  配置環境變數:

  

  備註:最新的為4.1.0,建議安裝4.x版本,根據一可知,版本4有重大升級,系統性能顯著提升,特別是在對中文的識別上更是明顯!

四.python程式碼實現 

 1 # -*- coding: utf-8 -*-
 2 """
 3 Spyder Editor
 4 
 5 This is a temporary script file.
 6 """
 7 
 8 import  pytesseract
 9 from PIL import Image
10 
11 #開啟驗證碼圖片
12 image = Image.open('E:\\testData\\tess\\1.png')
13 #載入一下圖片防止報錯,此處可以省略
14 #image.load()
15 #呼叫show來展示圖片,除錯用此處可以省略
16 #image.show()
17 text = pytesseract.image_to_string(image,lang='chi_sim')
18 print(text)

五.Python環境執行結果【無資料清洗】 

20
a
志
口
吳
吊
5
達
吊
園

康 阮 隨 阮 隨 隨 阮 隆 隨 阮 阮 龐
應 阮 院 阮 阮 際 阮 阮 院 院 阮 龐

宇
B
B
B
B
B
B
B
B
B
B
E

 

胡
胡
胡
胡
胡
胡
胡
胡
胡
胡
脫 醫

劇 澈 剖 剖 亨 亨 定 亨 宣 河

  

宇
B
B
B
B
E
E
E
E
E
E
振

產 蓮

主
主
主
主
主
主
主
主
主
主
生 交

E
E
E
E
E
E
E
E
E
E
E35653

職
職
職
職
職
職
職
職
職
職
E

E
E
E
E
E
E
E
E
E
E
093
View Code

  部分示例:
  

  可知對中文的識別一塌糊塗,因此建議還是使用版本4進行識別!

  

六.使用Java程式呼叫ImageIO進行資料預處理 

  1 package zhen;
  2 import java.awt.Color;
  3 import java.awt.image.BufferedImage;
  4 import java.io.File;
  5 import java.io.FileInputStream;
  6 import java.io.IOException;
  7 
  8 import javax.imageio.ImageIO;
  9  
 10  
 11 public class LineMark{
 12     public static void clean(String fromPath,String toPath) throws IOException{
 13         File file1 = new File(fromPath);
 14         BufferedImage image = ImageIO.read(file1);
 15         
 16         BufferedImage sourceImg =ImageIO.read(new FileInputStream(file1));  // 獲取圖片的長寬
 17         int width = sourceImg.getWidth();
 18         int height = sourceImg.getHeight();
 19         
 20         /**
 21          * 建立3維陣列用於儲存圖片rgb資料
 22          */
 23         int[][][] array = new int[width][height][3];
 24         for(int i=0;i<width;i++){ // 獲取圖片中所有畫素點的rgb
 25             for(int j=0;j<height;j++){
 26                 int pixel = image.getRGB(i, j); //獲得座標(i,j)的畫素
 27                 int red = (pixel & 0xff0000) >> 16; 
 28                 int green = (pixel & 0xff00) >> 8;
 29                 int blue = (pixel & 0xff);  //通過座標(i,j)的畫素值獲得r,g,b的值   
 30                 array[i][j][0] = red;
 31                 array[i][j][1] = green;
 32                 array[i][j][2] = blue;
 33             }
 34         }
 35         
 36         /**
 37          * 清除表格線:
 38          * 豎線:絕大多數點的x值都為255
 39          */
 40         for(int i=0;i<width;i++){
 41             int nums = 0;
 42             for(int j=0;j<height;j++){
 43                 if(array[i][j][0]<128 && array[i][j][1]<128 && array[i][j][2]<128){
 44                     nums += 1;
 45                 }
 46             }
 47             if(nums > height * 0.8){
 48                 for(int n=0;n<height;n++){
 49                     array[i][n][0] = 255;
 50                     array[i][n][1] = 255;
 51                     array[i][n][2] = 255;
 52                 }
 53             }
 54         }
 55         /**
 56          * 清除表格線:
 57          *     橫線:絕大多數點的y值都為255
 58          */
 59         for(int j=0;j<height;j++){
 60             int nums = 0;
 61             for(int i=0;i<width;i++){
 62                 if(array[i][j][0]<128 && array[i][j][1]<128 && array[i][j][2]<128){
 63                     nums += 1;
 64                 }
 65             }
 66             if(nums > height * 0.8){
 67                 for(int n=0;n<width;n++){
 68                     array[n][j][0] = 255;
 69                     array[n][j][1] = 255;
 70                     array[n][j][2] = 255;
 71                 }
 72             }
 73         }
 74         /**
 75          * 大點
 76          */
 77         for(int i=0;i<width;i++){
 78             for(int j=0;j<height;j++){
 79                 int cover = new Color(array[i][j][0],array[i][j][1],array[i][j][2]).getRGB();
 80                 image.setRGB(i,j,cover);
 81             }
 82         }
 83         File file2 = new File(toPath);
 84         ImageIO.write(image, "png", file2);
 85     }
 86     
 87     /**
 88      * 測試
 89      * @param args
 90      */
 91     public static void main(String[] args){
 92         String fromPath = "E:\\testData\\tess\\111.png";
 93         String toPath = "E:\\testData\\tess\\112.png";
 94         try {
 95             LineMark.clean(fromPath,toPath);
 96         } catch (IOException e) {
 97             e.printStackTrace();
 98         }
 99     }
100 }

七.執行結果

  處理之前:

    

  處理之後:

    

  

八.使用Tesseract 4 API進行文字識別

 1 package zhen;
 2 import java.awt.Rectangle;
 3 import java.awt.image.BufferedImage;
 4 import java.io.File;
 5 import java.io.FileInputStream;
 6 import java.io.FileOutputStream;
 7 import java.io.IOException;
 8 import javax.imageio.ImageIO;
 9 import net.sourceforge.tess4j.*;
10 import org.apache.poi.xssf.usermodel.*;
11  
12 public class RP {
13     private String a0="";
14 
15         public void toExcel(int i,XSSFWorkbook wb,XSSFSheet sheet,int len)  //將文字資訊做成表格
16         {            
17             for(int j=0;j<len;j++){
18                 String[] array = this.a0.split("\n"); // 分行
19                 for(int k=0;k<array.length;k++){
20                     XSSFRow row = sheet.createRow(k);  // 建立一行
21                     String[] array2 = array[k].split(" ");
22                     for(int m=0;m<array2.length;m++){
23                         row.createCell(m).setCellValue(array2[m]);      
24                     }
25                 }                  
26             }
27         }
28     public static void main(String[] args) throws IOException {
29         RP rp = new RP();
30         int num = 1;
31         
32         File root = new File("E:\\testData\\tess2");//存放處理後的圖片,imgs資料夾
33         File res = new File("E:\\testData\\tess");//源圖片位置,res資料夾下
34         
35         ITesseract instance = new Tesseract();
36         instance.setLanguage("chi_sim");              //使用訓練好中文字型檔識別
37         
38         XSSFWorkbook wb = new XSSFWorkbook();
39         XSSFSheet sheet = wb.createSheet("資訊彙總");        
40         try {
41             File[] ress = res.listFiles();
42             int i=0;
43             for(File file : ress){
44                 i++;
45                 LineMark.clean(file.getAbsolutePath(),"E:\\testData\\tess2\\"+i+".png");
46             }        //去除源圖片表格線,處理後的圖片放到img資料夾
47                         
48             File[] files = root.listFiles();
49             for (File file : files) { //對去除水印後的圖片逐個處理
50                 BufferedImage sourceImg =ImageIO.read(new FileInputStream(file));  // 獲取圖片的長寬
51                 int width = sourceImg.getWidth();
52                 int height = sourceImg.getHeight();
53                 Rectangle ret = new Rectangle(0,0,width,height); //識別全部資料
54                 
55                 String result = instance.doOCR(file, ret);  //開始採用doOCR(file)效率很低,因為圖片內容太多
56                 int len = 0;
57                 if(result != null){
58                     len = result.split(" ").length;
59                     rp.a0 = result;
60                 }
61                 System.out.print(result);
62                 rp.toExcel(num,wb,sheet,len);      //呼叫toExcel函式,將提取到的資訊寫入
63                 num++;
64             }
65         } catch (TesseractException e) {
66             System.err.println(e.getMessage());
67         }
68 
69          try {  
70                 FileOutputStream fout = new FileOutputStream("D:\\software\\company.xlsx");  
71                 wb.write(fout);  
72                 fout.close();  
73             } catch (IOException e) {  
74                 e.printStackTrace();  
75             }                 //把寫好資訊的表輸出
76     }
77     
78 }

九.不資料清洗執行結果

  

十.資料清洗執行結果

  

  經過對比可以明顯看出,表格線對識別的影響很大【其它形式的干擾也同樣如此,例如:驗證碼上的干擾線、圖案等】,因此,資料清洗必不可少!

  

十一.分析

  從上面的執行結果可知,在使用Tesseract 4時,在資料儘可能的清晰的情況下,大部分漢字還是能識別出來的,只是在【數字0】和【標點符號。】,【英語g】和【數字9】等外形相識的地方識別不清楚!當然,模型還有提升的空間,下一步將提升對存在格式傾斜或拍照的圖片進行識別的能