本专栏用于记录关于深度学习的笔记,不光方便自己复习与查阅,同时也希望能给您解决一些关于深度学习的相关问题,并提供一些微不足道的人工神经网络模型设计思路。
专栏地址:「深度学习一遍过」必修篇
目 录
1 方法
- 尺寸放大缩小
- 旋转(任意角度,如45°,90°,180°,270°)
- 翻转(水平翻转,垂直翻转)
- 明亮度改变(变亮,变暗)
- 像素平移(往一个方向平移像素,空出部分自动填补黑色)
- 添加噪声(椒盐噪声,高斯噪声)
注:不可用 “复制粘贴” 思想进行图像增强,因为此方法对计算机来说得到的图像是一样的,不会起到数据增强的效果。
2 具体实现
2.1 缩放
2.1.1 放大缩小
cv2.resize(image, None, fx=scale, fy=scale, interpolation=cv2.INTER_LINEAR)
2.2 翻转
2.2.1 水平翻转
cv2.flip(image, 1, dst=None) # 水平镜像
2.2.2 垂直翻转
cv2.flip(image, 0, dst=None) # 垂直镜像
2.2.3 旋转
R可控制图片放大缩小
cv2.warpAffine(image, M, (w, h))
2.3 明亮度
2.3.1 变暗
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)
2.3.2 变亮
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)
2.3.3 平移
cv2.warpAffine(img, mat_translation, (width, height))
2.4 增加噪声
2.4.1 增加椒盐噪声
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
2.4.2 增加高斯噪声
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]
3 完整代码
import os
import cv2
import numpy as np
'''
缩放
'''
# 放大缩小
def Scale(image, scale):
return cv2.resize(image, None, fx=scale, fy=scale, interpolation=cv2.INTER_LINEAR)
'''
翻转
'''
# 水平翻转
def Horizontal(image):
return cv2.flip(image, 1, dst=None) # 水平镜像
# 垂直翻转
def Vertical(image):
return cv2.flip(image, 0, dst=None) # 垂直镜像
# 旋转
def Rotate(image, angle=15, scale=0.9):
w = image.shape[1]
h = image.shape[0]
M = cv2.getRotationMatrix2D((w / 2, h / 2), angle, scale) # rotate matrix
image = cv2.warpAffine(image, M, (w, h)) # rotate
return image
'''
明亮度
'''
# 变暗
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.1):
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 Move(img, x, y):
img_info = img.shape
height = img_info[0]
width = img_info[1]
mat_translation = np.float32([[1, 0, x], [0, 1, y]]) # 变换矩阵:设置平移变换所需的计算矩阵:2行3列
# [[1,0,20],[0,1,50]] 表示平移变换:其中x表示水平方向上的平移距离,y表示竖直方向上的平移距离。
dst = cv2.warpAffine(img, mat_translation, (width, height)) # 变换函数
return dst
'''
增加噪声
'''
# 椒盐噪声
def SaltAndPepper(src, percetage=0.05):
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 GaussianNoise(image, percetage=0.05):
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
def Blur(img):
blur = cv2.GaussianBlur(img, (7, 7), 1.5) # cv2.GaussianBlur(图像,卷积核,标准差)
return blur
def TestOnePic():
test_jpg_loc = r"data/daisy/1.jpg"
test_jpg = cv2.imread(test_jpg_loc)
cv2.imshow("Show Img", test_jpg)
img1 = Blur(test_jpg)
cv2.imshow("Img 1", img1)
img2 = GaussianNoise(test_jpg,0.01)
cv2.imshow("Img 2", img2)
cv2.waitKey(0)
def TestOneDir():
root_path = "data/daisy"
save_path = root_path
for a, b, c in os.walk(root_path):
for file_i in c:
file_i_path = os.path.join(a, file_i)
print(file_i_path)
img_i = cv2.imread(file_i_path)
img_scale = Scale(img_i,1.5)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_scale.jpg"), img_scale)
img_horizontal = Horizontal(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_horizontal.jpg"), img_horizontal)
img_vertical = Vertical(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_vertical.jpg"), img_vertical)
img_rotate = Rotate(img_i,90)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_rotate90.jpg"), img_rotate)
img_rotate = Rotate(img_i, 180)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_rotate180.jpg"), img_rotate)
img_rotate = Rotate(img_i, 270)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_rotate270.jpg"), img_rotate)
img_move = Move(img_i,15,15)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_move.jpg"), img_move)
img_darker = Darker(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_darker.jpg"), img_darker)
img_brighter = Brighter(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_brighter.jpg"), img_brighter)
img_blur = Blur(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_blur.jpg"), img_blur)
img_salt = SaltAndPepper(img_i,0.05)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_salt.jpg"), img_salt)
def AllData(rootpath):
root_path = "data/"
save_loc = root_path
for a, b, c in os.walk(root_path):
for file_i in c:
file_i_path = os.path.join(a, file_i)
print(file_i_path)
split = os.path.split(file_i_path)
dir_loc = os.path.split(split[0])[1]
save_path = os.path.join(save_loc, dir_loc)
img_i = cv2.imread(file_i_path)
img_scale = Scale(img_i,1.5)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_scale.jpg"), img_scale)
img_horizontal = Horizontal(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_horizontal.jpg"), img_horizontal)
img_vertical = Vertical(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_vertical.jpg"), img_vertical)
img_rotate = Rotate(img_i, 90)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_rotate90.jpg"), img_rotate)
img_rotate = Rotate(img_i, 180)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_rotate180.jpg"), img_rotate)
img_rotate = Rotate(img_i, 270)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_rotate270.jpg"), img_rotate)
img_move = Move(img_i, 15, 15)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_move.jpg"), img_move)
img_darker = Darker(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_darker.jpg"), img_darker)
img_brighter = Brighter(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_brighter.jpg"), img_brighter)
img_blur = Blur(img_i)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_blur.jpg"), img_blur)
img_salt = SaltAndPepper(img_i, 0.05)
cv2.imwrite(os.path.join(save_path, file_i[:-4] + "_salt.jpg"), img_salt)
if __name__ == "__main__":
TestOneDir()
TestOnePic()
root_path = "data/"
AllData(root_path)
4 效果展示
5 补充:无数据增强与不同数据增强操作的差别
5.1 无数据增强
data_transforms = {
'train': transforms.Compose([
transforms.Scale(48),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5]) ]),
'val': transforms.Compose([
transforms.Scale(64),
transforms.CenterCrop(48),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])
]),
}
不做数据增强,不收敛
5.2 裁剪与翻转数据增强
data_transforms = {
'train': transforms.Compose([
transforms.RandomSizedCrop(48),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5]) ]),
'val': transforms.Compose([
transforms.Scale(64),
transforms.CenterCrop(48),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])
]),
}
自由缩放输入尺寸,裁剪+翻转数据增强,val_acc≈0.92
5.3 裁剪、翻转与旋转数据增强
data_transforms = {
'train': transforms.Compose([
transforms.RandomSizedCrop(48),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(15),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5]) ]),
'val': transforms.Compose([
transforms.Scale(64),
transforms.CenterCrop(48),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])
]),
}
自由缩放输入尺寸,裁剪+翻转+旋转数据增强,val_acc≈0.97
5.4 裁剪、翻转、旋转与颜色数据增强
data_transforms = {
'train': transforms.Compose([
transforms.RandomSizedCrop(48),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(15),
transforms.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1, hue=0.1),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5]) ]),
'val': transforms.Compose([
transforms.Scale(64),
transforms.CenterCrop(48),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])
]),
}
自由缩放输入尺寸,裁剪+翻转+旋转+颜色数据增强,val_acc≈0.99
5.5 总结
在数据太少时,数据增强大大提升了模型的泛化能力,很重要!
欢迎大家交流评论,一起学习
希望本文能帮助您解决您在这方面遇到的问题
感谢阅读
END
版权声明:本文为CSDN博主「荣仔!最靓的仔!」的原创文章,遵循 CC 4.0 BY-SA 版权协议。
转载请在醒目位置附上原文出处链接及本声明。