图像增强之弹性扭曲
准备条件:python环境(必要库,python-opencv,numpy,matplotlib)
import cv2
import numpy as np
import matplotlib.pyplot as pltprint('start')image = cv2.imread(r'C:\software\Fashion_Landmark_Detection_and_Category_Classification-master\images\CTU\3.jpg')# 使用cv2.imread()函数读取图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #BGR格式转换成RGB格式
image = cv2.resize(image, (28,28)) #图像缩放
# print(image.shape[0:2])# define constants 定义常量
img_height, img_width = image.shape[:2] #获取图像的高度和宽度
alpha = 60 #均匀分布参数α = 600
sigma = 4 #高斯滤波器方差参数 σ = 40
kernel_size = 2*int(4*sigma)+1 #内核尺寸# define random generator 定义随机生成器
random_state = np.random.RandomState(17)for k in range(1):dx = np.zeros((img_height, img_width)) #生成img_height*img_width的零矩阵dy = np.zeros((img_height, img_width)) #生成img_height*img_width的零矩阵# print(dx.sum())# print(dy.sum())for i in range(1):x_idx = int(random_state.rand(1)*img_width)#随机生成0~1之间数乘以矩阵的宽度得到该点在矩阵的列号y_idx = int(random_state.rand(1)*img_height)#随机生成0~1之间数乘以矩阵的高度得到该点在矩阵的行号x_value = alpha*(random_state.rand(1)*2-1) #随机生成-1~1之间的值,在乘以alpha即是均匀分布得到X的值y_value = alpha*(random_state.rand(1)*2-1) #随机生成-1~1之间的值,在乘以alpha即是均匀分布得到Y的值dx[y_idx, x_idx] = x_value #给矩阵中相应的X的值dy[y_idx, x_idx] = y_value #给矩阵中相应的Y的值# print(dx.sum())# print(dy.sum())
# cv2.GussianBlur()函数
# 语法:GaussianBlur(src,ksize,sigmaX [,dst [,sigmaY [,borderType]]])-> dst
# ——src输入图像;图像可以具有任意数量的通道,这些通道可以独立处理,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
# ——dst输出图像的大小和类型与src相同。
# ——ksize高斯内核大小。 ksize.width和ksize.height可以不同,但它们都必须为正数和奇数,也可以为零,然后根据sigma计算得出。
# ——sigmaX X方向上的高斯核标准偏差。
# ——sigmaY Y方向上的高斯核标准差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigmas为零,则分别从ksize.width和ksize.height计算得出;为了完全控制结果,而不管将来可能对所有这些语义进行的修改,建议指定所有ksize,sigmaX和sigmaY。tmp1 = cv2.GaussianBlur(dx,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)# print(tmp1.min())# print(tmp1.max())# print(tmp1.sum())print(tmp1.shape)tmp2 = cv2.GaussianBlur(dy,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)# print(tmp2.min())# print(tmp2.max())# print(tmp2.sum())print(tmp2.shape)dx_smooth = alpha * cv2.GaussianBlur(dx,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)dy_smooth = alpha * cv2.GaussianBlur(dy,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)# print(dx_smooth.min())# print(dx_smooth.max())# print(dx_smooth.sum())# print(dy_smooth.min())# print(dy_smooth.max())# print(dy_smooth.sum())# create coordinate maps src_coordinate + delta_coordinatex, y = np.meshgrid(np.arange(img_width), np.arange(img_height)) #np.arange函数返回一个有终点和起点的固定步长的排列类似range()# print(x)# print(y)
# [X, Y] = meshgrid(x, y)
# 将向量x和y定义的区域转换成矩阵X和Y, 其中矩阵X的行向量是向量x的简单复制,而矩阵Y的列向量是向量y的简单复制(注:下面代码中X和Y均是数组,在文中统一称为矩阵了)。map_x = np.float32(x+dx_smooth)map_y = np.float32(y+dy_smooth)# print(map_x)# print(map_y)print(image.shape)print(image)new_image = cv2.remap(image, map_x, map_y, cv2.INTER_LINEAR, cv2.BORDER_CONSTANT)#print(new_image.shape)print(new_image)print(new_image-image)
# INTER_NEAREST(最近邻插值),INTER_LINEAR(双线性插值(默认设置)),
# INTER_CUBIC(4x4像素邻域的双三次插值),INTER_LANCZOS4(8x8像素邻域的Lanczos插值)
# INTER_AREA(使用像素区域关系进行重采样。 它可能是图像抽取的首选方法,
# 因为它会产生无云纹理的结果。 但是当图像缩放时,它类似于INTER_NEAREST方法。)fig = plt.figure(4)ax1 = fig.add_subplot(131)#比如121,指的就是将这块画布分为1×2,然后1对应的就是1号区,2对应的2号区ax1.imshow(image)ax2 = fig.add_subplot(132)ax2.imshow(new_image)ax3 = fig.add_subplot(133)ax3.imshow(new_image-image)plt.show(block=False)#关闭图像以便下一步的执行plt.pause(1)#停顿一秒plt.close('all')#关闭图像
cv2.remap()函数解析
将一幅图像内的像素点放置到另外一幅图像内的指定位置即为重映射
函数形式为
dst = cv2.remap( src , map1 , map2 ,interpolation [, borderMode [ , borderValue]])
dst 代表目标图像,它和src具有相同的大小和类型
src代表原始图像
map1
1.表示(x,y)点的一个映射
2.表示CV _16SC2 , CV_32FC1 ,CV_32FC2类型(x,y)点的x值
map2
1.当map1表示(x,y)时,该值为空
2.当map1表示(x,y)点的x值时,该值是CV_16UC1,CV_32FC1类型(x,y)点的y值
interpolation代表插值方式,这里不支持INTER_AREA
borderMode代表边界模式,
borderValue代表边界值,该值默认为0
以下为将原始图像内第0行第3列上的像素值映射到所有像素点,即map1为3,map2为0
其映射关系即为map1和map2对应的像素位置对应图像的像素点的位置,即map1和map2的[0,0]对应图像的[0,0],然后将结果位置值存入该点,即map1存第几列,map2存第几行。对应以下代码即每个点映射的都是[0,3]的值
示例图
图像增强之弹性扭曲
准备条件:python环境(必要库,python-opencv,numpy,matplotlib)
import cv2
import numpy as np
import matplotlib.pyplot as pltprint('start')image = cv2.imread(r'C:\software\Fashion_Landmark_Detection_and_Category_Classification-master\images\CTU\3.jpg')# 使用cv2.imread()函数读取图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #BGR格式转换成RGB格式
image = cv2.resize(image, (28,28)) #图像缩放
# print(image.shape[0:2])# define constants 定义常量
img_height, img_width = image.shape[:2] #获取图像的高度和宽度
alpha = 60 #均匀分布参数α = 600
sigma = 4 #高斯滤波器方差参数 σ = 40
kernel_size = 2*int(4*sigma)+1 #内核尺寸# define random generator 定义随机生成器
random_state = np.random.RandomState(17)for k in range(1):dx = np.zeros((img_height, img_width)) #生成img_height*img_width的零矩阵dy = np.zeros((img_height, img_width)) #生成img_height*img_width的零矩阵# print(dx.sum())# print(dy.sum())for i in range(1):x_idx = int(random_state.rand(1)*img_width)#随机生成0~1之间数乘以矩阵的宽度得到该点在矩阵的列号y_idx = int(random_state.rand(1)*img_height)#随机生成0~1之间数乘以矩阵的高度得到该点在矩阵的行号x_value = alpha*(random_state.rand(1)*2-1) #随机生成-1~1之间的值,在乘以alpha即是均匀分布得到X的值y_value = alpha*(random_state.rand(1)*2-1) #随机生成-1~1之间的值,在乘以alpha即是均匀分布得到Y的值dx[y_idx, x_idx] = x_value #给矩阵中相应的X的值dy[y_idx, x_idx] = y_value #给矩阵中相应的Y的值# print(dx.sum())# print(dy.sum())
# cv2.GussianBlur()函数
# 语法:GaussianBlur(src,ksize,sigmaX [,dst [,sigmaY [,borderType]]])-> dst
# ——src输入图像;图像可以具有任意数量的通道,这些通道可以独立处理,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
# ——dst输出图像的大小和类型与src相同。
# ——ksize高斯内核大小。 ksize.width和ksize.height可以不同,但它们都必须为正数和奇数,也可以为零,然后根据sigma计算得出。
# ——sigmaX X方向上的高斯核标准偏差。
# ——sigmaY Y方向上的高斯核标准差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigmas为零,则分别从ksize.width和ksize.height计算得出;为了完全控制结果,而不管将来可能对所有这些语义进行的修改,建议指定所有ksize,sigmaX和sigmaY。tmp1 = cv2.GaussianBlur(dx,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)# print(tmp1.min())# print(tmp1.max())# print(tmp1.sum())print(tmp1.shape)tmp2 = cv2.GaussianBlur(dy,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)# print(tmp2.min())# print(tmp2.max())# print(tmp2.sum())print(tmp2.shape)dx_smooth = alpha * cv2.GaussianBlur(dx,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)dy_smooth = alpha * cv2.GaussianBlur(dy,(kernel_size, kernel_size),sigmaX=sigma,sigmaY=sigma,borderType=cv2.BORDER_CONSTANT)# print(dx_smooth.min())# print(dx_smooth.max())# print(dx_smooth.sum())# print(dy_smooth.min())# print(dy_smooth.max())# print(dy_smooth.sum())# create coordinate maps src_coordinate + delta_coordinatex, y = np.meshgrid(np.arange(img_width), np.arange(img_height)) #np.arange函数返回一个有终点和起点的固定步长的排列类似range()# print(x)# print(y)
# [X, Y] = meshgrid(x, y)
# 将向量x和y定义的区域转换成矩阵X和Y, 其中矩阵X的行向量是向量x的简单复制,而矩阵Y的列向量是向量y的简单复制(注:下面代码中X和Y均是数组,在文中统一称为矩阵了)。map_x = np.float32(x+dx_smooth)map_y = np.float32(y+dy_smooth)# print(map_x)# print(map_y)print(image.shape)print(image)new_image = cv2.remap(image, map_x, map_y, cv2.INTER_LINEAR, cv2.BORDER_CONSTANT)#print(new_image.shape)print(new_image)print(new_image-image)
# INTER_NEAREST(最近邻插值),INTER_LINEAR(双线性插值(默认设置)),
# INTER_CUBIC(4x4像素邻域的双三次插值),INTER_LANCZOS4(8x8像素邻域的Lanczos插值)
# INTER_AREA(使用像素区域关系进行重采样。 它可能是图像抽取的首选方法,
# 因为它会产生无云纹理的结果。 但是当图像缩放时,它类似于INTER_NEAREST方法。)fig = plt.figure(4)ax1 = fig.add_subplot(131)#比如121,指的就是将这块画布分为1×2,然后1对应的就是1号区,2对应的2号区ax1.imshow(image)ax2 = fig.add_subplot(132)ax2.imshow(new_image)ax3 = fig.add_subplot(133)ax3.imshow(new_image-image)plt.show(block=False)#关闭图像以便下一步的执行plt.pause(1)#停顿一秒plt.close('all')#关闭图像
cv2.remap()函数解析
将一幅图像内的像素点放置到另外一幅图像内的指定位置即为重映射
函数形式为
dst = cv2.remap( src , map1 , map2 ,interpolation [, borderMode [ , borderValue]])
dst 代表目标图像,它和src具有相同的大小和类型
src代表原始图像
map1
1.表示(x,y)点的一个映射
2.表示CV _16SC2 , CV_32FC1 ,CV_32FC2类型(x,y)点的x值
map2
1.当map1表示(x,y)时,该值为空
2.当map1表示(x,y)点的x值时,该值是CV_16UC1,CV_32FC1类型(x,y)点的y值
interpolation代表插值方式,这里不支持INTER_AREA
borderMode代表边界模式,
borderValue代表边界值,该值默认为0
以下为将原始图像内第0行第3列上的像素值映射到所有像素点,即map1为3,map2为0
其映射关系即为map1和map2对应的像素位置对应图像的像素点的位置,即map1和map2的[0,0]对应图像的[0,0],然后将结果位置值存入该点,即map1存第几列,map2存第几行。对应以下代码即每个点映射的都是[0,3]的值
示例图