发布网友 发布时间:2022-04-22 04:34
共4个回答
热心网友 时间:2022-04-23 07:30
自己没有做过,但是有一种插件不知道能不能有用。Javascript图片文字识别插件JS-OCR,尽量找一些插件,效率要高一些。
热心网友 时间:2022-04-23 08:48
没有使用这种方法做过,但是可以使用ocr进行识别图片上的文字啊,在网上都有ocr文字识别软件的,安装一个就可以了,比如说迅捷ocr文字识别都是还不错的。
热心网友 时间:2022-04-23 10:22
自己认为啊猫图鹰app挺好用的,工作紧任务非常重点话一般都用它,主要是真的挺方便很实用,最主要的是还不收钱,免费的软件!现在这种关于文档的没有几个不收钱呢而且很好入手
热心网友 时间:2022-04-23 12:14
思路
实现一个算法,思路是最重要的,而实现不过是把思想转化为能够运行的代码。
简单地说,要进行文本识别,自然是拿图片的数据与文字的图形数据进行对比,找到与图片数据匹配程度最高的字符。
首先,先确定图片中文本所用的字体、字号、行距等信息,打开PhotoShop,确定了字体为微软雅黑,16像素,行距为24,Base文字的开始坐标为(8, 161)。
然后,确定要进行匹配的字库,Base编码中可能出现的字符为26个字母大小写、10个数字、加号、斜杠,但目测在图片中没有斜杠出现,因此字库应该为:
01234567abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+
接着,是确定如何判断字符是否匹配,由于只需要对字型进行匹配,因此颜色值对算法并无用处,因此将其灰度化(详见百度百科),并使用01数组表示,1代表该像素点落在此字符图形上,0反之,而如何确定该某个灰度值在数组中应该表示为0还是1,这个转换公式更是算法中的关键。
最后,将字型的灰度化数据与图片中文字部分的灰度化数据进行对比,将误差最小的字型作为匹配到的字符,然后进行下一个字符的匹配,直到图片中所有字符匹配完毕为止。
递归实现
详细的思路于代码注释中,个人觉得这样结合上下文更为容易理解(注:代码应运行于服务器环境,否则会出现跨域错误,代码行数虽多,但注释就占了大半,有兴趣可以耐心看完,图片资源于上方“写在前面”)。
<!doctype html><html lang="zh-CN"><head> <meta charset="UTF-8"> <title>文字识别</title></head><body> <canvas id="canvas" width="880" height="1500"></canvas> <script type="text/javascript"> var image = new Image(); image.onload = recognition; image.src = 'image.jpg'; function recognition(){ // 开始时间,用于计算耗时 var beginTime = new Date().getTime(); // 获取画布 var canvas = document.getElementById('canvas'); // 字符库 var letters = '01234567abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+'; // 字型数据 var letterData = {}; // 获取context var context = canvas.getContext('2d'); // 设置字体、字号 context.font = '16px 微软雅黑'; // 设置文字绘制基线为文字顶端 context.textBaseline = 'top'; // 一个循环获取字符库对应的字型数据 for(var i = 0; i < letters.length; ++i){ var letter = letters[i]; // 获取字符绘制宽度 var width = context.measureText(letter).width; // 绘制白色背景,与图片背景对应 context.fillStyle = '#fff'; context.fillRect(0, 0, width, 22); // 绘制文字,以获取字型数据 context.fillStyle = '#000'; context.fillText(letter, 0, 0); // 缓存字型灰度化0-1数据 letterData[letter] = { width : width, data : getBinary(context.getImageData(0, 0, width, 22).data) } // 清空该区域以获取下个字符字型数据 context.clearRect(0, 0, width, 22); } // console.log(letterData); // 绘制图片 context.drawImage(this, 0, 0); // 要识别的文字开始坐标 var x = beginX = 8; var y = beginY = 161; // 行高 var lineHeight = 24; // 递归次数 var count = 0; // 结果文本 var result = ''; // 递归开始 findLetter(beginX, beginY, ''); // 递归函数 function findLetter(x, y, str){ // 找到结果文本,则递归结束 if(result){ return; } // 递归次数自增1 ++ count; // console.log(str); // 队列,用于储存可能匹配的字符 var queue = []; // 循环匹配字符库字型数据 for(var letter in letterData){ // 获取当前字符宽度 var width = letterData[letter].width; // 获取该矩形区域下的灰度化0-1数据 var data = getBinary(context.getImageData(x, y, width, 22).data); // 当前字符灰度化数据与当前矩形区域下灰度化数据的偏差量 var deviation = 0; // 一个临时变量以确定是否到了行末 var isEmpty = true; // 如果当前矩形区域已经超出图片宽度,则进行下一个字符匹配 if(x + width > 440){ continue; } // 计算偏差 for(var i = 0, l = data.length; i < l; ++i){ // 如果发现存在的有效像素点,则确定未到行末 if(isEmpty && data[i]){ isEmpty = false; } // 不匹配的像素点,偏差量自增1 if(data[i] != letterData[letter].data[i]){ ++deviation; } } // 由于调试时是在猎豹浏览器下进行的,而不同浏览器下的绘图API表现略有不同 // 考虑到用Chrome的读者应该也不少,故简单地针对Chrome对偏差进行一点手动微调 // (好吧,我承认我是懒得重新调整getBinary方法的灰度化、0-1化公式=_=||) // 下面这段if分支在猎豹浏览器下可以删除 if(letter == 'F' || letter == 'E'){ deviation -= 6; } // 如果匹配完所有17行数据,则递归结束 if(y > beginY + lineHeight * 17){ result = str; break; } // 如果已经到了行末,重置匹配坐标 if(isEmpty){ x = beginX; y += lineHeight; str += '\n'; } // 如果偏差量与宽度的比值小于3,则纳入匹配队列中 // 这里也是算法中的关键点,怎样的偏差量可以纳入匹配队列中 // 刚开始是直接用绝对偏差量判断,当偏差量小于某个值的时候则匹配成功,但调试过程中发现不妥之处 // 字符字型较小的绝对偏差量自然也小,这样l,i等较小的字型特别容易匹配成功 // 因此使用偏差量与字型宽度的比值作为判断依据较为合理 // 而这个判断值3的确定也是难点之一,大了递归的复杂度会大为增长,小了很可能将正确的字符漏掉 if(deviation / width < 3){ queue.push({ letter : letter, width : width, deviation : deviation }); } } // 如果匹配队列不为空 if(queue.length){ // 对队列进行排序,同样是根据偏差量与字符宽度的比例 queue.sort(compare); // console.log(queue); // 从队头开始进行下一个字符的匹配 for(var i = 0; i < queue.length && ! result; ++i){ var item = queue[i]; // 下一步递归 findLetter(x + item.width, y, str + item.letter); } }else{ return false; } } // 递归结束 // 两个匹配到的字符的比较方法,用于排序 function compare(letter1, letter2){ return letter1.deviation / letter1.width - letter2.deviation / letter2.width; } // 图像数据的灰度化及0-1化 function getBinary(data){ var binaryData = []; for(var i = 0, l = data.length; i < l; i += 4){ // 尝试过三种方式 // 一种是正常的灰度化公式,无论系数如何调整都无法与绘制的文字字型数据很好地匹配 // binaryData[i / 4] = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) < 90; // 一种是自己是通过自己手动调整系数,结果虽然接近但总是不尽人意 // binaryData[i / 4] = data[i] < 250 && data[i + 1] < 203 && data[i + 2] < 203; // 最后使用了平均值,结果比较理想 binaryData[i / 4] = (data[i] + data[i + 1] + data[i + 2]) / 3 < 200; } return binaryData; } console.log(result); // 输出耗时 console.log(count, (new Date().getTime() - beginTime) / 1000 + ' s'); // 将文字绘制到图片对应位置上,以方便查看提取是否正确 context.drawImage(this, this.width, 0); var textArray = result.split('\n'); for(var i = 0; i < textArray.length; ++i){ context.fillText(textArray[i], this.width + beginX, beginY + lineHeight * i); } } </script></body></html>
运行环境
Win7 位,i3-3220 CPU 3.30 GHz,8G内存
运行结果
yv66vgAAADIAHQoABgAPCQAQABEIABIKABMAFAcAFQcAFgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAARtYWluAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEAClNvdXJjZUZpbGUBAAlNYWluLmphdmEMAAcACAcAFwwAGAAZAQBv5paw5rWq6Laz55CD6Zif5a6e5Yqb6LaF576k77yM6Zi15a656LGq5Y2O44CC5LmF5Luw5aSn5ZCN77yM5ZGo5pel5LiA5oiY77yM6L+Y5pyb5LiN6YGX5L2Z5Yqb77yM5LiN5ZCd6LWQ5pWZ44CCBwAaDAAbABwBAARNYWluAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAEACQALAAwAAQAJAAAAJQACAAEAAAAJsgACEgO2AASxAAAAAQAKAAAACgACAAAAAwAIAAQAAQANAAAAAgAO715 1.984 s(猎豹)772 15.52 s(Chrome)
(递归次数谷歌只比猎豹多几十,耗时却对了十几秒,看来猎豹真的比Chrome快?)