广州长隆熊猫酒店工程电视工程机能接收网络电视吗

关于ORC验证码识别可以看本博客的另一篇文章
本文是对tesseract-ocr 使用的进一步技术升级说明,使用默认的识别库识别率比较低怎么办?
不用着急,tesseract-ocr本身的工具中提供了使用你提供的素材进行人工修正以提高识别率的方法。下面我们就来看一下。
1&&& 下载并安装版本的
2&&&& 如果你的训练素材是很多张非格式的图片,首先要做的事情就是将这么图片合并(个人觉得素材越多,基本每个字母和数字都覆盖了训练出来的识别率比较好)
下载这个工具:
首先进行到的转换,这个用自带的画图就可以。然后使用进行多张的。
3&&&&& 。在所在的目录下打开一个命令行,输入
4&&&&&& 使用打开文件,需要记住的是第步生成的要和这个文件同在一个目录下。逐个校正文字,后保存。
下载工具进行每个自的纠正(注意有逐页进行纠正)
5&&&&&& 。输入命令:
补充关于命名格式解释:
Make Box Files
For the next step below, Tesseract needs a 'box' file to go with each training image. The box file is a text file that lists the characters in the training image, in order, one per line, with the coordinates of the bounding box around the image.
Tesseract 3.0 has a mode in which it will output a text file of the required format, but if the character set is different to its current training, it will naturally have the text incorrect. So the key process here is to manually edit the file to put the correct
characters in it.
Run Tesseract on each of your training images using this command line:
tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox
6&&&&& 。输入命令:
7&&&&&&& 新建文件。如果是版本,那么需要在目录下新建一个名字为的文件,并且输入文本(这里的就是的中间字段)
8&&&&& 。输入命令:
9&&&&&&&& 此时,在目录下应该生成若干个文件了,把这几个文件加上前缀。然后输入命令:
必须确定的是1、3、4、5、13行的数据不是-1,那么一个新的字典就算生成了。
此时目录下“selfverify.traineddata”的文件拷贝到tesseract程序目录下的“tessdata”目录。
以后就可以使用该该字典来识别了,例如:
通过训练出来的新语言,识别率提高了不少。
阅读(...) 评论()查看: 1710|回复: 2
请教Tesseract-OCR技术是字符识别技术中的哪一类
请教Tesseract-OCR技术属于下面的那一种技术
统计字符识别、机构字符识别、神经网络字符识别
好像是神经网络吧 里面有神经网络训练的模块
好像是神经网络吧 里面有神经网络训练的模块
Powered by下次自动登录
现在的位置:
& 综合 & 正文
常用的两种ORC 验证码 识别方法及实践感言
用Asprise的OCR包,处理验证码。java ORC 图片中文识别tesseract-ocr 识别码库训练方法
来由,这几天想做坏事,从一个网站上批量查询东西,但是无奈每次查询都有验证码,所以就搜索到了以上几篇
基本介绍:
1、Asprise,是个收费的OCR软件,但是网络的力量是无穷的,可以下载到破解的
关于 Asprise的使用例子可以参考:
2、Tesseract,该技术是google的一个源码项目,出自HP()
、首先安装
、安装好了以后你需要哪种语言或者类别的识别支持,到官网的中去查找插件,并放置在安装目录的文件夹下(如果需要中文支持,下载的中文包
,解压缩之后复制到的安装目录文件夹之下)见图
、安装好以后,等等都可以进行的转换操作,我们就以命令行下为例
详解即为安装目录下的执行文件
即为你需要解析的图片文件
即为你需要将结果保存的文件名
即为以英文字母模式进行解析
即为以单行字母解析
关于Tesseract的JAVA中的使用说明可以参考代码:
综合使用以后,发现这2者效果一般,识别率很低,
原因很简单,大多数网站的验证码都加入不同程度的噪音,以防止OCR软件的自动分析。
一文中谈到了进行一些图像去噪处理的简单方法,但是效果也一般,不过这的确提供了一些思路,只要有好的噪点处理方法肯定会提高OCR识别率。
package com.
import java.awt.Graphics2D;
import java.awt.color.ColorS
import java.awt.geom.AffineT
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedI
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorM
import java.awt.image.MemoryImageS
import java.awt.image.PixelG
* 图像过滤,增强OCR识别成功率
public class ImageFilter {
private BufferedI
private int iw,
private int[]
public ImageFilter(BufferedImage image) {
this.image =
iw = image.getWidth();
ih = image.getHeight();
pixels = new int[iw * ih];
/** 图像二值化 */
public BufferedImage changeGrey() {
PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
pg.grabPixels();
} catch (InterruptedException e) {
e.printStackTrace();
// 设定二值化的域值,默认值为100
int grey = 100;
// 对图像进行二值化处理,Alpha值保持不变
ColorModel cm = ColorModel.getRGBdefault();
for (int i = 0; i & iw * i++) {
int red, green,
int alpha = cm.getAlpha(pixels[i]);
if (cm.getRed(pixels[i]) & grey) {
red = 255;
if (cm.getGreen(pixels[i]) & grey) {
green = 255;
green = 0;
if (cm.getBlue(pixels[i]) & grey) {
blue = 255;
pixels[i] = alpha && 24 | red && 16 | green && 8 |
// 将数组中的象素产生一个图像
return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih, pixels, 0, iw));
/** 提升清晰度,进行锐化 */
public BufferedImage sharp() {
PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
pg.grabPixels();
} catch (InterruptedException e) {
e.printStackTrace();
// 象素的中间变量
int tempPixels[] = new int[iw * ih];
for (int i = 0; i & iw * i++) {
tempPixels[i] = pixels[i];
// 对图像进行尖锐化处理,Alpha值保持不变
ColorModel cm = ColorModel.getRGBdefault();
for (int i = 1; i & ih - 1; i++) {
for (int j = 1; j & iw - 1; j++) {
int alpha = cm.getAlpha(pixels[i * iw + j]);
// 对图像进行尖锐化
int red6 = cm.getRed(pixels[i * iw + j + 1]);
int red5 = cm.getRed(pixels[i * iw + j]);
int red8 = cm.getRed(pixels[(i + 1) * iw + j]);
int sharpRed = Math.abs(red6 - red5) + Math.abs(red8 - red5);
int green5 = cm.getGreen(pixels[i * iw + j]);
int green6 = cm.getGreen(pixels[i * iw + j + 1]);
int green8 = cm.getGreen(pixels[(i + 1) * iw + j]);
int sharpGreen = Math.abs(green6 - green5) + Math.abs(green8 - green5);
int blue5 = cm.getBlue(pixels[i * iw + j]);
int blue6 = cm.getBlue(pixels[i * iw + j + 1]);
int blue8 = cm.getBlue(pixels[(i + 1) * iw + j]);
int sharpBlue = Math.abs(blue6 - blue5) + Math.abs(blue8 - blue5);
if (sharpRed & 255) {
sharpRed = 255;
if (sharpGreen & 255) {
sharpGreen = 255;
if (sharpBlue & 255) {
sharpBlue = 255;
tempPixels[i * iw + j] = alpha && 24 | sharpRed && 16 | sharpGreen && 8 | sharpB
// 将数组中的象素产生一个图像
return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih, tempPixels, 0, iw));
/** 中值滤波 */
public BufferedImage median() {
PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
pg.grabPixels();
} catch (InterruptedException e) {
e.printStackTrace();
// 对图像进行中值滤波,Alpha值保持不变
ColorModel cm = ColorModel.getRGBdefault();
for (int i = 1; i & ih - 1; i++) {
for (int j = 1; j & iw - 1; j++) {
int red, green,
int alpha = cm.getAlpha(pixels[i * iw + j]);
// int red2 = cm.getRed(pixels[(i - 1) * iw + j]);
int red4 = cm.getRed(pixels[i * iw + j - 1]);
int red5 = cm.getRed(pixels[i * iw + j]);
int red6 = cm.getRed(pixels[i * iw + j + 1]);
// int red8 = cm.getRed(pixels[(i + 1) * iw + j]);
// 水平方向进行中值滤波
if (red4 &= red5) {
if (red5 &= red6) {
red = red5;
if (red4 &= red6) {
red = red6;
red = red4;
if (red4 & red6) {
red = red4;
if (red5 & red6) {
red = red6;
red = red5;
// int green2 = cm.getGreen(pixels[(i - 1) * iw + j]);
int green4 = cm.getGreen(pixels[i * iw + j - 1]);
int green5 = cm.getGreen(pixels[i * iw + j]);
int green6 = cm.getGreen(pixels[i * iw + j + 1]);
// int green8 = cm.getGreen(pixels[(i + 1) * iw + j]);
// 水平方向进行中值滤波
if (green4 &= green5) {
if (green5 &= green6) {
green = green5;
if (green4 &= green6) {
green = green6;
green = green4;
if (green4 & green6) {
green = green4;
if (green5 & green6) {
green = green6;
green = green5;
// int blue2 = cm.getBlue(pixels[(i - 1) * iw + j]);
int blue4 = cm.getBlue(pixels[i * iw + j - 1]);
int blue5 = cm.getBlue(pixels[i * iw + j]);
int blue6 = cm.getBlue(pixels[i * iw + j + 1]);
// int blue8 = cm.getBlue(pixels[(i + 1) * iw + j]);
// 水平方向进行中值滤波
if (blue4 &= blue5) {
if (blue5 &= blue6) {
blue = blue5;
if (blue4 &= blue6) {
blue = blue6;
blue = blue4;
if (blue4 & blue6) {
blue = blue4;
if (blue5 & blue6) {
blue = blue6;
blue = blue5;
pixels[i * iw + j] = alpha && 24 | red && 16 | green && 8 |
// 将数组中的象素产生一个图像
return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih, pixels, 0, iw));
/** 线性灰度变换 */
public BufferedImage lineGrey() {
PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
pg.grabPixels();
} catch (InterruptedException e) {
e.printStackTrace();
// 对图像进行进行线性拉伸,Alpha值保持不变
ColorModel cm = ColorModel.getRGBdefault();
for (int i = 0; i & iw * i++) {
int alpha = cm.getAlpha(pixels[i]);
int red = cm.getRed(pixels[i]);
int green = cm.getGreen(pixels[i]);
int blue = cm.getBlue(pixels[i]);
// 增加了图像的亮度
red = (int) (1.1 * red + 30);
green = (int) (1.1 * green + 30);
blue = (int) (1.1 * blue + 30);
if (red &= 255) {
red = 255;
if (green &= 255) {
green = 255;
if (blue &= 255) {
blue = 255;
pixels[i] = alpha && 24 | red && 16 | green && 8 |
// 将数组中的象素产生一个图像
return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih, pixels, 0, iw));
/** 转换为黑白灰度图 */
public BufferedImage grayFilter() {
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp op = new ColorConvertOp(cs, null);
return op.filter(image, null);
/** 平滑缩放 */
public BufferedImage scaling(double s) {
AffineTransform tx = new AffineTransform();
tx.scale(s, s);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
return op.filter(image, null);
public BufferedImage scale(Float s) {
int srcW = image.getWidth();
int srcH = image.getHeight();
int newW = Math.round(srcW * s);
int newH = Math.round(srcH * s);
// 先做水平方向上的伸缩变换
BufferedImage tmp=new BufferedImage(newW, newH, image.getType());
Graphics2D g= tmp.createGraphics();
for (int x = 0; x & newW; x++) {
g.setClip(x, 0, 1, srcH);
// 按比例放缩
g.drawImage(image, x - x * srcW / newW, 0, null);
// 再做垂直方向上的伸缩变换
BufferedImage dst = new BufferedImage(newW, newH, image.getType());
g = dst.createGraphics();
for (int y = 0; y & newH; y++) {
g.setClip(0, y, newW, 1);
// 按比例放缩
g.drawImage(tmp, 0, y - y * srcH / newH, null);
这个是另外一个OCR工具
提高验证码识别率
&&&&推荐文章:
【上篇】【下篇】Tesseract-OCR字符训练工具及方法
Tesseract-OCR
Tesseract-OCR训练工具
更正训练步骤序号
最近参加了一个人工智能的竞赛,主要完成的工作是扫描识别广告牌、包装盒上的文字,包括中文、英文、和数字,后续会有些编辑、翻译的功能。
先看几张要识别的样张:
第一张是比较正规的图片,下面主要以它们为例讲解这个工具的实现思路。
网上关于tesseract-OCR的训练工具都是清一色的jTessBoxEditor,但这工具对于中文字符的训练太过繁琐,特别是像这种广告牌,有背景,有艺术字,根本就找不到对应的box,就算找到了还要自己人工输入打标签,而且工具对utf-8格式的汉字还不能正常显示。
为了一劳永逸的解决这种问题,花了几天工夫写了个训练工具,虽然还是会有大量手工的操作,但是这些步骤都是必不可少的,已经找不到太好的方法省掉了。
首先看下工具的输入和输出:
输入是大量的从广告素材中剪切下来的图片:
输出是tesseract-OCR需要的box和tif文件:
Box文件中是标签和位置信息:
Tif中是归一化后的字符信息:
用jTessBoxEditor器打开这个box,观察可看出结果非常好:
有了这个box文件和tif文件,接下来就能用tesseract进行训练了,训练步骤网上有很多,下面主要说下这个工具的实现思路,说穿了就一文不值。
这个工具分成两个阶段。
第一阶段从广告牌图片中切出包含文字的部分,对于中文只能一行一行的切,而对于英文可以多行多行的切,这是因为两者使用的提取算法不一样导致的。这部分需要手工去操作。
第一阶段输出的结果是二值化后的黑底白字的单个字符块:
第二个阶段就是以这些黑底白字的字符作为输入,需要给每个字符打上标签,即以这个字符开头重命名图片,第一个字符就代表了这个字符的标签。输出就是前文提到的box文件和tiff文件。这一阶段也是需要人工费时的去做,一方面需要一个一个正确的打标签,一方面对于有些第一阶段切下来的字符,效果不好的要去掉。
下面来分析,拿到一张图片,比如:
这张图片,是怎么样把字符切割开来并写入到box文件和tif图片里面的?
这个过程涉及到了简单的图像处理,需要用到openCV库。
首先把图片进行灰度化、均衡化,最后进行大津阀值二值化:
二值化的结果统一转化成黑底白字。
下面要把文中的字符切割开来,对于英文和数字,直接取轮廓操作,并取最小外接矩形就行。对于中文,由于存在上下、左右结构,轮廓不连续,需要特殊处理。
处理步骤说来也简单,通过统计图片中每列像素为1的个数,从左到右扫描,遇到像素为1的个数大于某个值(我设为3个),就假定为一个字符的左边界;遇到像素为1的个数小于等于某个值(我设为3个),就假定为一个字符的右边界;字符的上下边界还是使用原来图片的边界。遇到左右结构的汉字时,这样可能会把偏旁部首分开,因此需要把前面个字符的右边界和后面个字符的左边界间隔小于某个阀值(2或3像素)的合并成一个字符。
接着遍历每个确定好左右边界的字符,从上到下扫描确定字符的上边界,从下到上扫描确定字符的下边界。也是通过统计像素为1的个数来确定。
边界确定好后,通过openCV取出ROI区域并输出即可,作为第一阶段的结果,如下图所示:
对于第二阶段,给上面第一阶段输出的字符打好标签并后怎么输出tesseract训练需要的box和tif文件?
先分析box文件的内容,第一列指定了该字符的标签,后面数字指定该字符在tif图片中的坐标位置和长宽信息。因而工具要做的工作就是,每当输出一个字符在tif图片中,就同时输出该字符的信息在box文件中。需要注意的是,第一阶段输出的字符是黑底白字,需要把它转为白底黑字输出到tif图片中,效果更好。另外,第一阶段的字符标签在VS中文环境中使用的是ansi编码,输出到box文件中的时候需转换为utf-8编码。
Tesseract训练及合并字库
利用工具分别得到中文、英文(包含数字)的box和tif文件,分别命名为:
len.ennormal.exp0.tif、len.ennormal.exp0.box、normal.exp0.tif、normal.exp0.box。
在pc上安装好tesseract-OCR,并切换到工作目录,按下列步骤进行训练即可得到合并的字库。
进行box train,得到tr特征文件
tesseract len.ennormal.exp0.tif
len.ennormal.exp0
normal.exp0.tif
normal.exp0
可以看到英文和中文分别多出了len.ennormal.exp0.tr
normal.exp0.tr特征文件。
2.获取中英文的字符集
unicharset_extractor
len.ennormal.exp0.box
normal.exp0.box
3.定义字体特征文件
在目录下新建一个名字为“font_properties”的文件,并且输入文本 :
表示中英文字体文件,其中1表示为粗体。
4.聚集字符特征(inttemp、pffmtable、normproto)
mftraining –F font_properties
-U unicharset len.ennormal.exp0.normal.exp0.tr
5.Clustering,产生字符形状正常化特征文件normproto
cntraining
len.ennormal.exp0.tr
normal.exp0.tr
6.合并训练文件
此时,在目录下应该生成若干个文件了,把unicharset, inttemp, normproto, pffmtable这四个文件加上前缀“lshao.”(可任意)。然后 合并训练文件
输入命令:
combine_tessdata
注意箭头所指的行不为-1,即代表训练成功。
把训练好的lshao.traineddata压缩成zip格式并放到android工程的assets目录中即可。
最后识别结果还是不尽人意,猜测是缺少了进行图像预处理的过程。
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?

我要回帖

更多关于 网络电视接收器 的文章

 

随机推荐