使用深度学习执行图像分类任务时往往因为数据量不平衡或者数据量不足,需要进行数据增强,数据增强包括平移、旋转、裁剪、拉伸、缩放、水平翻转、垂直翻转、水平垂直、加噪声等等。而对于乳腺超声图像数据来说,拉伸、裁剪等操作会改变图像的形状信息,因此我使用水平翻转和旋转的方法进行数据扩充。
一、水平翻转
两种方法:分别是利用Opencv的DataAugment()函数、 PIL中的Image
1 Opencv方法:
代码:
'''
Python批量实现图像镜像翻转
函数:DataAugment()
函数功能:扩大数据量
输入参数:dir_path----图片库路径
'''
import cv2
import os
import copy
def DataAugment(dir_path):
if not os.path.exists(dir_path):
print('路径不存在')
else:
dirs = os.listdir(dir_path)
for subdir in dirs:
sub_dir = dir_path + '/' + subdir
img = cv2.imread(sub_dir)
size = img.shape # 获得图像的形状
iLR = copy.deepcopy(img) # 获得一个和原始图像相同的图像,注意这里要使用深度复制
h = size[0]
w = size[1]
for i in range(h): # 元素循环
for j in range(w):
iLR[i, w - 1 - j] = img[i, j] # 注意这里的公式没,是不是恍然大悟了(修改这里)
new_name = "%s" % (sub_dir)
cv2.imwrite(new_name, iLR)
print('done')
DataAugment(r"E:\python\ultrasoundSoundAugmentation-main\image\imaged")
# 地址中不能有中文字符,否则会报错
2 PIL中的Image方法
代码:
# coding: utf-8
# 作者:小星星
from PIL import Image
import os
import os.path
# rootdir = r'D:\用户目录\我的图片\From Yun\背景图\背景图' # 指明被遍历的文件夹
rootdir = r'E:\python\ultrasoundSoundAugmentation-main\image\malignant'
for parent, dirnames, filenames in os.walk(rootdir): # 遍历图片
for filename in filenames:
print('parent is :' + parent)
print('filename is :' + filename)
currentPath = os.path.join(parent, filename)
print('the fulll name of the file is :' + currentPath)
im = Image.open(currentPath)
out = im.transpose(Image.FLIP_LEFT_RIGHT) # 实现翻转
# newname=r"D:\用户目录\我的图片\From Yun\背景图\背景图反转"+'\\'+filename+"(1).jpg"
newname = r"E:\python\ultrasoundSoundAugmentation-main\image_hou\malignant" + '\\' + filename +'.jpg' # 重新命名
out.save(newname) # 保存结束
# im = Image.open(r'C:\Users\Administrator\Desktop\新建文件夹 (2)\1.jpg')
# out = im.transpose(Image.FLIP_LEFT_RIGHT)
# out.save(r'C:\Users\Administrator\Desktop\新建文件夹 (2)\test2.jpg')
二、旋转
翻转有两种情况 一种随机角度翻转,一种是固定角度。本打算将我的数据集分别按照15°、-15°、30°、-30°扩大四倍,但是再找代码的时候发现旋转角度只有为90°的倍数才会不出现下面这样的黑边。
`
先放代码:
代码1:
# -*- coding:utf-8 -*-
from math import *
import cv2
import numpy as np
import os
def rotate_bound1(image, angle):
(h, w) = image.shape[:2] # 返回(高,宽,色彩通道数),此处取前两个值返回
# 抓取旋转矩阵(应用角度的负值顺时针旋转)。参数1为旋转中心点;参数2为旋转角度,正的值表示逆时针旋转;参数3为各向同性的比例因子
M = cv2.getRotationMatrix2D((w / 2, h / 2), -angle, 1.0)
newW = int((h * np.abs(M[0, 1])) + (w * np.abs(M[0, 0])))
newH = int((h * np.abs(M[0, 0])) + (w * np.abs(M[0, 1])))
# 调整旋转矩阵以考虑平移
M[0, 2] += (newW - w) / 2
M[1, 2] += (newH - h) / 2
# 执行实际的旋转并返回图像
return cv2.warpAffine(image, M, (newW, newH)) # borderValue 缺省,默认是黑色
if __name__ == '__main__':
path_original = "E:/python/ultrasoundSoundAugmentation-main/1/a/" # 原文件夹,要求文件夹只含有图片
path_target = "E:/python/ultrasoundSoundAugmentation-main/2/" # 目标文件夹
path_images = os.listdir(path_original)
for path_image in path_images:
path_absolute = '{}//{}'.format(path_original, path_image) # 构造绝对路径
# 读取图片
img_origin = cv2.imread(path_absolute)
img = rotate_bound1(img_origin, 30)
cv2.waitKey(100)
path_save ='{}//{}'.format(path_target, path_image) # 构造
cv2.imwrite(path_save, img)
代码2:
import scipy
from scipy import misc
import os
import time
import glob
from scipy import ndimage
def get_image_paths(folder):
return glob.glob(os.path.join(folder, '*.jpg'))
def create_read_img(filename):
im = misc.imread(filename)
img_rote_30 = ndimage.rotate(im, 90)
scipy.misc.imsave(filename[:-4]+'_90.jpg',img_rote_30)
img_rote_15 = ndimage.rotate(im, 180)
scipy.misc.imsave(filename[:-4]+'_180.jpg',img_rote_15)
img_rote_345 = ndimage.rotate(im, 270)
scipy.misc.imsave(filename[:-4] + '_270.jpg', img_rote_345)
print(filename)
img_path = 'E:/python/ultrasoundSoundAugmentation-main/1/a/' #这个路径是所有图片在的位置
imgs = get_image_paths(img_path)
print (imgs)
for i in imgs:
create_read_img(i)
上面的两段代码 都可以按照固定的度数旋转,但是,旋转不是90度的度数时,会出现黑边。因此我又利用**Keras中的ImageDataGenerator( )**图片生成器。此函数可以随机旋转一定的度数,黑边会自动弥补上,但缺点是不能固定度数,随机性太强。
首先对ImageDataGenerator()介绍
keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
zca_epsilon=1e-6,
rotation_range=0.,
width_shift_range=0.,
height_shift_range=0.,
shear_range=0.,
zoom_range=0.,
channel_shift_range=0.,
fill_mode='nearest',
cval=0.,
horizontal_flip=False,
vertical_flip=False,
rescale=None,
preprocessing_function=None,
data_format=K.image_data_format())
参数讲解:featurewise_center:布尔值,使输入数据集去中心化(均值为0), 按feature执行
samplewise_center:布尔值,使输入数据的每个样本均值为0
featurewise_std_normalization:布尔值,将输入除以数据集的标准差以完成标准化, 按feature执行
samplewise_std_normalization:布尔值,将输入的每个样本除以其自身的标准差
zca_whitening:布尔值,对输入数据施加ZCA白化
zca_epsilon: ZCA使用的eposilon,默认1e-6
rotation_range:整数,数据提升时图片随机转动的角度
width_shift_range:浮点数,图片宽度的某个比例,数据提升时图片水平偏移的幅度
height_shift_range:浮点数,图片高度的某个比例,数据提升时图片竖直偏移的幅度
shear_range:浮点数,剪切强度(逆时针方向的剪切变换角度)
zoom_range:浮点数或形如[lower,upper]的列表,随机缩放的幅度,若为浮点数,则相当于[lower,upper] = [1 - zoom_range, 1+zoom_range]
channel_shift_range:浮点数,随机通道偏移的幅度
fill_mode:;‘constant’,‘nearest’,‘reflect’或‘wrap’之一,当进行变换时超出边界的点将根据本参数给定的方法进行处理
cval:浮点数或整数,当fill_mode=constant时,指定要向超出边界的点填充的值
horizontal_flip:布尔值,进行随机水平翻转
vertical_flip:布尔值,进行随机竖直翻转
rescale: 重放缩因子,默认为None. 如果为None或0则不进行放缩,否则会将该数值乘到数据上(在应用其他变换之前)
preprocessing_function: 将被应用于每个输入的函数。该函数将在图片缩放和数据提升之后运行。该函数接受一个参数,为一张图片(秩为3的numpy array),并且输出一个具有相同shape的numpy array
data_format:字符串,“channel_first”或“channel_last”之一,代表图像的通道维的位置。该参数是Keras 1.x中的image_dim_ordering,“channel_last”对应原本的“tf”,“channel_first”对应原本的“th”。以128x128的RGB图像为例,“channel_first”应将数据组织为(3,128,128),而“channel_last”应将数据组织为(128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channel_last”
详细代码:
from keras.preprocessing.image import ImageDataGenerator
path = 'E:/python/ultrasoundSoundAugmentation-main/1' # 类别子文件夹的上一级
dst_path = 'E:/python/ultrasoundSoundAugmentation-main/2/malignant'
# 图片生成器
datagen = ImageDataGenerator(
rotation_range = 170,
# width_shift_range = 0.02,
# height_shift_range = 0.02,
# shear_range = 0.02,
# horizontal_flip = False,
vertical_flip = True
)
gen = datagen.flow_from_directory(
path,
target_size = (224,224),
batch_size =29,
save_to_dir = dst_path,
# 生成后的图像保存路径
save_prefix = 'xx',
save_format = 'jpg')
for i in range(200):
gen.next()
最后生成batch_size*range( )张图片,注意batch_size尽量设置为能被文件数整除。
增强结果: