篇一:WPF常用知識以及本項目設計總結:http://www.cnblogs.com/baiboy/p/wpf.html
篇二:基於OneNote難點突破和批量識別:http://www.cnblogs.com/baiboy/p/wpf1.html
篇三:批量處理后的txt文件入庫處理:http://www.cnblogs.com/baiboy/p/wpf2.html
篇四:關於OneNote入庫處理以及審核:http://www.cnblogs.com/baiboy/p/wpf3.html
【小記】:大膽嘗試才能突破,某個中醫葯大學有一批圖片需要處理(ORC),然后進行數據挖掘。之前沒有接觸過ORC這個東西,但是還是應允了。在網上搜索一番,關於中文圖片識別,最終敲定為基於微軟的OneNote,其識別率相對較高。網上這個技術點的資料真心不多,后來於博客園找到一篇博文,但是那個程序還是bug百出,而且只是單處理。后來經過一番摸索逐個突破,批處理完成。然后進行界面設計,這些零碎工作完成后,便是入庫處理。由於OneNote生成的xml文件封裝好的,即不可視的。便將其代碼處理生成txt文件,再進行Oracle入庫處理。入庫前需要文件內容審核,並且在WPF開發中數據綁定和分頁中做了獨特處理。現在經過半個月的工作,本項目做個階段總結。一則知識總結便於二次開發,盡量保持程序流暢性,核心知識做以梳理;另外,相關WPF和OneNote常用技術共享,便於部分園友所需。本人技術有限,歡迎交流。項目還未結束,暫作階段文章發布,隨后相繼發布。
篇二:基於OneNote難點突破和批量識別
【1】開篇概述:在對本章技術介紹前,還是梳理下思路。描述下本章功能和開發過程。做個系統大致了解之后,在粘貼出本節效果圖配以完整代碼,然后分拆之,個體技術剖析。這樣既可以達到全局整體效果,也可以對局部技術或者知識點做以小結。功能看圖描述:本程序開發基於C#+WPF,然后這些條件具備前需要安裝office2010以上版本,包含OneNote即可
完整代碼:

