【第6天】资料前处理-资料扩增

现况

  1. 辨识手写中文字时,若图档内中文字迹有部分缺失,或是油墨泄漏造成字迹脏污,可能导致模型辨识错误,如下图。

  2. 训练影像辨识模型时,总不可避免地面临过拟合的情形,影响辨识效果。通常第一个想到的方法就是增加训练样本,以影像处理进行Data Augmentation,亦属於此列。

  3. 我们希望在资料前处理时,针对train资料集的图档加入椒盐杂讯,同时进行Data Augmentation,1张图档转变成4张,降低上述两点发生的可能性。


工具/套件

  1. opencv
  2. numpy
  3. random:将图档分割成25个区域後,使用rrandom.sample()随机抽取3个区域,用以加入椒盐杂讯。
  4. itertools:用以处理dict、list、tuple、str等资料类型,此处以product计算乘积。

内容

  1. 椒盐杂讯(Salt&Pepper Noise):分成盐噪音与胡椒噪音,盐噪音代表白色噪块(0)、胡椒噪音代表黑色躁块(255),当两者同时出现在图像上,会呈现黑白杂点,如下图。

    图片来自於:https://blog.csdn.net/u011995719/article/details/83375196

  2. Data Augmentation
    2.1 读取中文路径图档

    import os
    import cv2
    import numpy as np
    import random
    from itertools import product
    
    # 读取图档
    def cv_imread(filePath):
        cv_img = cv2.imdecode(np.fromfile(filePath,dtype=np.uint8),-1)
        return cv_img
    

    2.2 生成椒盐杂讯

    # 随机生成椒盐讯号
    def random_mask(filename):
        # 读取图档
        img = cv_imread(filename)
        img_high = img.shape[0]
        img_width = img.shape[1]
    
        # 将图档高度分成5等分
        img_high1, img_high2, img_high3, img_high4 = round(img_high*0.2), round(img_high*0.4), round(img_high*0.6), round(img_high*0.8)
        img_high_list = [0, img_high1, img_high2, img_high3, img_high4]
    
        # 将图档长度分成5等分
        img_width1, img_width2, img_width3, img_width4 = round(img_width*0.2), round(img_width*0.4), round(img_width*0.6), round(img_width*0.8)
        img_width_list = [0, img_width1, img_width2, img_width3, img_width4]
    
        # 切割成5*5个区块
        combine = list(product(img_high_list, img_width_list))
    
        # 随机抽取3个(取後不放回)
        masks = random.sample(combine, 3)
        print('masks:', masks)
        print('shape', img.shape)
    
        # mask
        mask_high = round(img_high/5)
        mask_widght = round(img_width/5)
        for i in masks:
            # y是宽,x是高
            (x, y) = i
            top_left = (y, x)
            bottom_right_widght = y + mask_widght
            bottom_right_high   = x + mask_high
            if y + img_width * 0.2 > img_width :
                bottom_right_widght = img_width
            if x + img_high * 0.2 > img_high:
                bottom_right_high = img_high
            bottom_right = (bottom_right_widght, bottom_right_high)
            print('top_left', top_left)
            print('bottom_right', bottom_right)
            # 产生黑、白躁点(黑色躁点为0、白色躁点为255)
            # cv2.rectangle(img, top_left, bottom_right, 255, -1)
            cv2.rectangle(img, top_left, bottom_right, 0, -1)
        print('-' * 20)
        return img
    

    2.3 显示mask成果

    # 显示图档
    def show_img(name, img):
        cv2.namedWindow(name, cv2.WINDOW_NORMAL)
        cv2.resizeWindow(name, 160, 120)
        cv2.imshow(name, img)
        cv2.waitKey()
    

    2.4 将1张图档资料扩增成4张,并另存新档

    if __name__ == '__main__':
        # 图档路径
        src_dir_name = './train/'
        target_dir_name = './test/'
    
        # 随机生成椒盐讯号,并另存新档
        for i in os.listdir(src_dir_name):
            sub_folder = src_dir_name + i + '/'
            for i in os.listdir(sub_folder):
                print(sub_folder+i)
                # 生成3张有椒盐讯号的新图档
                img1 = random_mask(sub_folder+i)
                img1 = cv2.resize(img1, (160, 120), interpolation=cv2.INTER_CUBIC)
                img2 = random_mask(sub_folder+i)
                img2 = cv2.resize(img1, (160, 120), interpolation=cv2.INTER_CUBIC)
                img3 = random_mask(sub_folder+i)
                img3 = cv2.resize(img1, (160, 120), interpolation=cv2.INTER_CUBIC)
                # 将新增随机椒盐杂讯後的图档另存新档
                cv2.imencode('.jpg', img1)[1].tofile(sub_folder+'1_'+i)
                cv2.imencode('.jpg', img2)[1].tofile(sub_folder+'2_'+i)
                cv2.imencode('.jpg', img3)[1].tofile(sub_folder+'3_'+i)
                print('=' * 50)
                show_img('name', img1)
    

小结

  1. 要训练出一个好的影像辨识模型,高品质的资料集是不可或缺的,因此,我们耗费了大量时间在资料前处理。历经4天的资料前处理,最终得到新资料集,数量如下。
    1.1 train资料集:174,808张
    1.2 test资料集:18,717张
  2. 工欲善其事,必先利其器!下一站,我们前往训练模型的「前置作业」。分享如何在本地端安装tensorflow架构与使用GPU训练模型,提高训练模型效率。

让我们继续看下去...


参考资料

  1. 浅谈图片杂讯处理
  2. 椒盐杂讯
  3. Python实现图像加噪

<<:  【Day 6】Replication

>>:  连续 30 天 玩玩看 ProtoPie - Day 6

【从零开始的 C 语言笔记】第三篇-基本的程序结构介绍 & 列印三角形

不怎麽重要的前言 上一篇我们学会怎麽创建档案,也运行了我们的第一个程序,接下来会介绍上次的程序码,分...

1. 解释 Scope ( Global scope / Function scope / Block scope )

2021.9.3更新: 调整了一些block scope的叙述。 Scope 的定义 scope ...

#25-让长条图一条条动起来~大数据时代!入手 D3.js~

自己做行销的时候,很喜欢玩数据, 数据可以打破一些先入为主的想法、 也可以给我们更全面的视角、或是新...

Day 6:JUCE 框架基本架构

本文介绍 Projucer 建立的 GUI Application 框架基本架构。框架(Framew...

Day26 :【TypeScript 学起来】Class 与 Interface 的使用

我们在前面的时候有提过 interface 是用来定义物件的型别,对物件的形状进行描述。在物件导向程...