[英]How to warp an image using deformed mesh
I'm trying to generate "crumpled" images using images obtained from a flatbed bed scanner.我正在尝试使用从平板扫描仪获得的图像生成“皱巴巴”的图像。
By following the method described in the paper [Link] in the section 3.1.按照3.1节中论文[链接]中描述的方法。 I've written the code generate the perturbed mesh but I don't know how to map this pixels from source image onto this mesh to form the perturbed image.
我已经编写了生成扰动网格的代码,但我不知道如何将源图像中的 map 这个像素添加到该网格上以形成扰动图像。
This is the code to generate the perturbed mesh.这是生成扰动网格的代码。
import numpy as np
import matplotlib.pyplot as plt
mr = 88
mc = 68
xx = np.arange(mr-1, -1, -1)
yy = np.arange(0, mc, 1)
[Y, X] = np.meshgrid(xx, yy)
ms = np.transpose(np.asarray([X.flatten('F'), Y.flatten('F')]), (1,0))
perturbed_mesh = ms
nv = np.random.randint(20) - 1
for k in range(nv):
#Choosing one vertex randomly
vidx = np.random.randint(np.shape(ms)[0])
vtex = ms[vidx, :]
#Vector between all vertices and the selected one
xv = perturbed_mesh - vtex
#Random movement
mv = (np.random.rand(1,2) - 0.5)*20
hxv = np.zeros((np.shape(xv)[0], np.shape(xv)[1] +1) )
hxv[:, :-1] = xv
hmv = np.tile(np.append(mv, 0), (np.shape(xv)[0],1))
d = np.cross(hxv, hmv)
d = np.absolute(d[:, 2])
d = d / (np.linalg.norm(mv, ord=2))
wt = d
curve_type = np.random.rand(1)
if curve_type > 0.3:
alpha = np.random.rand(1) * 50 + 50
wt = alpha / (wt + alpha)
else:
alpha = np.random.rand(1) + 1
wt = 1 - (wt / 100 )**alpha
msmv = mv * np.expand_dims(wt, axis=1)
perturbed_mesh = perturbed_mesh + msmv
plt.scatter(perturbed_mesh[:, 0], perturbed_mesh[:, 1], c=np.arange(0, mr*mc))
plt.show()
This is how the perturbed mesh looks like:这是扰动网格的样子:
This is the screenshot from the paper illustrating the synthetic image generation:这是说明合成图像生成的论文的屏幕截图:
Sample source image for testing: https://i.stack.imgur.com/26KN4.jpg用于测试的示例源图像: https://i.stack.imgur.com/26KN4.jpg
I'm stuck with mapping the source image pixels onto the mesh.我坚持将源图像像素映射到网格上。 I'll be grateful if someone can help.
如果有人可以提供帮助,我将不胜感激。
(1) Use cv2.copyMakeBorder
to enlarge the image, to avoid the warpped points going out of range of the original image size. (1) 使用
cv2.copyMakeBorder
放大图像,避免扭曲点超出原始图像尺寸范围。
cv2.copyMakeBorder(...)
copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) -> dst
. @brief Forms a border around an image.
.
. The function copies the source image into the middle of the destination image. The areas to the
. left, to the right, above and below the copied source image will be filled with extrapolated
. pixels. This is not what filtering functions based on it do (they extrapolate pixels on-fly), but
. what other more complex functions, including your own, may do to simplify image boundary handling.
useage:用途:
img = cv2.copyMakeBorder(img, dh, dh, dw, dw, borderType=cv2.BORDER_CONSTANT, value=(0,0,0))
Set dw=nw//2, dh=nh//2
maybe ok, adjust if necessary.设置
dw=nw//2, dh=nh//2
可能没问题,必要时调整。 The nh, nw
is the height and width of the source image. nh, nw
是源图像的高度和宽度。
(2) Create perturbed mesh grid using the method from the paper (2) 使用论文中的方法创建扰动网格
xs, ys = create_grid() # the result is like np.meshgrid
Notice make sure the type and the size.注意确定类型和尺寸。
# xs = xs.reshape(nh, nw).astype(np.float32)
# nh, nw is the height and width of the coppied image
(3) Use cv2.remap
to remap: (3) 使用
cv2.remap
重新映射:
cv2.remap(...)
remap(src, map1, map2, interpolation[, dst[, borderMode[, borderValue]]]) -> dst
. @brief Applies a generic geometrical transformation to an image.
.
. The function remap transforms the source image using the specified map:
. \f[\texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y))\f]
usage:用法:
dst= cv2.remap(img, xs, ys, cv2.INTER_CUBIC)
This is a demo result:这是一个演示结果:
(4) Crop the nonzero region and resize if necessary: (4) 裁剪非零区域并在必要时调整大小:
Related:有关的:
I'm leaving a minimum working demo for other readers.我要为其他读者留下一个最低限度的工作演示。
Currently, trying to figure out in which condition perturbed_mesh
becomes None
.目前,试图找出在哪种情况下
perturbed_mesh
变为None
。
def deform(img, perturbed_mesh):
h,w = img.shape[:2]
perturbed_mesh_x = perturbed_mesh[:,0]
perturbed_mesh_y = perturbed_mesh[:,1]
perturbed_mesh_x =perturbed_mesh_x.reshape((h,w))
perturbed_mesh_y =perturbed_mesh_y.reshape((h,w))
remapped = cv2.remap(img, perturbed_mesh_x, perturbed_mesh_y, cv2.INTER_LINEAR)
return remapped
def get_perturbed_mesh(img):
"""
Author: papabiceps
https://stackoverflow.com/q/53907633
"""
# mesh row & col
mr,mc = img.shape[:2]
xx = np.arange(0, mr, 1)
yy = np.arange(mc-1, -1, -1)
# yy = np.arange(0, mc, 1)
[Y, X] = np.meshgrid(xx, yy)
ms = np.transpose(np.asarray([X.flatten('F'), Y.flatten('F')]), (1,0))
perturbed_mesh = ms
nv = np.random.randint(20) - 1
for k in range(nv):
#Choosing one vertex randomly
vidx = np.random.randint(np.shape(ms)[0])
vtex = ms[vidx, :]
#Vector between all vertices and the selected one
xv = perturbed_mesh - vtex
#Random movement
mv = (np.random.rand(1,2) - 0.5)*20
hxv = np.zeros((np.shape(xv)[0], np.shape(xv)[1] +1) )
hxv[:, :-1] = xv
hmv = np.tile(np.append(mv, 0), (np.shape(xv)[0],1))
d = np.cross(hxv, hmv)
d = np.absolute(d[:, 2])
d = d / (np.linalg.norm(mv, ord=2))
wt = d
curve_type = np.random.rand(1)
if curve_type > 0.3:
alpha = np.random.rand(1) * 50 + 50
wt = alpha / (wt + alpha)
else:
alpha = np.random.rand(1) + 1
wt = 1 - (wt / 100 )**alpha
msmv = mv * np.expand_dims(wt, axis=1)
perturbed_mesh = perturbed_mesh + msmv
perturbed_mesh = perturbed_mesh.astype(np.float32)
if perturbed_mesh is not None:
result = deform(img, perturbed_mesh)
flipped = cv2.flip(result,1)
cv2.imshow("before",result)
cv2.imshow("after",flipped)
cv2.waitKey(0)
def main():
img = cv2.imread("./sample.png")
get_perturbed_mesh(img)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.