HOME/Articles/

pil example landmark tps (snippet)

Article Outline

Python pil example 'landmark tps'

Functions in program:

  • def morphops_tps(landmark_from, landmark_to, image, to_size):
  • def tps_warp_np(image, c_src, c_dst, dest_shape, bg=(255,255,255,0), reduced=True):
  • def tps_warp_pil(image : Image, c_src, c_dst, dest_size, bg=(255,255,255,0), reduced=True):

Modules used in program:

  • import cv2
  • import thinplate as tps
  • import cv2
  • import morphops
  • import thinplate as tps

python landmark tps

Python pil example: landmark tps

import thinplate as tps
from PIL import Image
import morphops
import cv2
# helper function for https://github.com/cheind/py-thin-plate-spline

import thinplate as tps
from PIL import Image
import cv2

def tps_warp_pil(image : Image, c_src, c_dst, dest_size, bg=(255,255,255,0), reduced=True):
    '''
    helper function for https://github.com/cheind/py-thin-plate-spline
    Returns TPS warped image with PIL image as input, 
    PIL is w x h while numpy is h x w. This function keeps the sanity between diamensions

            Parameters:
                    image (Image): PIL image
                    c_src (ndarray): centroid point of the source image (x, y). Normalized 0 to 1
                    c_dst (ndarray): centroid point of the desired destination image (x, y). Normalized 0 to 1
                    dest_size (tuple): Optional, destination image size, (w x h). if not provided source image size is taken.
                    bg (tuple or cv2 color, cv2 bordertype): bacground color to be filled 
                    reduced (bool) : Refer to tps.tps_theta_from_points for reference

            Returns:
                    warped_output (Image): Warped PIL image 
    '''
    dest_shape = dest_size[::-1] or image.size[::-1]
    theta = tps.tps_theta_from_points(c_src, c_dst, reduced=reduced)
    grid = tps.tps_grid(theta, c_dst, dest_shape)
    mapx, mapy = tps.tps_grid_to_remap(grid, image.size[::-1])
    warped_output = cv2.remap(np.array(image), mapx, mapy, cv2.INTER_CUBIC, borderValue=bg)
    return Image.fromarray(warped_output)



def tps_warp_np(image, c_src, c_dst, dest_shape, bg=(255,255,255,0), reduced=True):
    '''
    helper function for https://github.com/cheind/py-thin-plate-spline
    Returns TPS warped image with numpy image as input, 
    numpy image shapes are h x w. This function keeps the sanity between diamensions

            Parameters:
                    image (ndarray): numpy array image
                    c_src (ndarray): centroid point of the source image (x, y). Normalized 0 to 1
                    c_dst (ndarray): centroid point of the desired destination image (x, y). Normalized 0 to 1
                    dest_shape (tuple): Optional, destination image shape in numpy diamension sequence, (h, w). if not provided source image size is taken.
                    bg (tuple or cv2 color, cv2 bordertype): bacground color to be filled 
                    reduced (bool) : Refer to tps.tps_theta_from_points for reference

            Returns:
                    warped_output (ndarray): warped numpy image
    '''
    dest_shape = dest_shape or image.shape[:2]
    theta = tps.tps_theta_from_points(c_src, c_dst, reduced=reduced)
    grid = tps.tps_grid(theta, c_dst, dest_shape)
    mapx, mapy = tps.tps_grid_to_remap(grid, image.shape[:2])
    return cv2.remap(image, mapx, mapy, cv2.INTER_CUBIC, borderValue=bg)



def morphops_tps(landmark_from, landmark_to, image, to_size):
    '''
    morphops tps, considerably slower than https://github.com/cheind/py-thin-plate-spline
    '''
    xv, yv = np.meshgrid(np.arange(to_size[0]), np.arange(to_size[1]))

    pts = np.stack([xv.flatten(), yv.flatten()]).T

    maps = morphops.tps_warp(landmark_to, landmark_from, pts)

    maps2 = maps.reshape((to_size[1], to_size[0] ,2))
    mapx = maps2[...,1].astype(np.float32)
    mapy = maps2[...,0].astype(np.float32)

    img = cv2.remap(np.array(image), mapy, mapx, cv2.INTER_CUBIC, borderValue=(255,255,255,0))

    warped = Image.fromarray(img)
    return warped