Onenote实现OCR识别图片
OCR识别推荐两个软件:
1. Tesseract:一个开源的,由谷歌维护的OCR软件。
2. Onenote:微软Office附带或者可以自己独立安装。
3. ONOM:别人封装的onenote api接口
这次讲Onenote实现的OCR识别。github地址:https://github.com/everywan/Extraction.OCR
注:2010版及其以后版本OCR实现方式类似:office将其转换为特定xm格式,然后提取想要的节点就ok了;onenote2007识别比较简单:通过MODI API接口直接之别。
我这里是实现了 office2007和office2010的ocr识别函数。
源程序下载:坚果云连接(.net4.5,vs2017RC。本机环境:windows10)
1 public class ExtractionOCR
2 {
3 #region
4 private static readonly ExtractionOCR instance = new ExtractionOCR();
5 public static ExtractionOCR Instance { get { return instance; } }
6 public static string section_path { get; set; }
7 public static int waitTime = 3 * 1000;
8 #endregion
9 /// <summary>
10 /// office2007 MODI组件OCR识别
11 /// </summary>
12 /// <param name="imgPath"></param>
13 /// <returns></returns>
14 public string Ocr_2007(string imgPath)
15 {
16 try
17 {
18 var imgType = imgPath.Substring(imgPath.Length - 3);
19 var data = File.ReadAllBytes(imgPath);
20 string imgInfo = "";
21 int i = 0;
22 var localimgFile = AppDomain.CurrentDomain.BaseDirectory + @"\" + Guid.NewGuid().ToString() + "." + imgType;
23 while (!imgInfo.Equals("转换成功") && i < 3)
24 {
25 ++i;
26 imgInfo = this.GetBase64(data, imgType, localimgFile);
27 }
28 MODI.Document doc = new MODI.Document();
29 doc.Create(localimgFile);
30 MODI.Image image;
31 MODI.Layout layout;
32 doc.OCR(MODI.MiLANGUAGES.miLANG_CHINESE_SIMPLIFIED, true, true);
33 StringBuilder sb = new StringBuilder();
34 image = (MODI.Image)doc.Images[0];
35 layout = image.Layout;
36 sb.Append(layout.Text);
37 doc = null;
38 var localFilePath = AppDomain.CurrentDomain.BaseDirectory + @"\" + Guid.NewGuid().ToString() + ".txt";
39 File.WriteAllText(localFilePath, sb.ToString());
40 Console.WriteLine(sb.ToString());
41 return localFilePath;
42 }
43 catch (Exception e)
44 {
45 File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + @"\log.txt", e.ToString());
46 return "";
47 }
48 finally
49 {
50 GC.Collect();
51 }
52 }
53 /// <summary>
54 /// onenote 2010,注意需要先在onenote中创建笔记本,并且将至转换为onenote2007格式
55 /// 推荐使用onenote2016(个人版即可),API与2010类似,(去掉XMLSchema.xs2007参数即可)其他可参考API参数命名。
56 /// 注意1:一定要将dll属性中的“嵌入互操作类型”属性关闭
57 /// </summary>
58 /// <param name="imgPath"></param>
59 /// <returns></returns>
60 public string Ocr_2010(string imgPath)
61 {
62 try
63 {
64 #region 确定section_path存在
65 section_path = @"C:\Users\zhensheng\Desktop\打杂\ocr\ocr.one";
66 if (string.IsNullOrEmpty(section_path))
67 {
68 Console.WriteLine("请先建立笔记本");
69 File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + @"\log.txt", "需要先在onenote中创建笔记本,并且将至转换为onenote2007格式,且将.one文件得路径赋值给section_path");
70 return "";
71 }
72 #endregion
73 #region 准备数据
74 //后缀
75 var imgType = Path.GetExtension(imgPath);
76 imgPath = imgPath.Replace(".", "");
77 var data = File.ReadAllBytes(imgPath);
78 //根据大小确定重试次数
79 int fileSize = Convert.ToInt32(data.Length / 1024 / 1024); // 文件大小 单位M
80 string guid = Guid.NewGuid().ToString();
81 string pageID = "{" + guid + "}{1}{B0}"; // 格式 {guid}{tab}{??}
82 string pageXml;
83 XNamespace ns;
84 var onenoteApp = new Microsoft.Office.Interop.OneNote.Application(); //onenote提供的API
85 if (onenoteApp == null)
86 {
87 File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + @"\log.txt", "Microsoft.Office.Interop.OneNote.Application()创建失败");
88 return "";
89 }
90 //重试使用
91 XmlNode xmlNode;
92 int retry = 0;
93 #endregion
94 do
95 {
96 #region 创建页面并返回pageID
97 string sectionID;
98 onenoteApp.OpenHierarchy(section_path, null, out sectionID, CreateFileType.cftSection);
99 onenoteApp.CreateNewPage(sectionID, out pageID);
100 #endregion
101 #region 获取onenote页面xml结构格式
102 string notebookXml;
103 onenoteApp.GetHierarchy(null, HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2007);
104 var doc = XDocument.Parse(notebookXml);
105 ns = doc.Root.Name.Namespace;
106 #endregion
107 #region 将图片插入页面
108 Tuple<string, int, int> imgInfo = this.GetBase64(data, imgType);
109 var page = new XDocument(new XElement(ns + "Page",
110 new XElement(ns + "Outline",
111 new XElement(ns + "OEChildren",
112 new XElement(ns + "OE",
113 new XElement(ns + "Image",
114 new XAttribute("format", imgType), new XAttribute("originalPageNumber", "0"),
115 new XElement(ns + "Position",
116 new XAttribute("x", "0"), new XAttribute("y", "0"), new XAttribute("z", "0")),
117 new XElement(ns + "Size",
118 new XAttribute("width", imgInfo.Item2), new XAttribute("height", imgInfo.Item3)),
119 new XElement(ns + "Data", imgInfo.Item1)))))));
120 page.Root.SetAttributeValue("ID", pageID);
121 onenoteApp.UpdatePageContent(page.ToString(), DateTime.MinValue, XMLSchema.xs2007);
122 #endregion
123 #region 通过轮询访问获取OCR识别的结果,轮询超时次数为6次
124 int count = 0;
125 do
126 {
127 System.Threading.Thread.Sleep(waitTime * (fileSize > 1 ? fileSize : 1)); // 小于1M的都默认1M
128 onenoteApp.GetPageContent(pageID, out pageXml, PageInfo.piBinaryData, XMLSchema.xs2007);
129 }
130 while (pageXml == "" && count++ < 6);
131 #endregion
132 #region 删除页面
133 onenoteApp.DeleteHierarchy(pageID, DateTime.MinValue);
134 //onenoteApp = null;
135 #endregion
136 #region 从xml中提取OCR识别后的文档信息,然后输出到string中
137 XmlDocument xmlDoc = new XmlDocument();
138 xmlDoc.LoadXml(pageXml);
139 XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
140 nsmgr.AddNamespace("one", ns.ToString());
141 xmlNode = xmlDoc.SelectSingleNode("//one:Image//one:OCRText", nsmgr);
142 #endregion
143 }
144 //如果OCR没有识别出信息,则重试三次(个人测试2010失败率为0.2~0.3)
145 while (xmlNode == null && retry++ < 3);
146 if (xmlNode == null)
147 {
148 File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + @"\log.txt", "OCR没有识别出值");
149 return "";
150 }
151 var localFilePath = AppDomain.CurrentDomain.BaseDirectory + @"\" + Guid.NewGuid().ToString() + ".txt";
152 File.WriteAllText(localFilePath, xmlNode.InnerText.ToString());
153 Console.WriteLine(xmlNode.InnerText.ToString());
154 return localFilePath;
155 }
156 catch (Exception e)
157 {
158 File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + @"\log.txt", e.ToString());
159 return "";
160 }
161 }
162 private string GetBase64(byte[] data, string imgType, string filePath)
163 {
164 using (MemoryStream ms = new MemoryStream())
165 {
166 MemoryStream ms1 = new MemoryStream(data);
167 Bitmap bp = (Bitmap)Image.FromStream(ms1);
168 switch (imgType.ToLower())
169 {
170 case "jpg":
171 bp.Save(ms, ImageFormat.Jpeg);
172 break;
173 case "jpeg":
174 bp.Save(ms, ImageFormat.Jpeg);
175 break;
176 case "gif":
177 bp.Save(ms, ImageFormat.Gif);
178 break;
179 case "bmp":
180 bp.Save(ms, ImageFormat.Bmp);
181 break;
182 case "tiff":
183 bp.Save(ms, ImageFormat.Tiff);
184 break;
185 case "png":
186 bp.Save(ms, ImageFormat.Png);
187 break;
188 case "emf":
189 bp.Save(ms, ImageFormat.Emf);
190 break;
191 default:
192 return "不支持的图片格式。";
193 }
194 byte[] buffer = ms.ToArray();
195 File.WriteAllBytes(filePath, buffer);
196 ms1.Close();
197 ms.Close();
198 return "转换成功";
199 //return new Tuple<string, int, int>(Convert.ToBase64String(buffer), bp.Width, bp.Height);
200 }
201 }
202 private Tuple<string, int, int> GetBase64(byte[] data, string imgType)
203 {
204 using (MemoryStream ms = new MemoryStream())
205 {
206 MemoryStream ms1 = new MemoryStream(data);
207 Bitmap bp = (Bitmap)Image.FromStream(ms1);
208 switch (imgType.ToLower())
209 {
210 case "jpg":
211 bp.Save(ms, ImageFormat.Jpeg);
212 break;
213 case "jpeg":
214 bp.Save(ms, ImageFormat.Jpeg);
215 break;
216 case "gif":
217 bp.Save(ms, ImageFormat.Gif);
218 break;
219 case "bmp":
220 bp.Save(ms, ImageFormat.Bmp);
221 break;
222 case "tiff":
223 bp.Save(ms, ImageFormat.Tiff);
224 break;
225 case "png":
226 bp.Save(ms, ImageFormat.Png);
227 break;
228 case "emf":
229 bp.Save(ms, ImageFormat.Emf);
230 break;
231 default:
232 return new Tuple<string, int, int>("不支持的图片格式。", 0, 0);
233 }
234 byte[] buffer = ms.ToArray();
235 ms1.Close();
236 ms.Close();
237 return new Tuple<string, int, int>(Convert.ToBase64String(buffer), bp.Width, bp.Height);
238 }
239 }
240 }
注意:
1. office2007需要安装office sp2补丁。
2. 谨记 关闭onenote.dll的 嵌入互操作类型 关闭
3. 如果是在服务器上使用office/onenote,需要开启 桌面体验 功能。
4. 如果是在服务器上使用onenote 2007,需要注意的是该组件是32位的,也就是说直接调用这个接口的必须是32位程序。
5. 如果是在服务器上使用onenote 2010,出现了(Retrieving the COM class factory for component with CLSID {D7FAC39E-7FF1-49AA-98CF-A1DDD316337E} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)))这个异常,请在调用此dll的服务登陆身份修改为管理员账号,并且用此账号创建onenote笔记本,另外,本示例代码需要笔记本格式为onenote2007
a.
6. 如果有其他异常,参阅微软文档: 错误代码
参考:
3. Creating OneNote 2010 Extensions with the OneNote Object Model
4. 64位进程调用32位dll的解决方法 / 程序64位化带来的问题和思考
5. ONOM :封装的onenote api类
Onenote实现OCR识别图片的更多相关文章
- 【转】Python OCR识别图片验证码
转载自:博客 对于某些网站登录的时候,往往需要输入验证码才能实现登录.如果要爬虫这类网站,往往总会比这个验证码导致无法爬取数据.以下介绍一种比较折中的方法,也是比较可行的方法: 实现思想: 1.通过截 ...
- C++调用Asprise OCR识别图片
在一个识别软件中发现了Asprise OCR的"身影",上官网查了一下相关信息,发现功能挺强大的,识别印刷体应该不错,遗憾的是好像不能识别中文,不过不知道它对扭曲后的英文识别能力怎 ...
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结
篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇二:基于OneNote难点突破和批量识别
篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇四:关于OneNote入库处理以及审核
篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...
- 你知道OneNote的OCR功能吗?office lens为其增大威力,中文也识别
原文:[原创]你知道OneNote的OCR功能吗?office lens为其增大威力,中文也识别 OneNote提供了强大的从图片中取出文字的功能,大家只要装上了桌面版OneNote(本人用的2013 ...
- 以API方式调用C# dll,使用OneNote2013 sp1实现OCR识别本地图片
http://www.cnblogs.com/Charltsing/p/OneNoteOCRAPI.html OneNote2013 OCR API调用使用说明2019.4.17 使用说明:1.安装干 ...
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇三:批量处理后的txt文件入库处理
篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...
- 图片文字OCR识别-tesseract-ocr
帮助文件:https://github.com/tesseract-ocr/tesseract/blob/master/doc/tesseract.1.asc 下载地址:https://github. ...
随机推荐
- 适合普通大学生的 Java 后端开发学习路线
大家好,我是帅地. 接下来的一段时间,帅地会总结各种技术栈的学习路线,例如 Java 开发,C++ 开发,python 开发,前端开发等等,假如你没有明确的目标,或许可以按照我说的学习路线来学习一波, ...
- 数据结构和算法学习笔记十五:多路查找树(B树)
一.概念 1.多路查找树(multi-way search tree):所谓多路,即是指每个节点中存储的数据可以是多个,每个节点的子节点数也可以多于两个.使用多路查找树的意义在于有效降低树的深度,从而 ...
- python安全编程之指纹识别
什么是cms CMS是Content Management System的缩写,意为"内容管理系统",这是百度百科的解释,意思是相当于网站的建站模板,整个网站架构已经集成好了,只需 ...
- 总结开发中基于DevExpress的Winform界面效果
DevExpress是一家全球知名的控件开发公司, DevExpress 也特指此公司出品的控件集合或某系列控件或其中某控件.我们应用最为广泛的是基于Winform的DevExpress控件组,本篇随 ...
- OEM 刷新配置方法
一:设置>添加目标>配置自动搜索 二:主机上的目标>针对所选的主机 三:禁用调度 四:设置>添加目标>自动搜索结果 五:主机上的目标,搜索结果 六:删除 七:选择机器数据 ...
- netty系列之:文本聊天室
目录 简介 聊天室的工作流程 文本处理器 初始化ChannelHandler 真正的消息处理逻辑 总结 简介 经过之前的系列文章,我们已经知道了netty的运行原理,还介绍了基本的netty服务搭建流 ...
- SpringBoot开发十八-显示评论
需求介绍 显示评论,还是我们之前做的流程. 数据层:根据实体查询一页的评论数据,以及根据实体查询评论的数量 业务层:处理查询评论的业务,处理查询评论数量的业务 表现层:同时显示帖子详情数据时显示该帖子 ...
- pikachu Unsafe Fileupload
不安全的文件上传漏洞概述文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像.上传附件等等.当用户点击上传按钮后,后台会对上传的文件进行判断 比如是否是指定的类型.后缀名.大小等等, ...
- APP渗透测试之安卓APP抓包
之前说过一些信息搜集相关的东西(漏了APP没讲),按照渗透测试的完整流程,我作为测试,测个APP,也很合理吧 既然能用burpsuite测试web,那就能用burpsuite测试APP(有大佬自称用b ...
- vue3 自己做一个轻量级状态管理,带跟踪功能,知道是谁改的,还能定位代码。
上一篇 https://www.cnblogs.com/jyk/p/14706005.html 介绍了一个自己做的轻量级的状态管理,好多网友说,状态最重要的是跟踪功能,不能跟踪算啥状态管理? 因为vu ...