CV学习笔记(二十):数据集拼接生成

作者:云时之间
来源:知乎
链接:https://zhuanlan.zhihu.com/p/139918526
编辑:王萌

上一次使用了text_renderer尝试生成类似于银行卡的数据,但是实际下来效果并不好,我分析了一下原因:
①:text_renderer输出的背景和真实银行卡图片有很大的差异
②:大多数银行卡采用的是突出的字体,text_renderer很难去模拟
分析出以上的问题后,现在的重点开始转换成如何去近似的模拟银行卡数据集,最好的方法就是使用真实的银行卡卡号片段来拼接成数据。
一边说代码,一边捋顺思路:

一:准备数据

首先准备了大概50张的银行卡卡号片段的真实图片,尽量保证每张图片的长度为3-4位,为什么分为3-4位?分析了大多数的银行卡后,发现一个规律:
信用卡卡号:0000 0000 0000 0000
储蓄卡卡号:0000 0000 0000 0000 000
我们用CTPN检测的时候,往往会一段一段的检测,然后拼接起来,这种效果理论上会更好准备的数据如下:
图片的分辨率180*46
CV学习笔记(二十):数据集拼接生成
现在分析代码:
第一步:选择生成数量,读取图片
这部分注释很清楚,不再赘述
CV学习笔记(二十):数据集拼接生成

二:裁剪图片,拼接图片

这部分是整个程序之中的关键,我绘制了一个图,结合图来说一下
CV学习笔记(二十):数据集拼接生成
因为准备的数据集是3-4个字符一张图,DenseNet的输入长度为10时比较合适(具体为什么还没搞清楚),因此拼接的图片字符长度也是10个字符:读取图片
CV学习笔记(二十):数据集拼接生成
这里用到cut_image函数对image3进行裁剪:
CV学习笔记(二十):数据集拼接生成
裁剪前后对比:
CV学习笔记(二十):数据集拼接生成
对图片进行拼接:
CV学习笔记(二十):数据集拼接生成
拼接后效果:
CV学习笔记(二十):数据集拼接生成

三:数据增强

因为DenseNet的输入为280*32的图像,并且为减少计算,需要将图像转换为灰度图像
CV学习笔记(二十):数据集拼接生成
转换为灰度图像后,这里需要使用ImageDataGenerator类,简单的说ImageDataGenerator是keras.processing.image模块里的图片生成器,每次喂进去一个batch_size的数据,然后对这个批次的数据进行样本增强,用来扩充样本数据集的大小,增强模型的泛化能力,更模拟真实情况,比如旋转,缩放,对比度转换等等。

CV学习笔记(二十):数据集拼接生成

CV学习笔记(二十):数据集拼接生成

四:划分训练集和测试集

我们将训练集和测试集按照8:2的比例进行划分
CV学习笔记(二十):数据集拼接生成
运行,数据生成完毕
CV学习笔记(二十):数据集拼接生成

五:代码

import os
import numpy as np
import cv2
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
import os

#ToTAL是生成样本种子数量 ,真实样本数量为 TOTAL * 10
print("--------实际生成样本数为ToTal* 10--------")
TOTAL=int(input("输入要生成的种子数:"))
#图片路径,显示图片的名称
path_image=r'./images_base/'
list_path=os.listdir(path_image)

loca=["0,0,30,46","30,0,60,46","60,0,90,46","90,0,120,46"]
ALLIMAGE=len(list_path)#得到给出的训练集数量,image_base的数量
print("总共{0}张图片,需要生成{1}张图片\n------------正在生成中------------------".format(ALLIMAGE,TOTAL*10))

if not os.path.exists("./images"):
    os.mkdir("./images")

#对半裁图片,输入图片从120*46->60*46
def cut_image(imge,l2,l3,l0=0,l1=46):
    src2 = imge[l0:l1, l2:l3]
    return src2

for i in range(TOTAL):
    #生成0-allmage,三个的随机数
    rad_num=np.random.randint(0,ALLIMAGE,(1,3))

    img_path=[]

    for j in rad_num[0]:
        #取image_base里边的随机图片
         img_path.append([r"./images_base/"+str(list_path[j])])

         # img_path=img_path[0]
    imge1=cv2.imread(" ".join(img_path[0]))
    imge2 = cv2.imread(" ".join(img_path[1]))
    imge3 = cv2.imread(" ".join(img_path[2]))
    src1=cut_image(imge3, 0, 60)

    tmp = np.zeros((46, 300, 3), np.uint8)
    tmp[0:46, 0:120] = imge1
    tmp[0:46, 120:240] = imge2
    tmp[0:46, 240:300] = src1
    cv2.imshow("-",tmp)
    cv2.waitKey(0)
    '''
    名称为image1的前4位+image2前4位+src1的前两位
    '''
    name = " ".join(img_path[0]).split("/")[2][0:4] + " ".join(img_path[1]).split("/")[2][0:4] + \
           " ".join(img_path[2]).split("/")[2][0:2] + "I"
    # print(name)
    '''
    tmp输入300*46->DenseNet输入为280*32->Reshape后灰度
    '''
    tmp = cv2.resize(tmp, (280, 32))
    tmp = cv2.cvtColor(tmp, cv2.COLOR_BGR2GRAY)
    '''
    数据增强:
    随机旋转,除以总宽度0.01,除以总宽度0.015,
    空间随机缩放范围0.06
    随机填充
     '''
    datagen = ImageDataGenerator(   #数据增强
        rotation_range=2,
        width_shift_range=0.01,
        height_shift_range=0.015,
        zoom_range=0.06,
        fill_mode='nearest')

    #把图片的整数结构转成浮点型
    x = img_to_array(tmp)
    x = x.reshape((1,) + x.shape)
    i = 0
    '''
    接收numpy数组和标签为参数,生成经过数据提升或标准化后的batch数据,并在一个无限循环中不断的返回batch数据
    '''
    for batch in datagen.flow(x, batch_size=1,  # save_to_dir 文件夹   prefix图片名字   format格式
                              save_to_dir='images', save_prefix=name, save_format='jpg'):
        i += 1
        if i > 10:  # 如果不break会无限循环
            break  # otherwise the generator would loop indefinitely

    # cv2.imwrite("./out_data/" + name, tmp)

print("=====生成数据集======")
path_image=r'./images/'
list_path=os.listdir(path_image)
'''
生成训练集和测试集的txt文件
'''
f1=open("./data_train.txt",'w')
f2=open("./data_test.txt",'w')

for i in list(list_path)[0:int(len(list_path)*0.8)]: #划分80%训练
    f1.write(""+str(i))
    label=list(i)[0:10]
    for j in label:
        if j=="_":
            f1.write(" " + str(11))
        else:
            f1.write(" "+str(int(j)+1))
    f1.write("\n")

for i in list(list_path)[int(len(list_path)*0.8):]:
    f2.write(""+str(i))
    label=list(i)[0:10]
    for j in label:
        if j=="_":
            f2.write(" " + str(11))
        else:
            f2.write(" "+str(int(j)+1))
    f2.write("\n")
print("数据集生成完毕")
上一篇:堆 46


下一篇:httpd-2.4.46 编译安装