Datawhale_街景字符编码识别-Task2—图像数据读取与数据增广

本文介绍了图像增广技术,通过一系列随机变换扩大训练数据集,提高模型泛化能力。涵盖水平/垂直镜像、旋转、缩放、平移、亮度调整和噪声添加等方法,并提供详细的编程实现,包括组合变换的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、介绍

图像增广(image augmentation)技术通过对训练图像做一系列随机改变,来产生相似但又不同的训练样本,从而扩大训练数据集的规模。图像增广的另一种解释是,随机改变训练样本可以降低模型对某些属性的依赖,从而提高模型的泛化能力。

目前常用的图像增广技术有如下几种:

  • 镜像变换
  • 旋转
  • 缩放
  • 裁剪
  • 平移
  • 亮度修改
  • 添加噪声
  • 剪切
  • 变换颜色

在图像增广过程中可以使用其中一种手段进行扩充,也可以使用其中的几种方法进行组合使用,由于概念比较简单,容易理解,所以接下来就边实现,边详细阐述理论知识

2、理论部分

在这里插入图片描述

3、编程实现—1

1、读取图像:

# 1. 读取图像
img = cv2.imread("./data/000023.jpg")
cv2.imshow("Origin", img)
cv2.waitKey()

在这里插入图片描述
2、初始化一个矩阵,用于存储转化后的图像

generate_img = np.zeros(img.shape)

3.1、水平镜像

遍历图像的像素,用前文提到的数学关系式进行像素的转化

for i in range(h):
    for j in range(w):
        generate_img[i, w - 1 - j] = img[i, j]

cv2.imshow("Ver", generate_img.astype(np.uint8))
cv2.waitKey()

在这里插入图片描述
**Note:**初始化的图像数据类型是numpy.float64,用opencv显示时无法正常显示,因此在显示时需要用astype(np.uint8)把图像转化成numpy.uint8数据格式。

3.2、垂直镜像

for i in range(h):
    for j in range(w):
        generate_img[h-1-i, j] = img[i, j]

在这里插入图片描述
**Note:**镜像变换也可以直接调用opencv的flip进行使用

3.3、图像缩放

这个比较简单,直接调用opencv的resize函数即可

output = cv2.resize(img, (100, 300))

在这里插入图片描述

3.4、旋转变换

这个相对复杂一些,需要首先用getRotationMatrix2D函数获取一个旋转矩阵,然后调用opencv的warpAffine仿射函数按照旋转矩阵对图像进行旋转变换

center = cv2.getRotationMatrix2D((w/2, h/2), 45, 1)
rotated_img = cv2.warpAffine(img, center, (w, h))

在这里插入图片描述

3.5、平移变换

首先用numpy生成一个平移矩阵,然后用仿射变换函数对图像进行平移变换

move = np.float32([[1, 0, 100], [0, 1, 100]])
move_img = cv2.warpAffine(img, move, (w, h))

在这里插入图片描述

3.6、亮度变换

亮度变换的方法有很多种,本文介绍一种叠加图像的方式,通过给原图像叠加一副同样大小,不同透明度的全零像素图像来修改图像的亮度

alpha = 1.5
light = cv2.addWeighted(img, alpha, np.zeros(img.shape).astype(np.uint8), 1-alpha, 3)

其中alpha是原图像的透明度
在这里插入图片描述

3.7、添加噪声

首先写一下噪声添加的函数,原理就是给图像添加一些符合正态分布的随机数

def add_noise(img):
    img = np.multiply(img, 1. / 255,
                        dtype=np.float64)
    mean, var = 0, 0.01
    noise = np.random.normal(mean, var ** 0.5,
                             img.shape)
    img = convert(img, np.floating)
    out = img + noise
    return out

在这里插入图片描述

3.8、组合变换

除了以上方法单独使用之外,还可以叠加其中多种方法进行组合使用,比如可以结合选择、镜像进行使用
在这里插入图片描述

4、完整代码

import cv2
import numpy as np
from skimage.util.dtype import convert


class ImageAugmented(object):
    def __init__(self, path="../data/2007_000129.jpg"):
        self.img = cv2.imread(path)
        self.h, self.w = self.img.shape[0], self.img.shape[1]

    # 1. 镜像变换
    def flip(self, flag="h"):
        generate_img = np.zeros(self.img.shape)
        if flag == "h":
            for i in range(self.h):
                for j in range(self.w):
                    generate_img[i, self.h - 1 - j] = self.img[i, j]
        else:
            for i in range(self.h):
                for j in range(self.w):
                    generate_img[self.h - 1 - i, j] = self.img[i, j]
        return generate_img

    # 2. 缩放
    def _resize_img(self, shape=(100, 300)):
        return cv2.resize(self.img, shape)

    # 3. 旋转
    def rotated(self):
        center = cv2.getRotationMatrix2D((self.w / 2, self.h / 2), 45, 1)
        return cv2.warpAffine(self.img, center, (self.w, self.h))

    # 4. 平移
    def translation(self, x_scale=100, y_scale=100):
        move = np.float32([[1, 0, x_scale], [0, 1, y_scale]])
        return cv2.warpAffine(self.img, move, (self.w, self.h))

    # 5. 改变亮度
    def change_light(self, alpha=1.5, scale=3):
        return cv2.addWeighted(self.img, alpha, np.zeros(self.img.shape).astype(np.uint8), 1 - alpha, scale)

    # 6. 添加噪声
    def add_noise(self, mean=0, var=0.01):
        img = np.multiply(self.img, 1. / 255, dtype=np.float64)
        noise = np.random.normal(mean, var ** 0.5,
                                 img.shape)
        img = convert(img, np.floating)
        out = img + noise
        return out


