上一次使用了text_renderer尝试生成类似于银行卡的数据,但是实际下来效果并不好,我分析了一下原因:
①:text_renderer输出的背景和真实银行卡图片有很大的差异
②:大多数银行卡采用的是突出的字体,text_renderer很难去模拟
分析出以上的问题后,现在的重点开始转换成如何去近似的模拟银行卡数据集,最好的方法就是使用真实的银行卡卡号片段来拼接成数据。
一边说代码,一边捋顺思路:
一:准备数据
首先准备了大概50张的银行卡卡号片段的真实图片,尽量保证每张图片的长度为3-4位,为什么分为3-4位?分析了大多数的银行卡后,发现一个规律:
信用卡卡号:0000 0000 0000 0000
储蓄卡卡号:0000 0000 0000 0000 000
我们用CTPN检测的时候,往往会一段一段的检测,然后拼接起来,这种效果理论上会更好准备的数据如下:
图片的分辨率180*46
![b3b2b713900a115de421bea9bc9dcd0d.png](https://i-blog.csdnimg.cn/blog_migrate/c17cedac1374f536f822350e94c46526.jpeg)
现在分析代码:
第一步:选择生成数量,读取图片
这部分注释很清楚,不再赘述
![8da5853a68462535ea73894c690f3761.png](https://i-blog.csdnimg.cn/blog_migrate/ede286d5d9d5dee236404575ded2365a.jpeg)
二:裁剪图片,拼接图片
这部分是整个程序之中的关键,我绘制了一个图,结合图来说一下
![ca08452a279a13c36c0ae27254670b5c.png](https://i-blog.csdnimg.cn/blog_migrate/b60aff2e036ad7d40402896f8723437f.png)
因为准备的数据集是3-4个字符一张图,DenseNet的输入长度为10时比较合适(具体为什么还没搞清楚),因此拼接的图片字符长度也是10个字符:读取图片
![b688edca27123729cb3c428359cc12a1.png](https://i-blog.csdnimg.cn/blog_migrate/467727bb3e269480fa90ba14e1d6d928.png)
这里用到cut_image函数对image3进行裁剪:
![e3b2ef748061b1fd073979de9d16d60e.png](https://i-blog.csdnimg.cn/blog_migrate/8783389ef8217c0cc557dfa84062b464.png)
裁剪前后对比:
![ae2cb5b6a3971f4f8e948d5069c0de11.png](https://i-blog.csdnimg.cn/blog_migrate/d6b87a6a878bff6c2ab2e27faca51a72.png)
对图片进行拼接:
![b43c8fb27a695ca98188200de6dfe9bb.png](https://i-blog.csdnimg.cn/blog_migrate/5cc678fb4f959f002b4cb18ad933ebb8.png)
拼接后效果:
![9e45474cfe07d3a7922f62bf9e848d93.png](https://i-blog.csdnimg.cn/blog_migrate/974d96dc9568f6a90de5a87e6d37b6ea.png)
三:数据增强
因为DenseNet的输入为280*32的图像,并且为减少计算,需要将图像转换为灰度图像
![376e118601b755c45d6c53fd174319af.png](https://i-blog.csdnimg.cn/blog_migrate/2c469fa13c143d211d5c351183e3b335.png)
转换为灰度图像后,这里需要使用ImageDataGenerator类,简单的说ImageDataGenerator是keras.processing.image模块里的图片生成器,每次喂进去一个batch_size的数据,然后对这个批次的数据进行样本增强,用来扩充样本数据集的大小,增强模型的泛化能力,更模拟真实情况,比如旋转,缩放,对比度转换等等。
![6105bd01a79cf15080f69a986d45d024.png](https://i-blog.csdnimg.cn/blog_migrate/34eb00adcb98ec6c75fa8a4da747ad03.png)
![0ce89a47e83ea8e4af45e2178372de42.png](https://i-blog.csdnimg.cn/blog_migrate/e08b8be46cd5721fd0d108dad8faff64.jpeg)
四:划分训练集和测试集
我们将训练集和测试集按照8:2的比例进行划分
![2fd7a885631a0a71fceb0e2b6d5aa8cb.png](https://i-blog.csdnimg.cn/blog_migrate/9b8e41beb9fdec75d9e38dba5dd7ea6c.png)
运行,数据生成完毕
![fdcaa3633a34ffc6892cdb0941df047a.png](https://i-blog.csdnimg.cn/blog_migrate/9a43402e9c295255397a10916a22ce96.png)
五:代码
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("数据集生成完毕")