一、總體概述
本文主要介紹了由本人開發的、基於百度AI的雲貓OCR軟件的主要功能,性能評價及核心代碼解讀。因為是幾個帖子合並成一個,所以篇幅較長,希望各位能耐心看完,當然也可以各取所需。
本文主要分為以下幾個部分:
第一部分是雲貓OCR軟件介紹。 由開發者本人親自介紹軟件的主要功能。對標ABBYY等OCR軟件,雲貓OCR的功能更全面,使用更簡單,關鍵的是雲貓OCR目前是完全免費給大家用的。當然因為是試用版,可能存在一些bug,大家使用的時候不要亂按就行。雲貓展示版本的下載地址見帖子: https://ai.baidu.com/forum/topic/show/955975
第二部分是雲貓OCR基於百度OCR的具體實現方式說明。 同時也會對軟件的部分核心代碼進行展示,便於大家進行參考做出更有創意的產品。
第三部分是雲貓OCR使用說明及效果評測。 但因為雲貓OCR是2017年底左右開發的,所以用的不是百度OCR最新接口功能,如果雲貓能得到大家的支持,我可以考慮開發新版接入更多百度最新的AI接口,希望大家能多多捧場。
本文的最后部分是附錄,附上了我基於百度OCR進行開發的代碼解讀,使用的是最新的百度手寫體識別接口,也一並打包給大家參考。
第一部分 雲貓OCR的軟件介紹
一、雲貓OCR簡介
雲貓OCR是基於百度雲OCR算法,由進擊的狐狸進行開發的一款軟件。本軟件由C#語言進行開發,運行在Windows平台上。主要調用的接口是通用文字識別、通用文字識別(高精度)和表格識別等。
二、雲貓OCR目前實現的主要功能:
1.批量圖片文字識別,可以預覽圖片,可以對識別結果進行自動換行和縮進,可以控制QPS並發(QPS功能因為百度雲的timeout問題而暫時擱置);
2.批量表格圖片識別,支持自動打開識別結果,用戶也可以選擇直接打開保存目錄;
3.PDF轉圖片,在我的筆記本(配置為I7處理器/8G內存/128G SSD硬盤)的硬件環境下,PDF轉圖片程序模塊占用的內存不超過400M,同時可以在2分鍾左右的時間內轉換超過500頁內容的PDF文件。支持一鍵打開轉換結果文件夾。
4.雲貓軟件支持換膚功能,目前有兩套皮膚;
5.可以設置API Key和Secret Key;
6.支持中途停止識別;
7.支持把設置改變后對同一張圖片進行重新識別;
8.支持多種語言;
9.其他功能,比如識別統計信息、控制字體大小、右鍵把識別結果另存為rtf文件、全選和復制識別結果等等;
三、演示帖子鏈接
http://ai.baidu.com/forum/topic/show/492371
四、雲貓OCR演示視頻鏈接
https://v.qq.com/x/page/r0564n4a87e.html
建議大家用1.2x或者1.5x倍速觀看,因為本人的聲速有點慢。
第二部分 雲貓OCR基於百度OCR的具體實現方式說明
一、概述
雲貓OCR是基於百度AI,在Windows平台運行的一款軟件。我是用C#語言在Visual Studio2017集成開發環境中進行開發的,開發方式是SDK包開發。在開發中,我們需要參考百度的技術文檔。
百度雲文字識別技術文檔地址:
https://cloud.baidu.com/doc/OCR/index.html

二、准備工作
首先,我們需要下載最新的百度文字識別的SDK包。
C# SDK包的下載地址如下:

下載完畢后解壓縮,最新的包在文件夾net45里面。

打開Visual Studio2017開發環境,選擇新建項目,因為我打算用控制台項目講解,因此要選擇新建項目——C#控制台項目。建好項目之后,需要在項目中引用上面下載的SDK包。