namespace OnenoteOCRDemo { /// <summary> /// Main.xaml 的交互邏輯 /// </summary> public partial class Main : Window { #region 全局變量 private string __OutputFileName = string.Empty; private WebClient client = new WebClient(); private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value); #endregion #region 系統函數 public Main() { InitializeComponent(); } #endregion #region 用戶函數 #region 驗證文件夾是否存在,以及是否為空 :2014-7-10 17:12:57 //驗證文件夾是否存在,以及是否為空 //時間:2014-7-10 14:54:44 //作者:白寧超 private bool fn數據驗證() { if ((bool)this.rbtn本地圖片.IsChecked) { if (!Directory.Exists(this.txtfile.Text)) { this.labMsg.Content = "目錄不存在,重新選擇!"; this.txtfile.Focus(); return true; } System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(@txtfile.Text); if (di.GetFiles().Length + di.GetDirectories().Length == 0) { this.labMsg.Content = "目錄為空!"; this.txtfile.Focus(); return true; } } if (!Directory.Exists(this.txt輸出目錄.Text)) { this.labMsg.Content = "輸出目錄不存在,請重新選擇。"; this.txt輸出目錄.Focus(); return true; } return false; } #endregion #region 遍歷出文件中圖片路徑 //文件中選擇所有文件處理 //時間:2014-7-10 17:17:29 //作者:白寧超 public List<string> GetImgPath(string Filepath) { DirectoryInfo d = new DirectoryInfo(Filepath); ArrayList Flst = GetAll(d); //存放圖片完整路徑 List<string> imgpath = new List<string>(); foreach (object o in Flst) { imgpath.Add(@txtfile.Text + "\\" + o.ToString()); } return imgpath;//返回圖片路徑集合 } #endregion #region 獲取圖片的過程 private void fnStartDownload(string v_strImgPath, string v_strOutputDir, out string v_strTmpPath) { int n = v_strImgPath.LastIndexOf('/'); string URLAddress = v_strImgPath.Substring(0, n); string fileName = v_strImgPath.Substring(n + 1, v_strImgPath.Length - n - 1); this.__OutputFileName = v_strOutputDir + "\\" + fileName.Substring(0, fileName.LastIndexOf(".")) + ".txt"; if (!Directory.Exists(System.Configuration.ConfigurationManager.AppSettings["tmpPath"])) { Directory.CreateDirectory(System.Configuration.ConfigurationManager.AppSettings["tmpPath"]); } string Dir = System.Configuration.ConfigurationManager.AppSettings["tmpPath"]; v_strTmpPath = Dir + "\\" + fileName; this.client.DownloadFile(v_strImgPath, v_strTmpPath); } #endregion #region//刪除指定目錄下的所有文件夾以及文件 private void DelFillOrDir(string strPath) { if (Directory.GetDirectories(strPath).Length > 0 || Directory.GetFiles(strPath).Length > 0) { // 獲得文件夾數組 string[] strDirs = System.IO.Directory.GetDirectories(strPath); // 獲得文件數組 string[] strFiles = System.IO.Directory.GetFiles(strPath); // 遍歷所有子文件夾 foreach (string strFile in strFiles) { // 刪除文件夾 System.IO.File.Delete(strFile); } // 遍歷所有文件 foreach (string strdir in strDirs) { // 刪除文件 System.IO.Directory.Delete(strdir, true); } } // 成功 } #endregion #region//刪除文件 public static bool DeleteFile(string xmlPath) { FileInfo newFile = new FileInfo(xmlPath); if (newFile.Exists == true) { newFile.Delete(); return true; } else { return false; } } #endregion #region//刪除xml數據 public void DeleteXML(string xpath) { var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API string notebookXml; onenoteApp.GetHierarchy(null, Microsoft.Office.Interop.OneNote.HierarchyScope.hsPages, out notebookXml); var docc = XDocument.Parse(notebookXml); var ns = docc.Root.Name.Namespace; XDocument doc = XDocument.Load(xpath); string author = "USER-"; XElement xe = (from db in doc.Element(ns + "Page").Elements(ns + "Outline") where db.Attribute("author").Value == author select db).Single() as XElement; try { xe.Remove(); doc.Save(xpath); } catch { } } #region OCR寫入Onenote和生成文字整個過程 //string xpath = @"C:\Users\Administrator\Desktop\OCR_Onenote\OnenoteOCR2.1\tmp.xml"; private void fnOCR(string v_strImgPath) { ORC(v_strImgPath); } public void ORC(string v_strImgPath) { FileInfo file = new FileInfo(v_strImgPath); #region //獲取圖片的Base64編碼 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); #endregion //向Onenote2010中插入圖片 var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API /***************************************************************************************/ string sectionID; onenoteApp.OpenHierarchy(@"C:\Users\Administrator\Documents\OneNote 筆記本\個人\newfile.one", null, out sectionID, Microsoft.Office.Interop.OneNote.CreateFileType.cftSection); string pageID = "{A975EE72-19C3-4C80-9C0E-EDA576DAB5C6}{1}{B0}"; onenoteApp.CreateNewPage(sectionID, out pageID, Microsoft.Office.Interop.OneNote.NewPageStyle.npsBlankPageNoTitle); /********************************************************************************/ 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; #region if (pageNode != null) { //Image Type 只支持這些類型: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; } #endregion 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); //保存圖片進入Onenote頁面 //注意以下幾點:(待解決) //1,onenote頁面自動會生成一個頁面,可能造成一直ocr錯誤。刪除默認頁面,新建空頁 //2,圖片存儲在新建頁面中,通過如下代碼實現的,以追加存儲方式進行。 onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue); //線程休眠時間,單位毫秒,若圖片很大,則延長休眠時間,保證Onenote OCR完畢 System.Threading.Thread.Sleep(Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["WaitTIme"])); string pageXml; onenoteApp.GetPageContent(existingPageId, out pageXml, Microsoft.Office.Interop.OneNote.PageInfo.piBinaryData); //獲取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(); //加載xml中的數據 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); // rdlc.Save(xpath); /*****************************************************************************************************/ XmlNameTable nameTable = reader.NameTable; XmlNamespaceManager mgr = new XmlNamespaceManager(nameTable); mgr.AddNamespace("one", ns.ToString()); StringReader sr = new StringReader(pageXml); XElement onenote = XElement.Load(sr); ////讀取xml中數據,並保存到文本中。 //XDocument doc1 = XDocument.Load(xpath); var xml = from o in onenote.XPathSelectElements("//one:Image", mgr) select o.XPathSelectElement("//one:OCRText", mgr).Value; this.txtOCRed.Text = xml.First().ToString(); /**********************************************************************/ sr.Close(); reader.Close(); tmpOnenote.Close(); //DeleteXML(xpath); onenoteApp.DeleteHierarchy(existingPageId); //onenoteApp.DeletePageContent(existingPageId, "{242BE490-7BF9-43D5-B719-3999E7631259}{46}{B0}"); //onenoteApp.DeletePageContent(existingPageId, "{242BE490-7BF9-43D5-B719-3999E7631259}{50}{B0}"); } } } #endregion #endregion #endregion #region 系統事件 #region 搜索文件夾中的文件:2014-7-10 17:12:57 //搜索文件夾中的文件 //時間:2014-7-10 14:54:44 //作者:白寧超 ArrayList GetAll(DirectoryInfo dir) { try { ArrayList FileList = new ArrayList();//定義數組存放圖片文件名 FileInfo[] allFile = dir.GetFiles(); foreach (FileInfo fi in allFile) { FileList.Add(fi.Name);//遍歷圖片,並添加到數組 } DirectoryInfo[] allDir = dir.GetDirectories(); foreach (DirectoryInfo d in allDir) { GetAll(d); } return FileList; } catch (Exception e) { labMsg.Content = e.Message + "文件夾選擇方式錯誤,重新選擇!!"; return null; } } #endregion #region 選擇遍歷文件夾圖片 //文件中選擇所有文件處理 //時間:2014-7-10 14:54:44 //作者:白寧超 private void btn瀏覽_Click(object sender, RoutedEventArgs e) { txtmulu.Text = null; FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.Description = "請選擇待處理目錄"; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string foldPath = dialog.SelectedPath; txtfile.Text = foldPath; DirectoryInfo d = new DirectoryInfo(@txtfile.Text); ArrayList Flst = GetAll(d); foreach (object o in Flst) { txtmulu.Text += "正在ORC圖片: 【" + o.ToString() + "】\r\n"; } } else { labMsg.Content = "打開失敗!!"; } #region 上傳單個圖片 2014-7-10 15:34:17 /*OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "請選擇一個本地圖片"; ofd.Multiselect = false; ofd.Filter = "支持的圖片格式(*.jpg,*.jpeg,*.gif,*.bmp,*.png,*.tiff,*.emf)|*.jpg;*.jpeg;*.gif;*.bmp;*.png;*.tiff;*.emf"; if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { this.txt本地圖片.Text = ofd.FileName; this.img圖片.Source = new BitmapImage(new Uri(ofd.FileName, UriKind.RelativeOrAbsolute)); this.labMsg.Content = "本地圖片已成功加載。"; }*/ #endregion } #endregion #region 選擇本地圖片OCR轉化 private void rbtn本地圖片_Checked(object sender, RoutedEventArgs e) { if (this.IsInitialized) { if ((bool)this.rbtn本地圖片.IsChecked) { this.txtfile.Text = string.Empty; this.txtfile.IsEnabled = true; this.btn瀏覽.IsEnabled = true; this.txtfile.Focus(); this.txtmulu.Text = null; } } } #endregion #region 選擇需要輸入處理的文件 private void btn瀏覽_Click_1(object sender, RoutedEventArgs e) { txtmulu.Text = null; FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.Description = "請選擇待處理目錄"; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string foldPath = dialog.SelectedPath; txtfile.Text = foldPath; DirectoryInfo d = new DirectoryInfo(@txtfile.Text); ArrayList Flst = GetAll(d); foreach (object o in Flst) { txtmulu.Text += "正在ORC圖片: 【" + o.ToString() + "】\r\n"; } } else { labMsg.Content = "打開失敗!!"; } #region 上傳單個圖片 2014-7-10 15:34:17 /*OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "請選擇一個本地圖片"; ofd.Multiselect = false; ofd.Filter = "支持的圖片格式(*.jpg,*.jpeg,*.gif,*.bmp,*.png,*.tiff,*.emf)|*.jpg;*.jpeg;*.gif;*.bmp;*.png;*.tiff;*.emf"; if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { this.txt本地圖片.Text = ofd.FileName; this.img圖片.Source = new BitmapImage(new Uri(ofd.FileName, UriKind.RelativeOrAbsolute)); this.labMsg.Content = "本地圖片已成功加載。"; }*/ #endregion } #endregion #region 選擇輸出文件夾 private void btn輸出瀏覽_Click(object sender, RoutedEventArgs e) { FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.Description = "請選擇一個輸出目錄"; if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { this.txt輸出目錄.Text = fbd.SelectedPath; DelFillOrDir(this.txt輸出目錄.Text); } } #endregion #region 清空輸出文件 private void btn清空_Click(object sender, RoutedEventArgs e) { OCRtxt.Text = ""; this.OCRtxt.Focus(); } #endregion #region ORC轉化過程 private void btnOCR_Click(object sender, RoutedEventArgs e) { if (this.fn數據驗證()) { OCRtxt.Text = ""; return; } try { DirectoryInfo dir = new DirectoryInfo(this.txt輸出目錄.Text); if ((bool)this.rbtn本地圖片.IsChecked) { List<string> imgpath = GetImgPath(@txtfile.Text);//獲取圖片列表 //定義進度條默認值 pb_import.Minimum = 0; pb_import.Maximum = imgpath.Count(); double i = 0; txtOCRed.Text = ""; OCRtxt.Text += "******************************************************************************"; foreach (object img in imgpath) { this.fnOCR(img.ToString());//遍歷處理圖片orc FileInfo file = new FileInfo(img.ToString()); string name = file.Name.Substring(0, file.Name.LastIndexOf(".")); this.__OutputFileName = dir.FullName + @"\" + name + ".txt"; FileStream fs = new FileStream(this.__OutputFileName, FileMode.Create, FileAccess.ReadWrite); StreamWriter sw = new StreamWriter(fs); sw.Write(this.txtOCRed.Text);//將this.txtOCRed.Text內容寫進txt文件中 sw.Flush(); sw.Close(); fs.Close(); OCRtxt.Text += "成功ORC出: 【" + name + ".txt】" + "\r\n"; //回調UI進度顯示 i++; pb_import.Value = i; UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(pb_import.SetValue); Dispatcher.Invoke(updatePbDelegate, System.Windows.Threading.DispatcherPriority.Background, new object[] { System.Windows.Controls.ProgressBar.ValueProperty, Convert.ToDouble(i + 1) }); Thread.Sleep(1000); } } if (pb_import.Value == pb_import.Maximum) { System.Windows.Forms.MessageBox.Show("數據轉換完成。"); } else { System.Windows.Forms.MessageBox.Show("數據轉換失敗。"); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show("數據轉換失敗:" + ex.Message + ex.StackTrace); this.labMsg.Content = "OCR失敗。"; } finally { //System.Threading.Thread.CurrentThread.Abort(); Thread.Sleep(3000); } } #endregion #region//窗體關閉 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { DirectoryInfo dir = new DirectoryInfo(System.Configuration.ConfigurationManager.AppSettings["tmpPath"]); foreach (FileInfo file in dir.GetFiles()) { file.Delete(); } } #endregion #endregion } }
功能以及操作描述:
- 運行本頁面如上圖,然后通過選擇待處理目錄(含中文文字圖片),和輸出目錄,點擊ORC即可。
- 在待處理目錄下,點擊瀏覽按鈕,然后選擇相應的文件夾,后台通過判斷文件夾是否存在,如果存在進行遍歷,讀取出所有圖片,然后在本頁左端文本框對圖片進行顯示。
- 然后選擇輸出目錄中的瀏覽按鈕,選擇處理后的結果存放文件夾,此項必填。否則不執行。在每次操作瀏覽按鈕時,會對選擇的文件夾進行清空處理,這樣下次操作保持干凈數據。
- 完成以上步驟,可以進行ORC操作,操作過程中通過遍歷文件夾中圖片文件,在一個方面中打開OneNote接口,對圖片進行處理。圖片處理生成的是一個xml文件,此文件不可視,一個緩存的xml文件,隨着程序結束而終止,在處理過程中通過代碼解析緩存xml,將文本數據提取到一個txt文件中。同時沒執行一張圖片,如圖左邊打印成功執行的文件,同時進度條滾動,結束后進行提示。
- 最后打開對應文件夾里面顯示生產數據與對應圖片保持一致。規范字體識別率還是可以的
所遇問題以及瓶頸突破:
- 在描述難點之前,我還是先提取出核心ORC代碼,下面再做以概述。遍歷處理圖片

#region foreach (object img in imgpath) { this.fnOCR(img.ToString());//遍歷處理圖片orc FileInfo file = new FileInfo(img.ToString()); string name = file.Name.Substring(0, file.Name.LastIndexOf(".")); this.__OutputFileName = dir.FullName + @"\" + name + ".txt"; FileStream fs = new FileStream(this.__OutputFileName, FileMode.Create, FileAccess.ReadWrite); StreamWriter sw = new StreamWriter(fs); sw.Write(this.txtOCRed.Text);//將this.txtOCRed.Text內容寫進txt文件中 sw.Flush(); sw.Close(); fs.Close(); OCRtxt.Text += "成功ORC出: 【" + name + ".txt】" + "\r\n"; //回調UI進度顯示 i++; pb_import.Value = i; UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(pb_import.SetValue); Dispatcher.Invoke(updatePbDelegate, System.Windows.Threading.DispatcherPriority.Background, new object[] { System.Windows.Controls.ProgressBar.ValueProperty, Convert.ToDouble(i + 1) }); Thread.Sleep(1000); } #endregion
- fnOCR圖片處理核心代碼:下面截取核心代碼,詳細見付碼
public void ORC(string v_strImgPath) { FileInfo file = new FileInfo(v_strImgPath); //向Onenote2010中插入圖片 var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API /***************************************************************************************/ string sectionID; onenoteApp.OpenHierarchy(@"C:\Users\Administrator\Documents\OneNote 筆記本\個人\newfile.one", null, out sectionID, Microsoft.Office.Interop.OneNote.CreateFileType.cftSection); string pageID = "{A975EE72-19C3-4C80-9C0E-EDA576DAB5C6}{1}{B0}"; onenoteApp.CreateNewPage(sectionID, out pageID, Microsoft.Office.Interop.OneNote.NewPageStyle.npsBlankPageNoTitle); /********************************************************************************/ 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; 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); //保存圖片進入Onenote頁面 //注意以下幾點:(待解決) //1,onenote頁面自動會生成一個頁面,可能造成一直ocr錯誤。刪除默認頁面,新建空頁 //2,圖片存儲在新建頁面中,通過如下代碼實現的,以追加存儲方式進行。 onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue); //線程休眠時間,單位毫秒,若圖片很大,則延長休眠時間,保證Onenote OCR完畢 System.Threading.Thread.Sleep(Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["WaitTIme"])); string pageXml; onenoteApp.GetPageContent(existingPageId, out pageXml, Microsoft.Office.Interop.OneNote.PageInfo.piBinaryData); //獲取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(); //加載xml中的數據 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); ////讀取xml中數據,並保存到文本中。 //XDocument doc1 = XDocument.Load(xpath); var xml = from o in onenote.XPathSelectElements("//one:Image", mgr) select o.XPathSelectElement("//one:OCRText", mgr).Value; this.txtOCRed.Text = xml.First().ToString(); /**********************************************************************/ sr.Close(); reader.Close(); tmpOnenote.Close(); onenoteApp.DeleteHierarchy(existingPageId); } } }
問題繼續描述,未加入如上代碼時,暫且不說批處理,即便是單處理。結果是無論加載多少張圖片,可以生成對應txt文件,但是對應的所有txt文件里面文本內容始終一樣。解決方案分析下:
- 是文本生成問題,於是想到每次圖片生成清理出前一個xml,但是無論如何找不到xml存在,后來斷點調試發現,執行onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue);之后,打開Onenote頁面會發現圖片出來,說明onenote已經在處理,此刻xml已經生成。接下來 onenoteApp.GetPageContent(existingPageId, out pageXml, Microsoft.Office.Interop.OneNote.PageInfo.piBinaryData);方法把不可見的xml以字符串形式pageXml顯示處理,后面就是對其處理了。證明從xml着手是不能解決問題的。
- 接下來就是想另一個方案:采用接口提供的DeletePageContent方法,但是面臨問題在於其需要兩個參數(頁面序列id,和圖片id),對於頁面序列id通過斷點可以找到,但是圖片是隨機的,id無法控制。因此此方案失敗。
3. 在讀取xml中發現this.txtOCRed.Text = xml.First().ToString();那么讓去每次讀取最后一條數據不就ok?對,,肯定這樣,抱着堅定信心解決半日不得解。斷點再經調試發現,讀取的xml是不可控的,即是緩存中xml以輸出參數,輸出的字符串的處理。最終還不得解決。為此困惑數日。
4. 那么在生成的緩存xml重新放置到新建的xml中,然后每次讀取一條結束,刪除本次記錄。問題肯定解決的,大喜,於是做出如下構造:

#region//刪除xml數據 public void DeleteXML(string xpath) { var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API string notebookXml; onenoteApp.GetHierarchy(null, Microsoft.Office.Interop.OneNote.HierarchyScope.hsPages, out notebookXml); var docc = XDocument.Parse(notebookXml); var ns = docc.Root.Name.Namespace; XDocument doc = XDocument.Load(xpath); string author = "USER-"; XElement xe = (from db in doc.Element(ns + "Page").Elements(ns + "Outline") where db.Attribute("author").Value == author select db).Single() as XElement; try { xe.Remove(); doc.Save(xpath); } catch { } } #region OCR寫入Onenote和生成文字整個過程 //string xpath = @"C:\Users\Administrator\Desktop\OCR_Onenote\OnenoteOCR2.1\tmp.xml"; private void fnOCR(string v_strImgPath) { ORC(v_strImgPath); } public void ORC(string v_strImgPath) { FileInfo file = new FileInfo(v_strImgPath); #region //獲取圖片的Base64編碼 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); #endregion //向Onenote2010中插入圖片 var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API /***************************************************************************************/ string sectionID; onenoteApp.OpenHierarchy(@"C:\Users\Administrator\Documents\OneNote 筆記本\個人\newfile.one", null, out sectionID, Microsoft.Office.Interop.OneNote.CreateFileType.cftSection); string pageID = "{A975EE72-19C3-4C80-9C0E-EDA576DAB5C6}{1}{B0}"; onenoteApp.CreateNewPage(sectionID, out pageID, Microsoft.Office.Interop.OneNote.NewPageStyle.npsBlankPageNoTitle); /********************************************************************************/ 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; #region if (pageNode != null) { //Image Type 只支持這些類型: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; } #endregion 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); //保存圖片進入Onenote頁面 //注意以下幾點:(待解決) //1,onenote頁面自動會生成一個頁面,可能造成一直ocr錯誤。刪除默認頁面,新建空頁 //2,圖片存儲在新建頁面中,通過如下代碼實現的,以追加存儲方式進行。 onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue); //線程休眠時間,單位毫秒,若圖片很大,則延長休眠時間,保證Onenote OCR完畢 System.Threading.Thread.Sleep(Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["WaitTIme"])); string pageXml; onenoteApp.GetPageContent(existingPageId, out pageXml, Microsoft.Office.Interop.OneNote.PageInfo.piBinaryData); //獲取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(); //加載xml中的數據 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); // rdlc.Save(xpath); /*****************************************************************************************************/ XmlNameTable nameTable = reader.NameTable; XmlNamespaceManager mgr = new XmlNamespaceManager(nameTable); mgr.AddNamespace("one", ns.ToString()); StringReader sr = new StringReader(pageXml); XElement onenote = XElement.Load(sr); ////讀取xml中數據,並保存到文本中。 //XDocument doc1 = XDocument.Load(xpath); var xml = from o in onenote.XPathSelectElements("//one:Image", mgr) select o.XPathSelectElement("//one:OCRText", mgr).Value; this.txtOCRed.Text = xml.First().ToString(); /**********************************************************************/ sr.Close(); reader.Close(); tmpOnenote.Close(); //DeleteXML(xpath); onenoteApp.DeleteHierarchy(existingPageId); //onenoteApp.DeletePageContent(existingPageId, "{242BE490-7BF9-43D5-B719-3999E7631259}{46}{B0}"); //onenoteApp.DeletePageContent(existingPageId, "{242BE490-7BF9-43D5-B719-3999E7631259}{50}{B0}"); } } } #endregion #endregion
結果還是無濟於事,關鍵還是緩存的xml無法清理。
解決方案:搞定凌晨,無意間打開幾篇英文文章(文章看不懂,只看代碼),發現其原理在於圖片處理過程中,催毀原始頁面,新建頁面即可。
var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API /***************************************************************************************/ string sectionID; onenoteApp.OpenHierarchy(@"C:\Users\Administrator\Documents\OneNote 筆記本\個人\newfile.one", null, out sectionID, Microsoft.Office.Interop.OneNote.CreateFileType.cftSection); string pageID = "{A975EE72-19C3-4C80-9C0E-EDA576DAB5C6}{1}{B0}"; onenoteApp.CreateNewPage(sectionID, out pageID, Microsoft.Office.Interop.OneNote.NewPageStyle.npsBlankPageNoTitle); /********************************************************************************/
調用API中創建頁面方法CreateNewPage,pageID通過斷點可以調試到,sectionID找到本地的地址即可。然后在執行一條數據結束時,調用onenoteApp.DeleteHierarchy(existingPageId)即可。
止於此核心問題解決,下面總結下所用的文件相關操作:
1 、驗證文件夾是否存在,以及是否為空

#region 驗證文件夾是否存在,以及是否為空 :2014-7-10 17:12:57 //驗證文件夾是否存在,以及是否為空 //時間:2014-7-10 14:54:44 //作者:白寧超 private bool fn數據驗證() { if ((bool)this.rbtn本地圖片.IsChecked) { if (!Directory.Exists(this.txtfile.Text)) { this.labMsg.Content = "目錄不存在,重新選擇!"; this.txtfile.Focus(); return true; } System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(@txtfile.Text); if (di.GetFiles().Length + di.GetDirectories().Length == 0) { this.labMsg.Content = "目錄為空!"; this.txtfile.Focus(); return true; } } if (!Directory.Exists(this.txt輸出目錄.Text)) { this.labMsg.Content = "輸出目錄不存在,請重新選擇。"; this.txt輸出目錄.Focus(); return true; } return false; } #endregion
2、遍歷出文件中圖片路徑

#region 遍歷出文件中圖片路徑 //文件中選擇所有文件處理 //時間:2014-7-10 17:17:29 //作者:白寧超 public List<string> GetImgPath(string Filepath) { DirectoryInfo d = new DirectoryInfo(Filepath); ArrayList Flst = GetAll(d); //存放圖片完整路徑 List<string> imgpath = new List<string>(); foreach (object o in Flst) { imgpath.Add(@txtfile.Text + "\\" + o.ToString()); } return imgpath;//返回圖片路徑集合 } #endregion
3、獲取圖片的過程

#region 獲取圖片的過程 private void fnStartDownload(string v_strImgPath, string v_strOutputDir, out string v_strTmpPath) { int n = v_strImgPath.LastIndexOf('/'); string URLAddress = v_strImgPath.Substring(0, n); string fileName = v_strImgPath.Substring(n + 1, v_strImgPath.Length - n - 1); this.__OutputFileName = v_strOutputDir + "\\" + fileName.Substring(0, fileName.LastIndexOf(".")) + ".txt"; if (!Directory.Exists(System.Configuration.ConfigurationManager.AppSettings["tmpPath"])) { Directory.CreateDirectory(System.Configuration.ConfigurationManager.AppSettings["tmpPath"]); } string Dir = System.Configuration.ConfigurationManager.AppSettings["tmpPath"]; v_strTmpPath = Dir + "\\" + fileName; this.client.DownloadFile(v_strImgPath, v_strTmpPath); } #endregion
4、刪除指定目錄下的所有文件夾以及文件

#region//刪除指定目錄下的所有文件夾以及文件 private void DelFillOrDir(string strPath) { if (Directory.GetDirectories(strPath).Length > 0 || Directory.GetFiles(strPath).Length > 0) { // 獲得文件夾數組 string[] strDirs = System.IO.Directory.GetDirectories(strPath); // 獲得文件數組 string[] strFiles = System.IO.Directory.GetFiles(strPath); // 遍歷所有子文件夾 foreach (string strFile in strFiles) { // 刪除文件夾 System.IO.File.Delete(strFile); } // 遍歷所有文件 foreach (string strdir in strDirs) { // 刪除文件 System.IO.Directory.Delete(strdir, true); } } // 成功 } #endregion
5、刪除文件

#region//刪除文件 public static bool DeleteFile(string xmlPath) { FileInfo newFile = new FileInfo(xmlPath); if (newFile.Exists == true) { newFile.Delete(); return true; } else { return false; } } #endregion
6、刪除xml數據

#region//刪除xml數據 public void DeleteXML(string xpath) { var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API string notebookXml; onenoteApp.GetHierarchy(null, Microsoft.Office.Interop.OneNote.HierarchyScope.hsPages, out notebookXml); var docc = XDocument.Parse(notebookXml); var ns = docc.Root.Name.Namespace; XDocument doc = XDocument.Load(xpath); string author = "USER-"; XElement xe = (from db in doc.Element(ns + "Page").Elements(ns + "Outline") where db.Attribute("author").Value == author select db).Single() as XElement; try { xe.Remove(); doc.Save(xpath); } catch { } } #region OCR寫入Onenote和生成文字整個過程 //string xpath = @"C:\Users\Administrator\Desktop\OCR_Onenote\OnenoteOCR2.1\tmp.xml"; private void fnOCR(string v_strImgPath) { ORC(v_strImgPath); } public void ORC(string v_strImgPath) { FileInfo file = new FileInfo(v_strImgPath); #region //獲取圖片的Base64編碼 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); #endregion //向Onenote2010中插入圖片 var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API /***************************************************************************************/ string sectionID; onenoteApp.OpenHierarchy(@"C:\Users\Administrator\Documents\OneNote 筆記本\個人\newfile.one", null, out sectionID, Microsoft.Office.Interop.OneNote.CreateFileType.cftSection); string pageID = "{A975EE72-19C3-4C80-9C0E-EDA576DAB5C6}{1}{B0}"; onenoteApp.CreateNewPage(sectionID, out pageID, Microsoft.Office.Interop.OneNote.NewPageStyle.npsBlankPageNoTitle); /********************************************************************************/ 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; #region if (pageNode != null) { //Image Type 只支持這些類型: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; } #endregion 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); //保存圖片進入Onenote頁面 //注意以下幾點:(待解決) //1,onenote頁面自動會生成一個頁面,可能造成一直ocr錯誤。刪除默認頁面,新建空頁 //2,圖片存儲在新建頁面中,通過如下代碼實現的,以追加存儲方式進行。 onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue); //線程休眠時間,單位毫秒,若圖片很大,則延長休眠時間,保證Onenote OCR完畢 System.Threading.Thread.Sleep(Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["WaitTIme"])); string pageXml; onenoteApp.GetPageContent(existingPageId, out pageXml, Microsoft.Office.Interop.OneNote.PageInfo.piBinaryData); //獲取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(); //加載xml中的數據 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); // rdlc.Save(xpath); /*****************************************************************************************************/ XmlNameTable nameTable = reader.NameTable; XmlNamespaceManager mgr = new XmlNamespaceManager(nameTable); mgr.AddNamespace("one", ns.ToString()); StringReader sr = new StringReader(pageXml); XElement onenote = XElement.Load(sr); ////讀取xml中數據,並保存到文本中。 //XDocument doc1 = XDocument.Load(xpath); var xml = from o in onenote.XPathSelectElements("//one:Image", mgr) select o.XPathSelectElement("//one:OCRText", mgr).Value; this.txtOCRed.Text = xml.First().ToString(); /**********************************************************************/ sr.Close(); reader.Close(); tmpOnenote.Close(); //DeleteXML(xpath); onenoteApp.DeleteHierarchy(existingPageId); //onenoteApp.DeletePageContent(existingPageId, "{242BE490-7BF9-43D5-B719-3999E7631259}{46}{B0}"); //onenoteApp.DeletePageContent(existingPageId, "{242BE490-7BF9-43D5-B719-3999E7631259}{50}{B0}"); } } } #endregion #endregion
7、搜索文件夾中的文件

#region 搜索文件夾中的文件:2014-7-10 17:12:57 //搜索文件夾中的文件 //時間:2014-7-10 14:54:44 //作者:白寧超 ArrayList GetAll(DirectoryInfo dir) { try { ArrayList FileList = new ArrayList();//定義數組存放圖片文件名 FileInfo[] allFile = dir.GetFiles(); foreach (FileInfo fi in allFile) { FileList.Add(fi.Name);//遍歷圖片,並添加到數組 } DirectoryInfo[] allDir = dir.GetDirectories(); foreach (DirectoryInfo d in allDir) { GetAll(d); } return FileList; } catch (Exception e) { labMsg.Content = e.Message + "文件夾選擇方式錯誤,重新選擇!!"; return null; } } #endregion
8、選擇遍歷文件夾圖片

private void btn瀏覽_Click(object sender, RoutedEventArgs e) { txtmulu.Text = null; FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.Description = "請選擇待處理目錄"; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string foldPath = dialog.SelectedPath; txtfile.Text = foldPath; DirectoryInfo d = new DirectoryInfo(@txtfile.Text); ArrayList Flst = GetAll(d); foreach (object o in Flst) { txtmulu.Text += "正在ORC圖片: 【" + o.ToString() + "】\r\n"; } } else { labMsg.Content = "打開失敗!!"; } #region 上傳單個圖片 2014-7-10 15:34:17 /*OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "請選擇一個本地圖片"; ofd.Multiselect = false; ofd.Filter = "支持的圖片格式(*.jpg,*.jpeg,*.gif,*.bmp,*.png,*.tiff,*.emf)|*.jpg;*.jpeg;*.gif;*.bmp;*.png;*.tiff;*.emf"; if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { this.txt本地圖片.Text = ofd.FileName; this.img圖片.Source = new BitmapImage(new Uri(ofd.FileName, UriKind.RelativeOrAbsolute)); this.labMsg.Content = "本地圖片已成功加載。"; }*/ #endregion }
9、窗體關閉

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { DirectoryInfo dir = new DirectoryInfo(System.Configuration.ConfigurationManager.AppSettings["tmpPath"]); foreach (FileInfo file in dir.GetFiles()) { file.Delete(); } }
【補充】orc前后結果對照:應部分園友建議,更為直觀
- 整體orc結果:
- 具體orc結果:
【篇末】:程序中使用遍歷文件,文件夾清空處理,文件的刪除,文件的查找,文件夾的判空,重點在於圖片的OneNote處理等操作,完成了批處理。可以自動執行批文件夾中圖片,生成新的文本文件與圖片名一致。現在不足之處,對文件夾的文件類型篩選為執行圖片類型沒有處理,容錯不足,這個自己用文件放入純圖片可以,另外有時候進程處理不穩定,估計加入進度條原因。待版本2再做改進。下一節介紹文本文件處理入庫(Oracle)。特別wpf中DataGrid的使用,如何在wpf中完成分頁,簡單的集合類型數據庫分頁可以,但是數據庫連接如何分頁?