if __name__ == '__main__':
    aug = ImageAugmented()
    img = aug.translation()
    cv2.imshow("img", img)
    cv2.waitKey()

5、编程实现—2

#程序功能:python+opencv实现数据增强
#作者:mao
#时间:2019.5.25

import numpy as np
import cv2

img=cv2.imread("1.jpg")
cv2.imshow("original",img)

#水平镜像
h_flip=cv2.flip(img,1)
cv2.imshow("Flipped Horizontally",h_flip)

#垂直镜像
v_flip=cv2.flip(img,0)
cv2.imshow("Flipped Vertically",v_flip)

#水平垂直镜像
hv_flip=cv2.flip(img,-1)
cv2.imshow("Flipped Horizontally & Vertically",hv_flip)


#平移矩阵[[1,0,-100],[0,1,-12]]
M=np.array([[1,0,-100],[0,1,-12]],dtype=np.float32)
img_change=cv2.warpAffine(img,M,(300,300))
cv2.imshow("translation",img_change)

#90度旋转
rows,cols=img.shape[:2]
M=cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst=cv2.warpAffine(img,M,(cols,rows))
cv2.imshow("90",dst)

#45度旋转
rows,cols=img.shape[:2]
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,1)
dst=cv2.warpAffine(img,M,(cols,rows))
cv2.imshow("45",dst)

#缩放
height,width=img.shape[:2]
res=cv2.resize(img,(2*width,2*height))
cv2.imshow("large",res)

# 仿射变换
#对图像进行变换(三点得到一个变换矩阵)
# 我们知道三点确定一个平面,我们也可以通过确定三个点的关系来得到转换矩阵
# 然后再通过warpAffine来进行变换
point1=np.float32([[50,50],[300,50],[50,200]])
point2=np.float32([[10,100],[300,50],[100,250]])

M=cv2.getAffineTransform(point1,point2)
dst1=cv2.warpAffine(img,M,(cols,rows),borderValue=(255,255,255))
cv2.imshow("affine transformation",dst1)
cv2.waitKey(0)

循环读取文件夹内图片并增强后保存为图片

# 程序功能:python+opencv实现数据增强,并保存图片
# 作者:mao
# 时间:2020.5.6

import numpy as np
import cv2
import os
#数据增强后的图片保存路劲
save_path='E:\\python_project\\yi_xue_ying_xiang\\tuxiangzengqiang\\after\\'

for info in os.listdir(r'E:\python_project\yi_xue_ying_xiang\tuxiangzengqiang\pic'):
    domain = os.path.abspath(
        r'E:\python_project\yi_xue_ying_xiang\tuxiangzengqiang\pic')  # 获取文件夹的路径,此处其实没必要这么写,目的是为了熟悉os的文件夹操作
    info1 = os.path.join(domain, info)  # 将路径与文件名结合起来就是每个文件的完整路径
    img = cv2.imread(info1)
    cv2.imshow("original", img)
    cv2.waitKey(1000)
    # 水平镜像
    h_flip = cv2.flip(img, 1)
    cv2.imshow("Flipped Horizontally", h_flip)
    cv2.imwrite(save_path+info+'_h_flip.jpg', h_flip)
    # 垂直镜像
    v_flip = cv2.flip(img, 0)
    cv2.imshow("Flipped Vertically", v_flip)
    cv2.imwrite(save_path+info+'_v_flip.jpg', v_flip)
    # 水平垂直镜像
    hv_flip = cv2.flip(img, -1)
    cv2.imshow("Flipped Horizontally & Vertically", hv_flip)
    cv2.imwrite(save_path+info+'hv_flip.jpg', hv_flip)
    # # 平移矩阵[[1,0,-100],[0,1,-12]]
    # M = np.array([[1, 0, -100], [0, 1, -12]], dtype=np.float32)
    # img_change = cv2.warpAffine(img, M, (300, 300))
    # cv2.imshow("translation", img_change)
    # cv2.imwrite(save_path+info+'img_change.jpg', img_change)
    # 90度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
    dst_90 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_90", dst_90)
    cv2.imwrite(save_path+info+'dst_90.jpg', dst_90)
    # 70度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 70, 1)
    dst_70 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_70", dst_70)
    cv2.imwrite(save_path+info+'dst_70.jpg', dst_70)
    # 60度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 60, 1)
    dst_60 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_60", dst_60)
    cv2.imwrite(save_path+info+'dst_60.jpg', dst_60)
    # 50度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 50, 1)
    dst_50 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_50", dst_50)
    cv2.imwrite(save_path+info+'dst_50.jpg', dst_50)
    # 45度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 1)
    dst_45 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_45", dst_45)
    cv2.imwrite(save_path+info+'dst_45.jpg', dst_45)
    # 40度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 40, 1)
    dst_40 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_40", dst_40)
    cv2.imwrite(save_path+info+'dst_40.jpg', dst_40)
    # 30度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 30, 1)
    dst_30 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_30", dst_30)
    cv2.imwrite(save_path+info+'dst_30.jpg', dst_30)
    # 20度旋转
    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 20, 1)
    dst_20 = cv2.warpAffine(img, M, (cols, rows))
    cv2.imshow("dst_20", dst_20)
    cv2.imwrite(save_path+info+'dst_20.jpg', dst_20)
    # 缩放
    # height, width = img.shape[:2]
    # res = cv2.resize(img, (2 * width, 2 * height))
    # cv2.imshow("large", res)
    # cv2.imwrite(save_path+info+'res.jpg', res)
    # 仿射变换
    # 对图像进行变换(三点得到一个变换矩阵)
    # 我们知道三点确定一个平面,我们也可以通过确定三个点的关系来得到转换矩阵
    # 然后再通过warpAffine来进行变换
    point1 = np.float32([[50, 50], [300, 50], [50, 200]])
    point2 = np.float32([[10, 100], [300, 50], [100, 250]])
    M = cv2.getAffineTransform(point1, point2)
    dst1 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255, 255, 255))
    cv2.imshow("affine transformation", dst1)
    cv2.imwrite(save_path+info+'dst1.jpg', dst1)