三、核心代碼講解
(一)調用百度OCR函數識別圖片文字,返回的格式為Json
代碼如下:
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
namespace myOCRDemo
{
class Program
{
public static void GeneralBasicDemo()
{
// 設置APPID/AK/SK
var API_KEY = "你的 Api Key";
var SECRET_KEY = "你的 Secret Key";
//創建對象
var client = new Baidu.Aip.Ocr.Ocr(API_KEY, SECRET_KEY);
client.Timeout = 60000; // 修改超時時間
var image = File.ReadAllBytes("圖片文件路徑");
// 調用通用文字識別, 圖片參數為本地圖片,可能會拋出網絡等異常,請使用try/catch捕獲
var result = client.GeneralBasic(image);
Console.WriteLine(result);
}
static void Main(string[] args)
{
GeneralBasicDemo();
Console.Read();
}
}
}
注意,具體開發的時候要把上面的API Key和Secret Key分別改為你自己的,至於怎么申請和查看這兩個Key,可以參考我寫的評測篇帖子。帖子鏈接如下:
http://ai.baidu.com/forum/topic/show/955989
另外不要忘了把圖片文件路徑改為你自己的圖片路徑。下面是識別的結果示例:

原圖如下:

(二)解析Json格式,把識別結果轉變為更為直觀的文本類型
代碼如下:
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
namespace myOCRDemo
{
class Program
{
public static void GeneralBasicDemo()
{
// 設置APPID/AK/SK
var API_KEY = "你的Akey";
var SECRET_KEY = "你的SKey";
//創建對象
var client = new Baidu.Aip.Ocr.Ocr(API_KEY, SECRET_KEY);
client.Timeout = 60000; // 修改超時時間
var image = File.ReadAllBytes(@"你的圖片路徑");
// 調用通用文字識別, 圖片參數為本地圖片,可能會拋出網絡等異常,請使用try/catch捕獲
var result = client.GeneralBasic(image);
//解析Json的代碼
JObject jo = (JObject)JsonConvert.DeserializeObject(result.ToString());
int num = (int)jo["words_result_num"];
string[] words = new string[num];
for (int i = 0; i < num; i++)
words[i] = jo["words_result"][i]["words"].ToString();
//返回值
string txtOCR = null;
for (int i = 0; i < num; i++)
txtOCR += words[i] + "\n";
//顯示結果
Console.WriteLine(txtOCR);
}
static void Main(string[] args)
{
GeneralBasicDemo();
Console.Read();
}
}
}
程序運行結果如下:

這樣就比較符合人類的閱讀習慣了,上面這段代碼也是核心的基礎代碼,可以通過這些核心的代碼去做一些優化,比如自動換行、自動縮進、根據語言習慣自動改變標點符號等等。
(三)表格識別
百度的表格文字識別的編程較為麻煩,主要分成兩步:第一步是提交表格文字識別請求,獲得requestId;第二步是根據requestId獲取表格文字識別的結果,默認是Excel文件格式,Json結果會返回一段下載地址。
我的程序除了上面這兩步以外,還添加了自動下載Excel文件到本地電腦的代碼,供各位參考。另外要注意的是,提交識別請求和獲得識別結果這兩步之間,程序必須設置延時,否則不能獲得下載的URL 。經過實際測試,延時為3秒以上較為合適,3秒以下可能會出錯。
代碼如下:
///
/// 表格文字識別
///
public static void myTableRecognitionRequestDemo()
{
// 設置APPID/AK/SK
var API_KEY = "你的API Key";
var SECRET_KEY = "你的Secret Key";
//創建對象
var client = new Baidu.Aip.Ocr.Ocr(API_KEY, SECRET_KEY);
client.Timeout = 60000; // 修改超時時間
var image = File.ReadAllBytes(@"F:\表格圖片1.jpg");//這里要改成你的表格圖片路徑
// 調用表格文字識別,可能會拋出網絡等異常,請使用try/catch捕獲
var result = client.TableRecognitionRequest(image);
//解析Json
JObject jo = (JObject)JsonConvert.DeserializeObject(result.ToString());
string requestId = jo["result"][0]["request_id"].ToString();
Console.WriteLine("獲得requestId:"+requestId);
//延時3秒,這句是必須的
System.Threading.Thread.Sleep(3000);
//獲取表格識別結果
//有時會得不到鏈接,需要多嘗試幾次
var resultExcel = client.TableRecognitionGetResult(requestId);
Console.WriteLine("獲得的表格識別結果如下:");
Console.WriteLine(resultExcel);
//解析Json,獲得鏈接
JObject joResult = (JObject)JsonConvert.DeserializeObject(resultExcel.ToString());
string excelURL = joResult["result"]["result_data"].ToString();
Console.WriteLine("獲得的Excel文件下載地址是:\n" + excelURL);
//自動下載Excel文件到電腦
WebClient df = new WebClient();
df.DownloadFile(excelURL, @"F:\識別結果.xls");//這里要改成你的下載文件路徑
Console.WriteLine("下載完畢");
}
作者使用的測試用圖片:

表格文字識別結果截圖:

尾記:本文的示例代碼都是最新的代碼,跟百度SDK文檔里面的代碼是一致的,而雲貓OCR是2017年末就已經寫好的了,代碼有些陳舊,所以沒直接貼源代碼了。
代碼篇的原帖子地址:
http://ai.baidu.com/forum/topic/show/956037
第三部分 雲貓OCR的使用說明及效果評測
一、概述
筆者是在2017年接觸百度雲服務平台的,在這里我也稱之為百度AI 。筆者根據百度AI提供的函數接口,自行編程實現了一款OCR軟件——雲貓OCR。雲貓OCR大部分的代碼開發是在2017年底前完成的,之所以雪藏到現在,是因為筆者的一些私人事務(小孩出生等)——我是利用業余時間進行軟件開發的,所以中斷了大概一年多的時間,現在才有空繼續這個項目。
評測篇的原帖子地址:
http://ai.baidu.com/forum/topic/show/955989
二、評測的具體內容
(一)准備工作
在使用雲貓OCR之前,我們必須先去百度雲官網進行注冊賬號,有了賬號以后,我們還要去具體的雲服務項目下申請API Key和Secret Key ,一般這兩個Key是用戶各人保管的,不能隨便透露給外人。因為百度雲現在已經正式收費,而用戶每人每天的免費調用次數都是有限的,提高限額需要支付費用,用戶使用百度雲AI接口的依據主要就是這兩個Key,所以我們要保管好。下面是簡單的准備工作圖片說明:








(二)正式使用雲貓OCR
用戶有了百度雲API Key和Secret Key之后,就可以正式使用雲貓OCR了。具體使用步驟如下:



(三)評測的具體內容
首先介紹一下雲貓OCR調用的百度AI的主要接口,首先是通用文字識別(帶位置版),其次是通用文字識別(帶位置高精度版),最后是表格文字識別,下面依次介紹這三種識別。
1. 通用文字識別(帶位置版)和通用文字識別(帶位置高精度版)的混合使用

如上圖所示,用戶可以選擇多種語言(包括德語、法語、西班牙語等等),選擇好后點擊文字識別即可。因為百度雲提供的高精度文字識別接口只支持中英文,而通用的文字識別支持除中英文以外的多種語言,所以筆者在編寫軟件中,這兩種接口是混合使用的,具體怎么混合使用請看代碼篇。一般情況下,高精度的文字識別效果比通用的好,但也比較耗時。


本軟件支持識別的文字結果在本機保存為文件,具體如下圖操作:



保存的文件是rtf格式,可以用WPS或者Office Word打開。下面再給出一次性識別20張圖片的統計結果圖示:


從上圖可以看出,百度雲的文字識別結果速度還是不錯的,識別速度是平均大概2-3秒一張圖。
2. 表格文字識別
表格文字識別的主要步驟如下圖所示:

識別的結果軟件會自動保存為Excel文件並打開,如圖:


