最近在学习U-net,看到了它是通过弹性形变来扩充数据集,网络上搜了搜原理,参考数据增强:弹性变形(Elastic Distortion) - 知乎 (zhihu.com)
正巧大作业是相关于宝塔纹的图像分割,老师只给了12张图片,于是准备应用弹性形变扩充数据集。
代码如下:
import cv2
import numpy as np
import os.path
import copy
from numpy.random import random
from scipy.ndimage.filters import gaussian_filter
from scipy.ndimage.interpolation import map_coordinates
#参数
def elastic_para1(image, alpha, sigma,
alpha_affine, random_state=None):
if random_state is None:
random_state = np.random.RandomState(None)
shape = image.shape
shape_size = shape[:2]
# Random affine
center_square = np.float32(shape_size) // 2
square_size = min(shape_size) // 3
# pts1: 仿射变换前的点(3个点)
pts1 = np.float32([center_square + square_size,
[center_square[0] + square_size,
center_square[1] - square_size],
center_square - square_size])
# pts2: 仿射变换后的点
pts2 = pts1 + random_state.uniform(-alpha_affine, alpha_affine,
size=pts1.shape).astype(np.float32)
return pts1,pts2
def elastic_para2(image,pts1,pts2,random_state=None):
if random_state is None:
random_state = np.random.RandomState(None)
shape = image.shape
shape_size = shape[:2]
# 仿射变换矩阵
M = cv2.getAffineTransform(pts1, pts2)
# 对image进行仿射变换.
imageB = cv2.warpAffine(image, M, shape_size[::-1], borderMode=cv2.BORDER_REFLECT_101)
return imageB
def para3(image, alpha, sigma,
alpha_affine, random_state=None):
if random_state is None:
random_state = np.random.RandomState(None)
shape = image.shape
shape_size = shape[:2]
# generate random displacement fields
# random_state.rand(*shape)会产生一个和shape一样打的服从[0,1]均匀分布的矩阵
# *2-1是为了将分布平移到[-1, 1]的区间, alpha是控制变形强度的变形因子
dx = gaussian_filter((random_state.rand(*shape) * 2 - 1), sigma) * alpha
dy = gaussian_filter((random_state.rand(*shape) * 2 - 1), sigma) * alpha
# generate meshgrid
x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
# x+dx,y+dy
return x,y,dx,dy
#单次变换
def _single_elastic(image,imageB,x, y,
dx, dy):
shape = image.shape
print(shape)
indices = np.reshape(y + dy, (-1, 1)), np.reshape(x + dx, (-1, 1))
elastic_image = map_coordinates(imageB, indices, order=1, mode='constant').reshape(shape)
return elastic_image
def elastic(image, alpha, sigma,
alpha_affine, random_state=None):
shape = image.shape
print(shape)
is_color = len(image.shape) == 3
pts1,pts2 = elastic_para1(image[:,:,2], alpha, sigma, alpha_affine, random_state=None)
x, y, dx, dy = para3(image[:,:,2], alpha, sigma, alpha_affine, random_state=None)
if is_color:
# 如果是彩色图像,则单独处理每个通道
result_channels = []
# for channel in range(image.shape[2]):
a = 3
for channel in range(a):
imageB = elastic_para2(image[:, :, channel],pts1,pts2,random_state)
result_channel = _single_elastic(image[:, :, channel],imageB,x,y,dx,dy)
# [:, :, channel]切片,[所以行,所有列,通道]
print(channel)
result_channels.append(result_channel) # append往列表里加东西
return np.stack(result_channels, axis=2) # stack函数是用于沿着指定的轴将一系列数组堆叠起来的。
# axis=2参数指定了新的轴是第三个维度(维度从0开始计数,所以0是高度,1是宽度,2是颜色通道)
else:
# 如果是单通道图像,直接处理
return _single_elastic(image,x,y,dx,dy)
file_dir = r'E:/1_project/unet-pytorch-main/unet-pytorch-main/img/'
for img_name in os.listdir(file_dir):
img_path = file_dir + img_name
img = cv2.imread(img_path)
img_elastic = elastic(img, 200, 80,80)
cv2.imwrite(file_dir + img_name[0:-4] + '_elastic.jpg', img_elastic)
print(img_name[0:-4])
原理代码参考:数据增强:弹性变形(Elastic Distortion) - 知乎 (zhihu.com)
其他数据增强方法:图像增强python代码_python图像增强代码越长越好-CSDN博客
深度学习小白,有不对的地方请大佬指正。
上边代码三通道(彩色)可以应用,单通道灰度图会变成三通道,因为我作业用的是彩色图片,所以这块我还没改。后续可能会更新。
我的代码水平差的很......努力学习中!