开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
前言
对图像应用位移场( displacement fields )可以产生图像畸变,通过位移场可以计算每个像素原始位置的新目标位置。位置 处的新目标位置根据原位置得出,例如,如果 、 这意味着每个像素的新位置都向右移动 1。我们可以通过以下步骤创建图像弹性变形:
- 首先,生成随机位移场,即 、,其中 用于生成一个在
-1和1之间的随机数 - 然后用标准偏差为 的高斯函数(以像素为单位)与 、 执行卷积
- 如果 很大,因为随机值的平均值为
0,则将导致结果值非常小,如果我们将位移场进行归一化,则位移场将接近具有随机方向的常数;如果 很小,则位移场在归一化后近似于完全随机的场。如果 值大小合适,位移场则类似弹性变形,其中 为弹性系数 - 然后将位移场乘以控制变形强度的缩放因子
使用 scikit-image 实现弹性变形
(1) 首先导入所需的库,然后自定义函数实现弹性变形函数 elastic_transform():
import numpy as np
import matplotlib.pylab as plt
from skimage.color import rgb2gray
from scipy.ndimage import gaussian_filter, map_coordinates
def elastic_transform(image, alpha, sigma):
random_state = np.random.RandomState(None)
h, w = image.shape
dx = gaussian_filter((random_state.rand(*image.shape) * 2 - 1), sigma, mode="constant", cval=0) * alpha
dy = gaussian_filter((random_state.rand(*image.shape) * 2 - 1), sigma, mode="constant", cval=0) * alpha
x, y = np.meshgrid(np.arange(w), np.arange(h))
indices = np.reshape(y+dy, (-1, 1)), np.reshape(x+dx, (-1, 1))
distored_image = map_coordinates(image, indices, order=1, mode='reflect')
return distored_image.reshape(image.shape)
函数 map_coordinates() 通过插值将输入阵列映射到新的坐标,坐标的数组用于为输出中的每个点找到输入中的相应坐标,这些坐标处的输入值由调用函数时所用的插值参数 order 确定。
(2) 使用 matplotlib 的 imread() 函数读取输入图像,并使用 skimage.color 的 rgb2gray() 函数将其转换为灰度图像:
img = rgb2gray(plt.imread('2.png'))
(3) 调用 elastic_transform() 函数将弹性变形应用于图像:
img1 = elastic_transform(img, 100, 4)
(4) 绘制原始输入和应用弹性形变后的输出图像:
plt.figure(figsize=(20,10))
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.axis('off'), plt.title('Original', size=10)
plt.subplot(122)
plt.imshow(img1, cmap='gray')
plt.axis('off'), plt.title('Deformed', size=10)
plt.tight_layout()