Task2—图像数据读取与数据增广
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)