图片识别
Caffe,全称Convolutional Architecture for Fast Feature Embedding,是一个计算CNN相关算法的框架。
Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的linux机器上,也可实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
AWS
AWS BPM业务流程管理开发平台是一个易于部署和使用的业务流程管理基础平台软件,AWS平台提供了从业务流程梳理、建模到运行、监控、优化的全周期管理和面向角色的BPM Total Solution。
OpenCV
它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV用C++语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语言接口。该库也有大量的Python, Java and MATLAB/OCTAVE (版本2.5)的接口。
OpenCV自带例子中,提供了boost,mlp,knearest,nbayes,svm,rtrees这些机器学习方法,进行训练和识别。
处理的步骤和方式都类似。这些例子的识别率不是很高,OCR识别率在90%以上才有较好的使用意义,所以,OCR还需要更多特征和分析方法,来提高识别率,tesseract是一个不错的开源OCR引擎。
数字识别的步骤
ROI抽取、训练、识别
1.ROI抽取即将感兴趣的区域从原始图像中分离,该步骤包括二值化,噪点的消除等。直接将整个图像作为特征数据维度太高,计算量太大,可进行降维处理,拿到字符的ROI图像,二值化。将图像分块,然后统计每个小块中非0像素的个数,这样形成了一个较小的矩阵,这矩阵就是新的特征。
灰度图
2.训练
3.识别即通过一些分类器将第一步中的结果进行分类,事实上属于机器学习的一个典型应用
训练和识别一般采用同一种方法,目前普遍使用KNN、SVM。
数据之美:在自然语言与机器翻译领域,简单模型加上大量有效样本数据,比复杂模型加小样本数据,有效的多。收集有效的、大量的样本库很重要。
CNN
CNN的分类模型与传统模型的不同点在于其可以直接将一幅二维图像输入模型中,接着在输出端即给出分类结果。其优势在于不需复杂的预处理,将特征抽取,模式分类完全放入一个黑匣子中,通过不断的优化来获得网络所需参数,在输出层给出所需分类,网络核心就是网络的结构设计与网络的求解。这种求解结构比以往多种算法性能更高。
tesseract
google支持的开源的OCR图文识别开源项目
1.tesseract 图片名 输出文件名 -l 字库文件 -psm pagesegmode 配置文件
2.tesseract code.jpg result -l chi_sim -psm 7 nobatch
3.-l chi_sim 表示用简体中文字库(需要下载中文字库文件,解压后,存放到tessdata目录下去,字库文件扩展名为 .raineddata 简体中文字库文件名为: chi_sim.traineddata)
4.-psm 7 表示告诉tesseract code.jpg图片是一行文本 这个参数可以减少识别错误率. 默认为 3
5.configfile 参数值为tessdata\configs 和 tessdata\tessconfigs 目录下的文件名
cv2.imshow()
使用函数cv2.imshow() 显示图像。窗口会自动调整为图像大小。第一个参数是窗口的名字,其次才是我们的图像。你可以创建多个窗口,只要你喜欢,但是必须给他们不同的名字。
cv2.waitKey()
一个键盘绑定函数。需要指出的是它的时间尺度是毫
秒级。函数等待特定的几毫秒,看是否有键盘输入。特定的几毫秒之内,如果按下任意键,这个函数会返回按键的ASCII 码值,程序将会继续运行。如果没有键盘输入,返回值为-1,如果我们设置这个函数的参数为0,那它将会无限期的等待键盘输入。
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )
功能:对输入的图像src进行高斯滤波后用dst输出
参数:src和dst当然分别是输入图像和输出图像。Ksize为高斯滤波器模板大小,sigmaX和sigmaY分别为高斯滤波在横线和竖向的滤波系数。borderType为边缘扩展点插值类型。
.shape读取矩阵的长度
cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
获得原图像的副本,转换成灰度图
cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
Sobel算子是一种带方向的过滤器
前四个是必须的参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
其后是可选的参数:
dst不用解释了;
ksize是Sobel算子的大小,必须为1、3、5、7。
scale是缩放导数的比例常数,默认情况下没有伸缩系数;
delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。
cv2.CV_16S
16位有符号的数据类型
Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。
cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])
经过处理后,别忘了用convertScaleAbs()函数将其转回原来的uint8形式。否则将无法显示图像,而只是一副灰色的窗口
其中可选参数alpha是伸缩系数,beta是加到结果上的一个值。结果返回uint8类型的图片。
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
由于Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted(...)函数将其组合起来
其中alpha是第一幅图片中元素的权重,beta是第二个的权重,gamma是加到最后结果上的一个值。
np.absolute
x = np.array([-1.2, 1.2])
np.absolute(x)
array([ 1.2, 1.2])
np.absolute(1.2 + 1j)
1.5620499351813308
np.unit8
无符号整数,0 至 255
np.sum(axis = 1)
每一行的元素相加
cv2.threshold
将得到的结果二值化
cv2.getStructuringElement(cv2.MORPH_RECT,(13,7))
定义结构元素
用OpenCV-Python内置的常量定义椭圆(MORPH_ELLIPSE)和十字形结构(MORPH_CROSS)元素要简单一些,如果定义矩形(MORPH_RECT)和自定义结构元素,则两者差不多。
腐蚀和膨胀
<pre>
import cv2
import numpy as np
img = cv2.imread('D:/binary.bmp',0)
OpenCV定义的结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
腐蚀图像
eroded = cv2.erode(img,kernel)
显示腐蚀后的图像
cv2.imshow("Eroded Image",eroded);
膨胀图像
dilated = cv2.dilate(img,kernel)
显示膨胀后的图像
cv2.imshow("Dilated Image",dilated);
原图像
cv2.imshow("Origin", img)
NumPy定义的结构元素
NpKernel = np.uint8(np.ones((3,3)))
Nperoded = cv2.erode(img,NpKernel)
显示腐蚀后的图像
cv2.imshow("Eroded by NumPy kernel",Nperoded);
cv2.waitKey(0)
cv2.destroyAllWindows()
</pre>
腐蚀和膨胀的处理很简单,只需设置好结构元素,然后分别调用cv2.erode(...)和cv2.dilate(...)函数即可,其中第一个参数是需要处理的图像,第二个是结构元素。返回处理好的图像。
开运算和闭运算 cv2.morphologyEx
形态学基本处理:开运算和闭运算就是将腐蚀和膨胀按照一定的次序进行处理。但这两者并不是可逆的,即先开后闭并不能得到原先的图像。
<pre>
coding=utf-8
import cv2
import numpy as np
img = cv2.imread('D:/binary.bmp',0)
定义结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5, 5))
闭运算
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
显示腐蚀后的图像
cv2.imshow("Close",closed);
开运算
opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
显示腐蚀后的图像
cv2.imshow("Open", opened);
cv2.waitKey(0)
cv2.destroyAllWindows()
</pre>
<font color=blue >闭运算用来连接被误分为许多小块的对象,开运算用于移除由图像噪音形成的斑点,</font>因此,某些情况下可以连续运用这两种运算。如对一副二值图连续使用闭运算和开运算,将获得图像中的主要对象。同样,如果想消除图像中的噪声(即图像中的“小点”),也可以对图像先用开运算后用闭运算,不过这样也会消除一些破碎的对象。
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
<font color=blue>寻找检测物体的轮廓 </font>
注:cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图
<font color=#00ffff>参数:</font>
第一个参数是寻找轮廓的图像;
第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):
cv2.RETR_EXTERNAL表示只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
cv2.RETR_TREE建立一个等级树结构的轮廓。
第三个参数method为轮廓的近似办法
cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
<font color=#00ffff>返回值:</font>
返回两个值:contours,hierarchy。一个是轮廓本身(list),还有一个是每条轮廓对应的属性。
list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。这个概念非常重要。
该函数还可返回一个可选的hiararchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
第一个参数是指明在哪幅图像上绘制轮廓;
第二个参数是轮廓本身,在Python中是一个list。
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。绘制参数将在以后独立详细介绍。
void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);
InputArray curve:输入的点集
OutputArray approxCurve:输出的点集,当前点集是能最小包容指定点集的。draw出来即是一个多边形;
double epsilon:指定的精度,也即是原始曲线与近似曲线之间的最大距离。
bool closed:若为true,则说明近似曲线是闭合的,它的首位都是相连,反之,若为false,则断开。
IplImage *image = cvLoadImage("I:\OpenCV Learning\picture\sumpalace.jpg");
cvShowImage("image1",image);
//将ROI区域图像保存在image中:左上角x、左上角y、矩形长、宽
cvSetImageROI(image,cvRect(200,200,600,200));
cvShowImage("imageROI",image);
//执行cvSetImageROI()之后显示image图像是只显示ROI标识的一部分,即改变了指针image,
//但是它仍旧保留有原来图像的信息,在执行这一句cvResetImageROI(image),之后,image指示原来的图像信息。
cvResetImageROI(image);
cvShowImage("image2",image);
cvWaitKey(0);
return 0;
}
jTessBoxEditor
import cv2
img = cv2.imread("lenna.png")
crop_img = img[200:400, 100:300] # Crop from x, y, w, h -> 100, 200, 300, 400
NOTE: its img[y: y + h, x: x + w] and not img[x: x + w, y: y + h]
cv2.imshow("cropped", crop_img)
cv2.waitKey(0)
jTessBoxEditor训练步骤
- 工具jTessBoxEditor,下载地址为 http://sourceforge.net/projects/vietocr/files/jTessBoxEditor/
- tif文面命名格式[lang].[fontname].exp[num].tif
tesseract chi.fontname.exp0.tif chi.fontname.exp0 batch.nochop makebox
运行以上命令也会产生一个box文件。产生box文件的过程是必须的,也是最重要的,没有box文件以下的内容都无法进行。
需要记住的是生成的.box要和这个.tif文件同在一个目录下。
- 文字校正。运行jTessBoxEditor工具,打开chi.黑体.exp0.tif文件(必须将上一步生成的.box和.tif样本文件放在同一目录),如上图所示。可以看出有些字符识别的不正确,可以通过该工具手动对每张图片中识别错误的字符进行校正。校正完成后保存即可。
- 产生字符特征文件
tesseract chi.fontname.exp0.tif chi.fontname.exp0 nobatch box.train
- 计算字符集
unicharset_extractor chi.fontname.exp0.box
- 定义字体特征文件,---Tesseract-OCR3.01以上的版本在训练之前需要创建一个名称为font_properties.txt的字体特征文件
手工建立一个文件font_properties.txt
内容如:fontname 0 0 0 0 0
注意:fontname为字体名称,italic为斜体,bold为黑体字,fixed为默认字体,serif为衬线字体,fraktur德文黑字体,1和0代表有和无. - 聚集字符特征
shapeclustering -F font_properties.txt -U unicharset chi.fontname.exp0.tr
使用上一步产生的字符集文件unicharset,来生成当前新语言的字符集文件chi.unicharset。同时还会产生图形原型文件inttemp和每个字符所对应的字符mftraining -F font_properties.txt -U unicharset -O chi.unicharset chi.fontname.exp0.tr
特征数文件pffmtable。最重要的就是这个inttemp文件了,他包含了所有需要产生的字的图形原型。
这一步产生字符形状正常化特征文件normproto。cntraining chi.fontname.exp0.tr
- 把目录下的unicharset、inttemp、pffmtable、shapetable、normproto这五个文件前面都加上chi.
combine_tessdata chi.
11. 然后把chi.traineddata放到tessdata目录