ocr.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import common from '../../utils/util';
  2. import main from '../../utils/main';
  3. const app = getApp();
  4. Page({
  5. data: {
  6. Menu:[],
  7. },
  8. onLoad: function (options) {
  9. },
  10. onShow:function(){
  11. var that = this;
  12. that.setData({
  13. Menu:[{Name:"相册",CSS:"",Fun:"chooseImage"},{Name:"拍照",CSS:"Selected",Fun:"retake"}]
  14. });
  15. },
  16. retake() {
  17. this.data.Menu[0].CSS="";
  18. this.data.Menu[1].CSS="Selected";
  19. this.setData({
  20. Menu:this.data.Menu,
  21. });
  22. },
  23. // 拍照识别
  24. takePhoto() {
  25. const ctx = wx.createCameraContext();
  26. ctx.takePhoto({
  27. quality: 'high',
  28. success: (res) => {
  29. this.setData({
  30. imageUrl: res.tempImagePath,
  31. cameraActive: false,
  32. showCanvas: true
  33. })
  34. this.performOCR(res.tempImagePath)
  35. },
  36. fail: (err) => {
  37. console.error('拍照失败:', err)
  38. wx.showToast({
  39. title: '拍照失败,请重试',
  40. icon: 'none'
  41. })
  42. }
  43. })
  44. },
  45. chooseImage() {
  46. this.data.Menu[0].CSS="Selected";
  47. this.data.Menu[1].CSS="";
  48. this.setData({
  49. Menu:this.data.Menu,
  50. });
  51. wx.chooseMedia({
  52. count: 1,
  53. mediaType: ['image'],
  54. sourceType: ['album'],
  55. success: (res) => {
  56. const tempFilePath = res.tempFiles[0].tempFilePath
  57. this.setData({
  58. imageUrl: tempFilePath,
  59. cameraActive: false,
  60. showCanvas: true
  61. })
  62. this.performOCR(tempFilePath)
  63. },
  64. fail: (err) => {
  65. console.error('选择图片失败:', err)
  66. wx.showToast({
  67. title: '选择图片失败',
  68. icon: 'none'
  69. })
  70. }
  71. })
  72. },
  73. // 加强版的OCR识别方法
  74. async performOCR(imagePath) {
  75. if (!imagePath) {
  76. console.error('图片路径无效')
  77. }
  78. wx.showLoading({ title: '识别中...', mask: true })
  79. try {
  80. // 1. 压缩图片
  81. const compressed = await new Promise((resolve, reject) => {
  82. wx.compressImage({
  83. src: imagePath,
  84. quality: 70,
  85. success: resolve,
  86. fail: () => resolve({ tempFilePath: imagePath })
  87. })
  88. })
  89. //console.log("1");
  90. // 2. 转换为base64
  91. const fileRes = await new Promise((resolve, reject) => {
  92. wx.getFileSystemManager().readFile({
  93. filePath: compressed.tempFilePath,
  94. encoding: 'base64',
  95. success: resolve,
  96. fail: reject
  97. })
  98. })
  99. //console.log("2");
  100. // 3. 调用云函数(添加超时处理)
  101. let postData={ ImageBase64: `data:image/jpeg;base64,${fileRes.data}` };
  102. let url = common.Encrypt("OCRImageData");
  103. url=app.globalData.serverUrl+url;
  104. //console.log("url:"+url);
  105. const cloudRes = await new Promise((resolve, reject) => {
  106. wx.request({
  107. url: url,
  108. method: "POST",
  109. data: postData,
  110. success: resolve,
  111. fail: reject,
  112. })
  113. });
  114. //console.log("3");
  115. // 4. 验证返回结果
  116. if (!cloudRes || !cloudRes.data.result) {
  117. throw new Error('无效的响应格式')
  118. }
  119. //console.log("4");
  120. if (!cloudRes.data.result) {
  121. throw new Error(cloudRes.data.result.message || '识别服务返回空数据')
  122. }
  123. // 5. 处理识别结果
  124. const texts = cloudRes.data.result.TextDetections.map(item => ({
  125. text: item.DetectedText || '未识别到文字',
  126. pos: this.convertPosition(item.ItemPolygon || { Points: [] })
  127. })).filter(item => item.DetectedText !== '未识别到文字')
  128. //console.log("5");
  129. if (texts.length === 0) {
  130. throw new Error('未识别到有效文字')
  131. }
  132. // 6.提取英文单词
  133. const engTexts=this.extractEnglishWords(texts);
  134. let arr=[];
  135. for(var i=0;i<engTexts.length;i++){
  136. let obj={};
  137. obj.Word=engTexts[i];
  138. obj.Selected=0;
  139. arr.push(obj);
  140. }
  141. app.globalData.OCRWords=engTexts;
  142. wx.navigateTo({
  143. url: "./selectword",
  144. });
  145. } catch (err) {
  146. console.error('OCR处理失败:', err)
  147. wx.showToast({
  148. title: err.message || '识别失败',
  149. icon: 'none',
  150. duration: 3000
  151. })
  152. } finally {
  153. wx.hideLoading()
  154. }
  155. },
  156. // 加强坐标转换
  157. convertPosition(polygon) {
  158. try {
  159. const points = polygon.Points || []
  160. if (points.length === 0) {
  161. return { x: 50, y: 50, width: 200, height: 30 }
  162. }
  163. const xs = points.map(p => p.X || 0)
  164. const ys = points.map(p => p.Y || 0)
  165. return {
  166. x: Math.min(...xs),
  167. y: Math.min(...ys),
  168. width: Math.max(...xs) - Math.min(...xs),
  169. height: Math.max(...ys) - Math.min(...ys)
  170. }
  171. } catch (e) {
  172. return { x: 50, y: 50, width: 200, height: 30 }
  173. }
  174. },
  175. // 提取英语单词的函数 - 增强版
  176. extractEnglishWords(texts) {
  177. console.group('英语单词提取');
  178. const words = new Set();
  179. texts.forEach(item => {
  180. const text = item.text;
  181. console.log('处理文本:', text);
  182. // 改进的正则表达式,能更好处理中英文混合文本
  183. const wordRegex = /(?:^|\s|[\u4e00-\u9fa5])([A-Za-z]{2,}(?:['’-][A-Za-z]+)*)(?=$|\s|[\u4e00-\u9fa5])/g;
  184. let match;
  185. while ((match = wordRegex.exec(text)) !== null) {
  186. const word = match[1];
  187. console.log('匹配到单词:', word);
  188. // 验证单词有效性
  189. if (/^[A-Za-z'’-]+$/.test(word)) {
  190. const lowerWord = word.toLowerCase();
  191. words.add(lowerWord);
  192. console.log('添加单词:', lowerWord);
  193. }
  194. }
  195. });
  196. //const result = Array.from(words).sort();
  197. const result=Array.from(words);
  198. console.log('提取结果:', result);
  199. console.groupEnd();
  200. return result;
  201. },
  202. onShareAppMessage: function () {
  203. return {
  204. title: app.globalData.ShareTitle,
  205. path: app.globalData.SharePath + '?UserID=' + app.globalData.userInfo.UserID,
  206. imageUrl: app.globalData.ShareImage,
  207. }
  208. },
  209. })