How to warp an image using deformed mesh

(1) Use cv2.copyMakeBorder to enlarge the image, to avoid the warpped points going out of range of the original image size.

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. The nh, nw is the height and width of the source image.

(2) Create perturbed mesh grid using the method from the paper

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:

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:

enter image description here

(4) Crop the nonzero region and resize if necessary:

enter image description here


Related:

  1. Converting opencv remap code from c++ to python

  2. Split text lines in scanned document

Leave a Comment