上一次咱們討論了Tesseract OCR引擎的用法,做爲一款老牌的OCR引擎,目前已經開源,最新版本3.0中更是加入了中文OCR功能,再加上Google的更新、維護,能夠說是潛力很大,值得期待。由上一次的測試結果也能夠看出,Tesseract的OCR結果還不是很理想,尤爲是中英文混合的文字,其識別率有限。本次咱們來關注下Office 2010中的Onenote,調用其API來測試OCR功能。html
PS:在公司經理一直推薦使用MyBase來記錄工做中遇到的問題、工做日誌等,可是我一直堅持使用Onenote :)git
測試代碼下載編程
在Visual Studio 2010 Ultimate + Onenote 2010 x64中測試經過小程序
轉載請註明出處:http://www.cnblogs.com/brooks-dotnet/archive/2010/10/07/1845313.html網絡
一、Onenote 2010 新特性:架構
New features in 2010:app
Gather, organize, and searchdom |
Sharing and universal accesside |
|
-
Access from anywhere:
- Share on the Web
- View and edit in a browser
- Sync notes to OneNote Mobile
-
Share notes:
- Unread changes are highlighted
- See author initials
- Version history
- Find recent edits
- Find edits by author
- Faster sync with SharePoint
|
Examples:工具
 |
Organize topics using subpages Drag tabs to indent and organize pages within a section. |
 |
Keep notes visible during other tasks OneNote will link notes to documents and Web pages you view.
View > |
 |
|
 |
What's new in a shared notebook? Unread changes are shown automatically. |
 |
What notes are teammates working on?
Share > |
 |
 |
|
 |
Select location when sending to OneNote When sending from Outlook or Internet Explorer |
 |
Link to information for yourself and others
Insert > |
 |
or type |
[[page name]] |
|
More Resources Online
Videos, templates, training, help, and discussion groups.
Microsoft® OneNote® 2010 Guide Notebook
Copyright © 2009 Microsoft Corporation. All rights reserved.
The example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted herein are fictitious. No association with any real company, organization, product, domain name, email address, logo, person, places, or events is intended or should be inferred.
二、Onenote中的OCR功能
園子裏的朋友斯克迪亞很早就寫過一片博文,詳細介紹了GUI下使用OCR功能的方法,當時我也看了,想用編程來實現Onenote的OCR功能。後來忙其餘事就沒有細究,國慶假期我正好在查找一些OCR工具,又想起了這回事,因而多方查找資料、測試,今天終因而略有小成,特與你們分享。程序還存在不少問題,歡迎拍磚。
2.一、關於Onenote OCR功能的一處細節要先提一下,那就是若是從網絡上覆制一幅圖片到Onenote中,是沒法進行OCR的;可是若是從本地插入一幅圖片到Onenote中,則能夠進行OCR:
左邊是本地圖片,右邊是網絡圖片,能夠看出,網絡圖片右鍵菜單中的【Copy Text from Picture】是灰掉的,沒法點擊。


2.二、我用WPF寫的小程序界面以下,和上一次TesseractGUI一模一樣,不過是換藥未換湯。
左邊選擇圖片,支持本地圖片、網絡圖片預覽、縮放、移動,右邊選擇輸出目錄、顯示OCR結果:

2.三、MSDN雜誌上有一篇文章給了我很大的啓發,介紹了Onenote 2010中的對象模型,感興趣的朋友能夠深刻閱讀。CodePlex上還有一個託管的Onenote對象模型項目ONOM,對Onenote PIA提供了更好的封裝。創建WPF項目並添加引用時要注意一下:
首先,因爲與 Visual Studio 2010 隨附的 OneNote 互操做程序集不匹配,您不該該在"添加引用"對話框的".NET"選項卡上直接引用 Microsoft.Office.Interop.OneNote 組件,而是應該在"COM"選項卡上引用 Microsoft OneNote 14.0 類型庫組件。這樣作仍會向項目的引用中加入 OneNote 互操做程序集。
其次,OneNote 14.0 類型庫與 Visual Studio 2010"NOPIA"功能不兼容。在 NOPIA 功能中,主互操做程序集默認狀況下不會嵌入到應用程序中。所以,請務必將 OneNote 互操做程序集引用的"嵌入互操做類型"屬性設置爲 False。