cv2.waitKey(0)

6、编程实现—3

翻转,旋转,椒盐噪声,高斯噪声,亮度调节


def SaltAndPepper(src,percetage):  
    SP_NoiseImg=src.copy()
    SP_NoiseNum=int(percetage*src.shape[0]*src.shape[1]) 
    for i in range(SP_NoiseNum): 
        randR=np.random.randint(0,src.shape[0]-1) 
        randG=np.random.randint(0,src.shape[1]-1) 
        randB=np.random.randint(0,3)
        if np.random.randint(0,1)==0: 
            SP_NoiseImg[randR,randG,randB]=0 
        else: 
            SP_NoiseImg[randR,randG,randB]=255 
    return SP_NoiseImg 
def addGaussianNoise(image,percetage): 
    G_Noiseimg = image.copy()
    w = image.shape[1]
    h = image.shape[0]
    G_NoiseNum=int(percetage*image.shape[0]*image.shape[1]) 
    for i in range(G_NoiseNum): 
        temp_x = np.random.randint(0,h) 
        temp_y = np.random.randint(0,w) 
        G_Noiseimg[temp_x][temp_y][np.random.randint(3)] = np.random.randn(1)[0] 
    return G_Noiseimg
#dimming
def darker(image,percetage=0.9):
    image_copy = image.copy()
    w = image.shape[1]
    h = image.shape[0]
    #get darker
    for xi in range(0,w):
        for xj in range(0,h):
            image_copy[xj,xi,0] = int(image[xj,xi,0]*percetage)
            image_copy[xj,xi,1] = int(image[xj,xi,1]*percetage)
            image_copy[xj,xi,2] = int(image[xj,xi,2]*percetage)
    return image_copy
def brighter(image, percetage=1.5):
    image_copy = image.copy()
    w = image.shape[1]
    h = image.shape[0]
    #get brighter
    for xi in range(0,w):
        for xj in range(0,h):
            image_copy[xj,xi,0] = np.clip(int(image[xj,xi,0]*percetage),a_max=255,a_min=0)
            image_copy[xj,xi,1] = np.clip(int(image[xj,xi,1]*percetage),a_max=255,a_min=0)
            image_copy[xj,xi,2] = np.clip(int(image[xj,xi,2]*percetage),a_max=255,a_min=0)
    return image_copy
def rotate(image, angle=15, scale=0.9):
    w = image.shape[1]
    h = image.shape[0]
    #rotate matrix
    M = cv2.getRotationMatrix2D((w/2,h/2), angle, scale)
    #rotate
    image = cv2.warpAffine(image,M,(w,h))
    return image
def img_augmentation(path, name_int):        
    img = cv2.imread(path)
    img_flip = cv2.flip(img,1)#flip
    img_rotation = rotate(img)#rotation
    
    img_noise1 = SaltAndPepper(img, 0.3)
    img_noise2 = addGaussianNoise(img, 0.3)
    
    img_brighter = brighter(img)
    img_darker = darker(img)
    
    cv2.imwrite(save_path+'%s' %str(name_int)+'.jpg', img_flip)
    cv2.imwrite(save_path+'%s' %str(name_int+1)+'.jpg', img_rotation)
    cv2.imwrite(save_path+'%s' %str(name_int+2)+'.jpg', img_noise1)
    cv2.imwrite(save_path+'%s' %str(name_int+3)+'.jpg', img_noise2)
    cv2.imwrite(save_path+'%s' %str(name_int+4)+'.jpg', img_brighter)
    cv2.imwrite(save_path+'%s' %str(name_int+5)+'.jpg', img_darker)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值