使用 scikit-image 实现弹性变形

257 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

前言

对图像应用位移场( displacement fields )可以产生图像畸变,通过位移场可以计算每个像素原始位置的新目标位置。位置 (x,y)(x,y) 处的新目标位置根据原位置得出,例如,如果 ΔX(x,y)=1ΔX(x,y)=1Δy(x,y)=0Δy(x,y)=0 这意味着每个像素的新位置都向右移动 1。我们可以通过以下步骤创建图像弹性变形:

  • 首先,生成随机位移场,即 Δy(x,y)=rand(1,+1)Δy(x,y)= rand(-1,+1)Δx(x,y)=rand(1,+1)Δx(x,y)= rand(-1,+1),其中 rand(1,+1)rand(-1,+1) 用于生成一个在 -11 之间的随机数
  • 然后用标准偏差为 σσ 的高斯函数(以像素为单位)与 ΔxΔxΔyΔy 执行卷积
  • 如果 σσ 很大,因为随机值的平均值为 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) 使用 matplotlibimread() 函数读取输入图像,并使用 skimage.colorrgb2gray() 函数将其转换为灰度图像:

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()

Figure_7.png