2.四、Onenote沒有采用OpenXML格式進行描述,而是使用了原始的XML ,一個完整的頁面的描述代碼以下:
2.五、Onenote的OCR機制是這樣的:當咱們插入一幅圖片時,Onenote會自動進行OCR處理,並將OCR後的結果以XML的形式寫入到頁面結構中。所以咱們的處理思路是,編程向Onenote中插入一幅圖片,而後提取OCR後的結果。
即【OCRText】標籤中的內容:
<one:OCRText>
<![CDATA[ew features in One Note 14
Gather, organize, and search
. Improved organization inside sections
O Multi-level subpages
o Collapsing subpages
O Drag-dropto make a subpage
o In-place New Page button
. Updated Search that抯 faster than navigating
. Improved hyperlinkingof notes, wiki links
. Outlook and lE integration improvements
O Section picker when sendingtoOneNote
o Notes on Outlook tasks
. QuIck Styles for making headings
. Linked note-taking on Web pages and documents
. Math support
. Dock to Desktop mode
Sharing and universal access
. Access from everywhere
O Share on the Web
O Browser access
O OneNote Mobile- syncs with the Web
. Sharing enhancements:
O Unread highlighting
O Author marks
O Recent Edits
O Find by Author
o VersioningandRecycleBin
O Faster sync with SharePoint
. Improved OneNoteMobile for mobile devices
O Sync overtheair
O Sync selected notebooks or sections]]>
</one:OCRText>
2.六、下面咱們來動手一步步處理,關於界面搭建的XAML再也不贅述,感興趣的朋友請自行下載源代碼,主要關注下業務代碼。
圖片在Onenote XML中是以Base64位編碼格式存在的,故首先對插入的圖片進行Base64編碼:
//獲取圖片的Base64編碼
FileInfo file = new FileInfo(v_strImgPath);
using (MemoryStream ms = new MemoryStream())
{
Bitmap bp = new Bitmap(v_strImgPath);
switch (file.Extension.ToLower())
{
case ".jpg":
bp.Save(ms, ImageFormat.Jpeg);
break;
case ".jpeg":
bp.Save(ms, ImageFormat.Jpeg);
break;
case ".gif":
bp.Save(ms, ImageFormat.Gif);
break;
case ".bmp":
bp.Save(ms, ImageFormat.Bmp);
break;
case ".tiff":
bp.Save(ms, ImageFormat.Tiff);
break;
case ".png":
bp.Save(ms, ImageFormat.Png);
break;
case ".emf":
bp.Save(ms, ImageFormat.Emf);
break;
default:
this.labMsg.Content = "不支持的圖片格式。";
return;
}
byte[] buffer = ms.GetBuffer();
string _Base64 = Convert.ToBase64String(buffer);
2.七、構建插入圖片後的Onenote XML代碼:
var onenoteApp = new Microsoft.Office.Interop.OneNote.Application();
string notebookXml;
onenoteApp.GetHierarchy(null, Microsoft.Office.Interop.OneNote.HierarchyScope.hsPages, out notebookXml);
var doc = XDocument.Parse(notebookXml);
var ns = doc.Root.Name.Namespace;
var pageNode = doc.Descendants(ns + "Page").FirstOrDefault();
var existingPageId = pageNode.Attribute("ID").Value;
2.八、這裏有一處小細節,就是Onenote XML中圖片格式只支持以下幾種:auto|png|emf|jpg,故須要將圖片格式作一下處理:
string ImgExtension = file.Extension.ToLower().Substring(1);
switch (ImgExtension)
{
case "jpg":
ImgExtension = "jpg";
break;
case "png":
ImgExtension = "png";
break;
case "emf":
ImgExtension = "emf";
break;
default:
ImgExtension = "auto";
break;
}
2.九、下面這段是關鍵代碼了,使用Linq to XML構造出插入圖片後的Onenote XML:
var page = new XDocument(new XElement(ns + "Page",
new XElement(ns + "Outline",
new XElement(ns + "OEChildren",
new XElement(ns + "OE",
new XElement(ns + "Image",
new XAttribute("format", ImgExtension), new XAttribute("originalPageNumber", "0"),
new XElement(ns + "Position",
new XAttribute("x", "0"), new XAttribute("y", "0"), new XAttribute("z", "0")),
new XElement(ns + "Size",
new XAttribute("width", bp.Width.ToString()), new XAttribute("height", bp.Height.ToString())),
new XElement(ns + "Data", _Base64)))))));
page.Root.SetAttributeValue("ID", existingPageId);
onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue);
2.十、線程休眠幾秒鐘,等待OCR完成,Onenote OCR根據圖片大小須要消耗一些時間:
//線程休眠時間,單位毫秒,若圖片很大,則延長休眠時間,保證Onenote OCR完畢
System.Threading.Thread.Sleep(Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["WaitTIme"]));
2.十一、爲了便於提取OCR後的結果,將構造好的Onenote XML代碼寫入一個臨時的XML文件:
string pageXml;
onenoteApp.GetPageContent(existingPageId, out pageXml, Microsoft.Office.Interop.OneNote.PageInfo.piAll);
//獲取OCR後的內容
FileStream tmpXml = new FileStream(System.Configuration.ConfigurationManager.AppSettings["tmpPath"] + @"\tmp.xml", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(tmpXml);
sw.Write(pageXml);
sw.Flush();
sw.Close();
tmpXml.Close();
2.十二、使用Linq to XML和XPath表達式提取OCR後的結果:
FileStream tmpOnenote = new FileStream(System.Configuration.ConfigurationManager.AppSettings["tmpPath"] + @"\tmp.xml", FileMode.Open, FileAccess.ReadWrite);
XmlReader reader = XmlReader.Create(tmpOnenote);
XElement rdlc = XElement.Load(reader);
XmlNameTable nameTable = reader.NameTable;
XmlNamespaceManager mgr = new XmlNamespaceManager(nameTable);
mgr.AddNamespace("one", ns.ToString());
StringReader sr = new StringReader(pageXml);
XElement onenote = XElement.Load(sr);
var xml = from o in onenote.XPathSelectElements("//one:Image", mgr)
select o.XPathSelectElement("//one:OCRText", mgr).Value;
this.txtOCRed.Text = xml.First().ToString();
2.1三、釋放佔用的資源:
sr.Close();
reader.Close();
tmpOnenote.Close();
2.1四、最後將OCR後的結果寫入到輸出文件中:
FileStream fs = new FileStream(this.__OutputFileName, FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.Write(this.txtOCRed.Text);
sw.Flush();
sw.Close();
fs.Close();
this.labMsg.Content = "OCR成功。";
因爲我安裝的是Onenote 2010 x64英文版,未找到中文語言包,故先測試下英文OCR。
2.1五、本地圖片測試結果:

2.1六、網絡圖片測試結果:
網絡圖片是先下載到本地,後面步驟和本地圖片同樣。

小結
此方法的優勢是效率很高,可擴展性強,只要改改配置文件、Linq to XML代碼就能夠完成不少附加工做。
缺點是,要求客戶端必需要安裝Onenote,且至少要有一個打開的Page,OCR時沒法判斷哪個圖片是正在OCR的,若連續操做則顯示結果混亂。
此外,我沒有找到編程創建Onenote文檔的方法,以及對Onenote XML架構瞭解的還不夠多,對一些元素不知道如何編程生成,如ObjectID等。
綜上所述,Onenote 2010的OCR水平仍是很高的,和Tesseract相比,OCR的準確率與效率均提升了不止一個檔次,可是鑑於Onenote 2010 API十分簡陋,遠不及Word、Excel等操做方便,且官方文檔對於Onenote 2010 XML架構的介紹還不是很詳細,缺乏示例。但願Office 1五、Onenote 2014能有所改進吧。關於OCR的介紹到此告一段落,歡迎感興趣的朋友繼續討論。