深度学习(八)——自动生成图片数据集

    最近做了一个汉字验证码识别的项目,该项目最大的难点就是数据集的准备。在自己没有数据集的情况下选择了自动生成,不过自己生成的数据集训练出来的模型,只在用自己方法生成的数据上表现比较好,但是在真实数据集上表现比较差,也算是自己为自己踩了一格坑。不过自己生成数据集的经历,还是学到了很多知识。并且该方法产生的数据集,可以产生无限的大量数据,可以供后面一些模型的测试,提供了很好的资源,今天我也把产生数据集的方法分享给大家。

一、问题的产生背景和自己生成数据集的意义

      我作的项目是破解验证码,没错,是不是感觉有点像黑客。哈哈,也是自己以为,其实业界人会觉得很low。破解验证码的目的是为了网络爬虫准备,在爬数据的过程中会遇到跳出验证吗的问题。影响到机器的自动爬,需要输进去验证码,这样我的工作就有了意义。但是,遇到一个很大的问题,我没数据,我没数据。所以有了两个思路,第一个思虑就是爬验证码,然后在标注训练。不过开始想了想真是特别夸张,要多少人力,汉字那么多分类我要多少数据。因此产生了第二个想法,自己生成数据,这样谁也管不住老子产生多少数据了。

二、真实数据样例

数据样本分析:

背景色相同,有四个干扰线,颜色不同。字体经过自己子产生数据过程中的对比是书宋,有干扰点,分布均匀。这不是明显机器自动生成的数据嘛,更加坚信了我产生数据的想法。

三、数据的生成过程

我就写一下步骤吧:

1、产生与真实数据相同的背景

2、产生干扰点,你们会想为什么这么早产生干扰点,因为我是用改变像素点的方法产生,我遍历整个图的像素,根据自己的设定随机改变一些像素值,就会产生了干扰点,而对后面汉字产生没有影响。(经过实验比较好的方法)

扫描二维码关注公众号,回复: 16558450 查看本文章

3、用drawimage的方法在背景上生成汉字,汉字我用的是shusong.ttf

4、旋转字体,字体写上以后就是整张图旋转了,但是旋转以后背景图的四个角是改变的。因为背景是有层次感的,导致旋转后四个角遮挡不聊了,漏出黑色。

5、这一步大家应该知道,把四个角的黑色三角变成白色。网上很多方法,先对图片根据像素值对其进行截取,只留下汉字所在的方框,然后在放在另外一个背景下,让背景统一。不过博主有一个另外简单想法,就是根据三通道值进行判断哪一部分是黑色三角,如果三通道值都是0,则代表是。但是这种方法应该最前面字体产生有个要求,黑色字体的像素不能是0,要是从1开始,这样对视觉没啥影响吧。

6、旋转以后,我们就要对图片产生干扰线。随机生成四条线,宽度和汉字的相同,颜色随机产生。

7、批量产生,我把常用汉字存到一个字典里,然后产生某个汉字的图片,都放在汉字所对应的key值文件夹下,这样我在训练的时候,根据访问文件夹就知道样本的标签啦。

四、代码分享和分析

from PIL import Image
import matplotlib.pyplot as plt
from PIL import ImageFont
from PIL import ImageDraw
import tensorflow as tf
import numpy as np
import random
import os
import cv2
import skimage.util
from code7 import ImageChar

class Creatimage(object):
    def __init__(self, font=ImageFont.truetype('fangzheng_shusong.ttf', 30),
                 img_r=Image.new("RGB", (50, 50), (255, 255, 255)), size=(50, 50),
                 chars="作", image_arr=np.zeros((256, 256, 3), np.uint8), value=0,
                 count=0, image_list = [[255,240,245],[185,211,238],[187,255,255]]):
        self.font = font
        self.img_r = img_r
        self.image_arr = image_arr
        self.size = size
        self.char = chars
        self.value = value
        self.count = count
        self.image_list=image_list
    def addnoise(self):
        self.img_r = np.array(self.img_r)
        for i in range(50):
            for j in range(50):
                if i%2 ==0 and j%2==0:
                    list =self.image_list[random.randint(0,2)]
                    self.img_r[i][j][0]=list[0]
                    self.img_r[i][j][1]=list[1]
                    self.img_r[i][j][2]=list[2]
    def drawText(self):
        self.img_r = Image.fromarray(self.img_r)
        draw = ImageDraw.Draw(self.img_r)
        draw.text((15, 20), self.char, self.randRGB(), font=self.font)
        del draw
    def rotate(self):
        self.img_r = self.img_r.rotate(random.randint(0,90), expand=0)

    def randLine(self, num):
        draw = ImageDraw.Draw(self.img_r)
        lineColor = self.randRGB()
        for i in range(0, num):
            draw.line([self.randPoint(), self.randPoint()], lineColor, 2)
        del draw

    def randPoint(self):
        (width, height) = self.size
        return (random.randint(0, width), random.randint(0, height))

    def randRGB(self):
        return (random.randint(1, 255),
                random.randint(1, 255),
                random.randint(1, 255))


    def changeIm(self):
        self.image_arr = np.array(self.img_r)
        for i in range(50):
            for j in range(50):
                if self.image_arr[i][j][0]==0 and self.image_arr[i][j][0]==0 and self.image_arr[i][j][0]==0:
                    self.image_arr[i][j][0]=255
                    self.image_arr[i][j][1]=255
                    self.image_arr[i][j][2]=255
                    if i % 2 == 0 and j % 2 == 0:
                        list = self.image_list[random.randint(0, 2)]
                        self.image_arr[i][j][0] = list[0]
                        self.image_arr[i][j][1] = list[1]
                        self.image_arr[i][j][2] = list[2]
        # print(self.image_arr)
    #im=np.array(img_r)
    #imshow(im)

    def printimage(self):
        plt.imshow(self.image_arr)
        plt.show()


    def createImage(self, num):
        self.addnoise()
        self.drawText()
        self.rotate()
        self.randLine(num)
        self.changeIm()
        self.printimage()

    def saveImage(self):
        out_dir = os.path.expanduser("./dateset")
        train_images_dir = os.path.join(out_dir, "train")
        if not os.path.isdir(train_images_dir):
            os.makedirs(train_images_dir)
        char_dir = os.path.join(train_images_dir, "%0.5d" % self.value)
        path_image = os.path.join(char_dir, "%d.jpeg" % self.count)
        if not os.path.isdir(char_dir):
            os.makedirs(char_dir)
        cv2.imwrite(path_image, self.image_arr)
        im = Image.fromarray(self.image_arr)

        im.save(path_image)

if __name__ == "__main__":
    ic = Creatimage()
    ic.createImage(4)
    ic.saveImage()

六、产生数据的样例

七、总结

良心说我感觉很像了,也是我呕心沥血,用了浑身解数的模仿,加各种技巧产生的。分享给大家,批量生产的源码在我的github上(https://github.com/machine-lv/Production-verification-code

猜你喜欢

转载自blog.csdn.net/qq_37100442/article/details/84034983
今日推荐