I'm encountering an issue with radial distortion in image processing. I'm trying to apply radial distortion to an image using distortion coefficients k_1 = 1 , k_2 = 0.4 and k_3 = 0.2 . According to the distortion model, I should be getting pincushion distortion as the output. However, when I tried two different methods, I got two different results.
Method 1: Bilinear Interpolation with Array Calculation
In this method, I used pure array calculation to apply radial distortion, the output is pincushion distortion. Here's the code I used:
def apply_distortion_jit(img,W,img_mat, k1, k2, k3):
H = W
dis_center_x = W/2
dis_center_y = H/2
for x in range(W-2):
for y in range(H-2):
x_norm = (x - dis_center_x)/ (W)
y_norm = (y - dis_center_y)/ (H)
r = x_norm * x_norm + y_norm * y_norm
coeff = (k1 + k2 * r + k3 * (r ** 2))
x_d = coeff * (x - W/2) + W/2
y_d = coeff * (y - H/2) + H/2
if x_d >= W-1 or y_d >= H-1 or x_d<0 or y_d <0:
continue
x_d_int = math.floor(x_d)
y_d_int = math.floor(y_d)
dx = x_d - x_d_int
dy = y_d - y_d_int
img_mat[y_d_int,x_d_int] = (1-dx)*(1-dy)*img[y,x] + dx*(1-dy)*img[y,x+1] + \
(1-dx)*dy*img[y+1,x] + dx*dy*img[y+1,x+1]
img_mat[y_d_int,x_d_int+1] = (1-dx)*(1-dy)*img[y,x+1] + dx*(1-dy)*img[y,x+2] + \
(1-dx)*dy*img[y+1,x+1] + dx*dy*img[y+1,x+2]
img_mat[y_d_int+1,x_d_int] = (1-dx)*(1-dy)*img[y+1,x] + dx*(1-dy)*img[y+1,x+1] + \
(1-dx)*dy*img[y+2,x] + dx*dy*img[y+2,x+1]
img_mat[y_d_int+1,x_d_int+1] = (1-dx)*(1-dy)*img[y+1,x+1] + dx*(1-dy)*img[y+1,x+2] + \
(1-dx)*dy*img[y+2,x+1] + dx*dy*img[y+2,x+2]
return img_mat
Bilinear Interpolation output image
Method 2: Interpolation with scipy.ndimage.map_coordinates
In this method, I used scipy.ndimage.map_coordinates to apply radial distortion. I expected to get pincushion distortion, but the output showed barrel distortion. Here's the code :
def apply_distortion_scipy(img,W, k1, k2, k3):
H = W
x, y = np.meshgrid(np.float32(np.arange(W)), np.float32(np.arange(H))) # meshgrid for interpolation mapping
dis_center_x = W / 2
dis_center_y = W / 2
x_norm = (x - dis_center_x) / (W)
y_norm = (y - dis_center_y) / (H)
r = x_norm * x_norm + y_norm * y_norm
coeff = (k1 + k2 * r + k3 * (r ** 2))
x_d = coeff * (x - W / 2) + W / 2
y_d = coeff * (y - H / 2) + H / 2
# img = np.array(img)
img_mat = scipy.ndimage.map_coordinates(img, [y_d.ravel(), x_d.ravel()])
img_mat.resize(img.shape)
return img_mat
scipy.ndimage.map_coordinates output image
I have looked through the API Reference of scipy.ndimage.map_coordinates, but there are no specific implementation codes. Can anyone tell me what could be wrong with my issue?