Yeah. Below is a Python script. I used OpenCV to transform image by coordinates.

import numpy as np

import cv2 as cv2

def toHomo(mx, my, width, height, focal, ppU, ppV):

scale = max(width, height)

px = ((mx - width / 2) / scale - ppU) * 35.0 / focal

py = ((my - height / 2) / scale - ppV) * 35.0 / focal

return px, py

def fromHomo(px, py, width, height, focal, ppU, ppV):

scale = max(width, height)

mx = (px * focal / 35 + ppU) * scale + width / 2

my = (py * focal / 35 + ppV) * scale + height / 2

return mx, my

def brownDistortion(x0, y0, k1, k2, k3, p1, p2):

x2 = x0 * x0

y2 = y0 * y0

xy = x0 * y0

r2 = x2 + y2

k = 1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2

tx = p1 * (r2 + x2) + 2 * p2 * xy

ty = p2 * (r2 + y2) + 2 * p1 * xy

return x0 * k + tx, y0 * k + ty

original = cv2.imread(“image.jpg”)

#data from .XMP

height = len(original)

width = len(original[0])

focal = 60

scale = max(width, height)

#order k1 k2 p2 p1 k3

distKoeff = np.array([0.1, 0.5, 0, 0, 1])

pp = [0.001, 0.002]

mapX = np.zeros((height, width), np.float32)

mapY = np.zeros((height, width), np.float32)

for row in range(0, height):

for col in range(0, width):

mx, my = toHomo(col + 0.5, row + 0.5, width, height,focal, pp[0], pp[1])

mx, my = brownDistortion(mx,my,distKoeff[0], distKoeff[1],distKoeff[4],distKoeff[2], distKoeff[3])

px, py = fromHomo(mx, my,width, height, focal,pp[0],pp[1])

mapX[row][col] = px - 0.5

mapY[row][col] = py - 0.5

result = cv2.remap(original,mapX,mapY, cv2.INTER_CUBIC)

cv2.imwrite(“result.jpg”,result)