Dense Deformation(Elastic deformation)的采样与可视化
对于采样(sample)而言,分为前向与后向。前向直观上更容易理解,但实际应用会有问题,因此,算法中的采样操作一般为后向。
采样
前向采样:
- 将输入图像坐标
p1
根据DDF(Dense deformation Feild)
或Affine Matrix
或其他方式进行变换得到坐标p2
,输入图像p1
坐标处的值 映射到输出图像p2
处。
伪代码示例:
#与input_image shape一致的空矩阵
output_image = empty_array()
for row in input_image.height:
for col in input_image.width:
# 或者 dx,dy = Affinematrix*[row,col]
dx,dy = random(),random()
output_image[row+dy,col+dx] = input_image[row,col]
这样会出现的问题是,output_image中,很多坐标上没有值。而后向采样就能解决这个问题。
后向采样:
- 将输出图像坐标
p1
根据DDF(Dense deformation Feild)
或Affine Matrix的逆
或其他方式进行变换得到坐标p2
,输出图像p1
坐标处的值 根据输入图像p2
坐标处经过插值算法得到的像素值确定。
伪代码示例:
#与input_image shape一致的空矩阵
output_image = empty_array()
for row in output_image.height:
for col in output_image.width:
# 或者 dx,dy = Affinematrix_inverse*[row,col]
dx,dy = random(),random()
# 根据插值算法,得到input_image中(row+dy,col+dx)处的像素值
value = interpolate(input_image,row+dy,col+dx)
output_image[row,col] = value
由伪代码也易看出,后向采样可以确保输出图像中每个坐标都有对应的像素值(若row+dy或col+dx超出输入图像范围,value=None,则是变形的结果,而不是输出图像这一坐标没有值)
(更新)旋转
(2020-6-24)在实现图像旋转时同样遇到了前向采样、后向采样这个问题,觉得很容易弄糊涂,特此记录下自己的一点理解。
已知旋转矩阵(具体推导见后文)为
[ c o s θ − s i n θ s i n θ c o s θ ] \begin{bmatrix} cos\theta &-sin\theta \\ sin\theta& cos\theta \end{bmatrix} [cosθsinθ−sinθcosθ]
其中的 θ \theta θ定义了逆时针旋转的角度(没有特别说明时,旋转中心即图像原点,此处也就是图像左上角)。下面的代码将一个横条旋转了30度。
def warpRotate(image, matrix):
height, width = image.shape[:2]
dst = np.zeros((height, width))
for x in range(height):
for y in range(width):
u = int(x*matrix[0,0]+y*matrix[0,1])
v = int(x*matrix[1,0]+y*matrix[1,1])
# 为了直观,这儿用的是前向采样
if (u >= 0 and u < height) and (v >= 0 and v < width):
dst[u,v] = image[x,y]
return dst
#定义原始图像
size = 11
img = np.zeros((size, size))
img[int((size-1)/2), :] = np.ones(size)
#定义旋转矩阵
theta = np.radians(30)
c, s = np