完成了opencv基础知识学习,现在进行实践操作

1、生成随机四位数字验证码

opencv验证码识别 java opencv验证码识别_验证码

import os
import random
# captcha是用于生成验证码图片的库,可以 pip install captcha 来安装它
from captcha.image import ImageCaptcha


def random_captcha_text(num):
    # 验证码列表
    captcha_text = []
    for i in range(10):  # 0-9数字
        captcha_text.append(str(i))
    # for i in range(65, 91):  # 对应从“A”到“Z”的ASCII码
    #     captcha_text.append(chr(i))
    # for i in range(97, 123):  # 对应从“a”到“z”的ASCII码
    #     captcha_text.append(chr(i))

    # 从list中随机获取6个元素,作为一个片断返回
    example = random.sample(captcha_text, num)

    # 将列表里的片段变为字符串并返回
    verification_code = ''.join(example)
    return verification_code


# 生成字符对应的验证码
def generate_captcha_image():
    image = ImageCaptcha()
    # 获得随机生成的验证码
    captcha_text = random_captcha_text(4)
    # 把验证码列表转为字符串
    captcha_text = ''.join(captcha_text)
    # 生成验证码

    path = 'D:/验证码识别/test/'
    if not os.path.exists(path):
        print("目录不存在!,已自动创建")
        os.makedirs(path)
    print("生成的验证码的图片为:", captcha_text)
    image.write(captcha_text, path + captcha_text + '.png')


if __name__ == '__main__':
    number = 100
    for i in range(number):
        generate_captcha_image()

2、安装pytesseract包,中间出现很多问题,最终查阅资料得以解决

3、对验证码图片进行预处理

opencv验证码识别 java opencv验证码识别_验证码_02

图像预处理主要包括对图像的灰度化、二值化、去噪声,以及图像倾斜的矫正和增强等。

(1)灰度化:
对图像进行灰度处理,是为了减少识别样本的计算量,将图像样本统一,简化训练和识别难度。

Gray=0-299R+0.587G+0.114B(1)

opencv验证码识别 java opencv验证码识别_命令行_03

(2)二值化:
二值化指将图像上的像素点转化为黑白两种颜色的点,即将灰度值设置为0(黑)或255(白)。其目的是区分图像的前后景,使图像呈现明显的视觉效果,同时为后续的识别和处理做准备。我试了几种二值化的方法最后选择了OTSU,可以明显发现图像中有一些横线和小点点的干扰

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_04

 

 

# 二值图像就是将灰度图转化成黑白图,没有灰,在一个值之前为黑,之后为白
# 有全局和局部两种
# 在使用全局阈值时,我们就是随便给了一个数来做阈值,那我们怎么知道我们选取的这个数的好坏呢?答案就是不停的尝试。
# 如果是一副双峰图像(简 单来说双峰图像是指图像直方图中存在两个峰)呢?
# 我们岂不是应该在两个峰之间的峰谷选一个值作为阈值?这就是 Otsu 二值化要做的。
# 简单来说就是对 一副双峰图像自动根据其直方图计算出一个阈值。
# (对于非双峰图像,这种方法 得到的结果可能会不理想)。

(3)去噪声:
图像中往往含有噪声,要对图形进行噪声处理,减少噪声影响,将噪声干扰降到最低,我采用开运算,因为开运算的特性,正好可以降低干扰。

opencv验证码识别 java opencv验证码识别_验证码_05

 

然后再试着改变kernel算子的值,我先设置的是(2,2)效果如上图,后来找到最合适的是(3,3)

opencv验证码识别 java opencv验证码识别_二值化_06

基本没有小白点了

 

 

 