從上圖可以看出,表格文字識別的速度比普通文字識別要慢一些,大概需要5-6秒。
評測總結:百度OCR對於印刷體的識別還是不錯的,比起以前的OCR軟件來說,百度OCR可以說是革命性的進步。當然,它也有自己的短板。比如手寫體的識別,筆者還沒有評測,但百度雲通用文字高精度接口對手寫體的識別是較差的。再比如QPS並發,我的理解是可以提高OCR文字識別的速度,對於大量的圖片文字識別來說尤其是重要,可以節省大量時間。但遺憾的是,百度雲對並發好像做的不太好,程序不一定支持QPS並發,這個缺點我們也是希望百度后面能夠有所改正。
附錄:
C#編程實現手寫識別
一、概述
本人是用C#編程,調用百度API接口實現手寫體識別的,參考了百度的產品文檔。
文檔地址:https://cloud.baidu.com/doc/OCR/index.html
二、代碼及解說
本人的源代碼大部分是來自百度的產品文檔,但其中也遇到了一些麻煩。比如文字識別的編碼問題,百度的代碼給出的編碼是Default,但在我的機器上這樣做會顯示亂碼。經過查找資料,我把編碼改成UTF8,亂碼的問題才得到解決。
作者的所有源代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Drawing;
using System.Web;
using System.Net;
namespace myHandwrite
{
public static class FileUtils
{
///
/// 轉base64編碼
///
///
///
public static String getFileBase64(String fileName)
{
FileStream filestream = new FileStream(fileName, FileMode.Open);
byte[] arr = new byte[filestream.Length];
filestream.Read(arr, 0, (int)filestream.Length);
string baser64 = Convert.ToBase64String(arr);
filestream.Close();
return baser64;
}
}
class Program
{
// 調用getAccessToken()獲取的 access_token建議根據expires_in 時間 設置緩存
// 返回token示例
public static String TOKEN = "24.adda70c11b9786206253ddb70affdc46.2592000.1493524354.282335-1234567";
// 百度雲中開通對應服務應用的 API Key 建議開通應用的時候多選服務
private static String clientId = "這里改成你的API Key";
// 百度雲中開通對應服務應用的 Secret Key
private static String clientSecret = "這里改成你的Secret Key";
///
/// 獲取token的函數
///
///
public static String getAccessToken()
{
String authHost = "https://aip.baidubce.com/oauth/2.0/token";
HttpClient client = new HttpClient();
List> paraList = new List>();
paraList.Add(new KeyValuePair("grant_type", "client_credentials"));
paraList.Add(new KeyValuePair("client_id", clientId));
paraList.Add(new KeyValuePair("client_secret", clientSecret));
HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
String result = response.Content.ReadAsStringAsync().Result;
//自己加的代碼
JObject jo = (JObject)JsonConvert.DeserializeObject(result.ToString());
string myToken = jo["access_token"].ToString();
Console.WriteLine("獲得的Token是:" + myToken);
return myToken;
}
///
/// 手寫體文字識別
///
///
///
///
public static string myHandwriting(string token,string filename)
{
//string token = "#####調用鑒權接口獲取的token#####";
// 圖片的base64編碼
string strbaser64 = FileUtils.getFileBase64(filename);
string host = "https://aip.baidubce.com/rest/2.0/ocr/v1/handwriting?access_token=" + token;
Encoding encoding = Encoding.Default;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
request.Method = "post";
request.ContentType = "application/x-www-form-urlencoded";
request.KeepAlive = true;
//這里加上了一些參數
String str = "recognize_granularity=big&image=" + HttpUtility.UrlEncode(strbaser64);
byte[] buffer = encoding.GetBytes(str);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//顯示結果是亂碼,嘗試改變編碼,經過測試需要改成UTF8編碼
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string result = reader.ReadToEnd();
Console.WriteLine("手寫文字識別:");
//解析Json的代碼
JObject jo = (JObject)JsonConvert.DeserializeObject(result.ToString());
int num = (int)jo["words_result_num"];
string[] words = new string[num];
for (int i = 0; i < num; i++)
words[i] = jo["words_result"][i]["words"].ToString();
//返回值
string txtOCR = null;
for (int i = 0; i < num; i++)
txtOCR += words[i] + "\n";
//顯示結果
Console.WriteLine(txtOCR);
return txtOCR;
}
static void Main(string[] args)
{
//這里要改成你的圖片路徑
string filename = @"F:\手寫體5.jpg";
string token = getAccessToken();
myHandwriting(token,filename);
Console.Read();
}
}
}
注意,上面的代碼中需要各位改成自己的Akey和Skey,另外要改一下圖片路徑。如果返回的是亂碼,還需要改一下編碼。
識別的結果如下:

程序用的圖片文件如下:

作者:kohakuarc
