使用OneNote的COM組件,實現OCR功能。

 背景

       在業務系統開發的過程中,很多情況下會去識別圖片中的相關信息,並且把信息錄入到系統中。現在希望通過自動化的方式錄入,就有了以下的工作。在對比了幾個OCR軟件在中文識別方面的準確率後,決定使用微軟的OneNote開發相應的功能。

        準備工作

  1. 安裝OneNote 2010;(注:在 Microsoft Office 2003 中的工具組件中有一個“ Microsoft Office Document Imaging”的組件包,之後的Office版本將這個功能集成到OneNote中了)
  2. 查詢網上相關OneNote的資料,真是少得可憐,即使找到現有的代碼也是各種坑。
  3. 在OneNote中的圖片識別功能如下圖,把圖片放到一個tab中,右鍵圖片就會出現紅框所標註的功能,這個是我需要在程序中來調用的:
     

     

           代碼實現的邏輯

  1.  獲取圖片的Base64編碼;
  2. 開啓OneNote程序,在一個空的newfile.one中,生成一個新的page;
  3. 此時,新的page頁中,會有一個固定格式的xml,把圖片的Base64編碼,更新到對應的節點上;
  4. 更新節點後,會自動調用OCR的功能,把識別出來的文字,放入到固定節點上;
  5. 從識別出來的文字節點上,取出相應的文字就可以了;
  6. 徹底銷燬當前的頁面(如果不是徹底的話,這個newfile.one會越來越大);
public class OrcImage
    {
        private static readonly string tmpPath = AppDomain.CurrentDomain.BaseDirectory + "tmpPath/";
        private static readonly int waitTime = Convert.ToInt32(ConfigurationManager.AppSettings["WaitTime"]);


        private Tuple<string, int, int> GetBase64(string strImgPath)
        {
            return GetBase64(new FileInfo(strImgPath));
        }


        /// <summary>
        /// 獲取圖片的Base64編碼
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        private Tuple<string, int, int> GetBase64(FileInfo file)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                Bitmap bp = new Bitmap(file.FullName);
                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:
                        return new Tuple<string, int, int>("不支持的圖片格式。", 0, 0);
                }
                byte[] buffer = ms.GetBuffer();
                return new Tuple<string, int, int>(Convert.ToBase64String(buffer), bp.Width, bp.Height);
            }
        }


        public string Orc_Img(FileInfo fi)
        {
            // 向Onenote2010中插入圖片
            var onenoteApp = new Microsoft.Office.Interop.OneNote.Application();  //onenote提供的API
            /***************************************************************************************/
            string sectionID;
            onenoteApp.OpenHierarchy(tmpPath + "newfile.one", null, out sectionID, CreateFileType.cftSection);
            string pageID = "{A975EE72-19C3-4C80-9C0E-EDA576DAB5C6}{1}{B0}";  // 格式 {guid}{tab}{??}
            onenoteApp.CreateNewPage(sectionID, out pageID, NewPageStyle.npsBlankPageNoTitle);
            /********************************************************************************/
            string notebookXml;
            onenoteApp.GetHierarchy(null, 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;
            if (pageNode != null)
            {
                Tuple<string, int, int> imgInfo = this.GetBase64(fi);
                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", fi.Extension.Remove(0, 1)), 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", imgInfo.Item2), new XAttribute("height", imgInfo.Item3)),
                                                        new XElement(ns + "Data", imgInfo.Item1)))))));
                page.Root.SetAttributeValue("ID", existingPageId);


                onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue);


                // 線程休眠時間,單位毫秒,若圖片很大,則延長休眠時間,保證Onenote OCR完畢
                int fileSize = Convert.ToInt32(fi.Length / 1024 / 1024); // 文件大小 單位M
                System.Threading.Thread.Sleep(waitTime * (fileSize > 1 ? fileSize : 1)); // 小於1M的都默認1M


                string pageXml;
                onenoteApp.GetPageContent(existingPageId, out pageXml, PageInfo.piBinaryData);


                /*********************************************************************************/


                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(pageXml);
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
                nsmgr.AddNamespace("one", ns.ToString());


                XmlNode xmlNode = xmlDoc.SelectSingleNode("//one:Image//one:OCRText", nsmgr);
                string strRet = xmlNode.InnerText;


                /**********************************************************************/


                onenoteApp.DeleteHierarchy(sectionID, DateTime.MinValue, true);  // 摧毀原始頁面


                return strRet;
            }


            return "沒有識別";
        }
    }

       XML的格式

/*Onenote 2010 中圖片的XML格式
                       <one:Image format="" originalPageNumber="0" lastModifiedTime="" objectID="">
                            <one:Position x="" y="" z=""/>
                            <one:Size width="" height=""/>
                            <one:Data>Base64</one:Data>


                            //以下標籤由Onenote 2010自動生成,不要在程序中處理,目標是獲取OCRText中的內容。
                            <one:OCRData lang="en-US">
                            <one:OCRText>
                                <![CDATA[   OCR後的文字   ]]>
                            </one:OCRText>
                            <one:OCRToken startPos="0" region="0" line="0" x="4.251968383789062" y="3.685039281845092" width="31.18110275268555" height="7.370078563690185"/>
                            <one:OCRToken startPos="7" region="0" line="0" x="39.40157318115234" y="3.685039281845092" width="13.32283401489258" height="8.78740119934082"/>
                            <one:OCRToken startPos="12" region="0" line="1" x="4.251968383789062" y="17.85826683044434" width="23.52755928039551" height="6.803150177001953"/>
                            <one:OCRToken startPos="18" region="0" line="1" x="32.031494140625" y="17.85826683044434" width="41.10236358642578" height="6.803150177001953"/>
                            <one:OCRToken startPos="28" region="0" line="1" x="77.66928863525391" y="17.85826683044434" width="31.46456718444824" height="6.803150177001953"/>
                            ................
                       </one:Image>
                    */


                    /*ObjectID格式
                      The representation of an object to be used for identification of objects on a page. Not unique through OneNote, but unique on the page and the hierarchy.
                       <xsd:simpleType name="ObjectID" ">
                          <xsd:restriction base="xsd:string">
                             <xsd:pattern value="\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}\{[0-9]+\}\{[A-Z][0-9]+\}" />
                          </xsd:restriction>
                       </xsd:simpleType>
                    */

     

        目前是桌面應用程序是實現了相關功能。預期期望是:任何一個系統通過webservice接口形式就能使用OCR功能。但是改成一個web程序遇到了問題,在網上找了僅有的一點點資料,也沒有解決。我瞭解到,現在使用OneNote的OCR功能的程序也都是用WinForm程序,在程序運行的過程中,會在後臺啓動OneNote程序。所以我猜測可能是由於這個原因,導致它只能做成桌面程序。 

   

檢索 COM 類工廠中 CLSID 爲 {D7FAC39E-7FF1-49AA-98CF-A1DDD316337E} 的組件失敗,原因是出現以下錯誤: 80070005 拒絕訪問。 (異常來自 HRESULT:0x80070005 (E_ACCESSDENIED))。

web中報這個錯誤,是權限的問題。依照配置Excel,Word這類COM來找,可是發現DCOM中,一直都找不到這個ID的組件。知道的朋友麻煩告知一下,謝謝。


安裝OneNote 2010;(注:在 Microsoft Office 2003 中的工具組件中有一個“ M

      程序效果圖如下:識別效果還不錯,剩下的就是根據所需要的信息,進行正則表達式的匹配就可以了。

 

轉載自:http://www.cnblogs.com/BenAndWang/p/5826634.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章