开运算:先进性腐蚀再进行膨胀就叫做开运算,它被用来去除噪声。
闭运算:先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。
这里我们用到的函数是 cv2.morphologyEx()。
开闭操作作用:
1. 去除小的干扰块-开操作
2. 填充闭合区间-闭操作
3. 水平或垂直线提取,调整kernel的row,col值差异。
比如:采用开操作,kernel为(1, 15),提取垂直线,kernel为(15, 1),提取水平线,
"""
def recongize_text(image):
    gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    cv.imshow("gray1",gray)
    gray=interference_line(gray)
    cv.imshow("gray2",gray)

    ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
    # binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
    kernel=cv.getStructuringElement(cv.MORPH_RECT,(3,4))
    open_out=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
    # open_out=cv.morphologyEx(open_out,cv.MORPH_CLOSE,kernel)

    cv.imshow("binary_image",open_out)

    cv.bitwise_not(open_out,open_out)
    cv.imshow("dd",open_out)

    result = np.array(open_out)
    ss = cv.medianBlur(result, 5)
    cv.imshow('66666.png', ss)

    textImage=Image.fromarray(ss)

    target = tess.image_to_string(textImage)
    print("识别结果:%s "%target)

 

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_07

opencv验证码识别 java opencv验证码识别_二值化_08

opencv验证码识别 java opencv验证码识别_命令行_09

 

 

但是由于,tesseract这个库识别的效果并不是很理想,他会自动把数字识别成其他的符号或者字母

或者直接识别不出来,不同的验证码,需要选取不同的opencv图像处理方式

所以上网查阅资料,自己创建库

(4)tesseract训练

大体流程为:安装jTessBoxEditor -> 获取样本文件 -> Merge样本文件 –> 生成BOX文件 -> 定义字符配置文件 -> 字符矫正 -> 执行批处理文件 -> 将生成的traineddata放入tessdata中

1、用jTessBoxEditor把要训练样本图片文件合并成tif文件(样本图片一定要为有效的格式图片)

       运行jTessBoxEditor程序,界面如下: 

 

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_10

点击顶栏的Tools选项,选择Merge TIFF..   进入你要训练的样本图片所在的目录,点击Ctrl+Alt+A,选择所有图片点击打开:

 

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_11

然后保存文件名到指定目录,我这里保存的文件名为: langyp.font.exp0.tif

opencv验证码识别 java opencv验证码识别_命令行_12

2、生成Box文件

 打开cmd,到你langyp.font.exp0.tif文件所在目录,执行:

  tesseract langyp.font.exp0.tif langyp.font.exp0 batch.nochop makebox


opencv验证码识别 java opencv验证码识别_二值化_13

结果生成了langyp.font.exp0.box文件

3、 对样本图片用jTessBoxEditor工具进行矫正

点击jTessBoxEditor工具的Box Editor选项,点击下方的open选项,打开刚刚生成的langyp.font.exp0.tif文件,结果如下: 

 

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_14

 

右侧为对应的Box文件数据,如果char的字符和当前的样本图片一致时就进行矫正,修改char里的字符,然后进行save,这样就矫正了,进入下张样本图片时,同样,矫正后点击save,当所有样本图片都矫正了,这一步也就完成了

4、生成font_properties文件(该文件没有后缀名)
 
在命令行执行:echo font 0 0 0 0 0 >font_properties
 结果生成了font_properties文件 

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_15

 

 内容为字体名font,后面带5个0,分别代表字体的粗体、斜体等属性,这里全部是0

5、生成.tr训练文件
在命令行执行: tesseract langyp.font.exp0.tif langyp.font.exp0 -l eng -psm 7 nobatch box.train

opencv验证码识别 java opencv验证码识别_验证码_16

 

 6、生成字符集文件
在命令行执行 : unicharset_extractor langyp.font.exp0.box

opencv验证码识别 java opencv验证码识别_二值化_17

 

 

结果生成了unicharset文件

7、生成shape文件
在命令行执行 : shapeclustering -F font_properties -U unicharset -O langyp.unicharset langyp.font.exp0.tr

opencv验证码识别 java opencv验证码识别_命令行_18

 

结果生成了shapetable文件和langyp.unicharset文件

8、生成聚集字符特征文件
在命令行执行: mftraining -F font_properties -U unicharset -O langyp.unicharset langyp.font.exp0.tr

结果生成了pffmtable,inttemp,unicharset文件

9、生成字符正常化特征文件
在命令行执行: cntraining langyp.font.exp0.tr

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_19

 

结果生成了normproto文件

10、把h,i步骤生成的文件用rename命令进行更名
在命令行执行:  

**rename normproto fontyp.normproto  
rename inttemp fontyp.inttemp  
rename pffmtable fontyp.pffmtable  
rename unicharset fontyp.unicharset  
rename shapetable fontyp.shapetable**

11、合并训练文件
在命令行执行: combine_tessdata fontyp

opencv验证码识别 java opencv验证码识别_opencv验证码识别 java_20

 

12、将fontyp.traineddata文件拷贝至Tesseract-OCR文件夹里的tessdata语言包文件夹里

windows下面:

opencv验证码识别 java opencv验证码识别_验证码_21