OpenCV: How to get the position of one point after cv2.fisheye.undistortImage?

Viewed 1611

I am trying to create a fisheye effect, but I am not familiar with cv2.fisheye.undistortImage() and cv2.fisheye.undistortPoints(). Here is my code:

import cv2
import glob
import numpy as np

# grab a list of jpg from one folder
img_list = glob.glob('/home/folder/*.jpg')

# get the K and D for cv2.fisheye.undistortImage
K = np.array([[900.,0,512],
        [0,900.,288],
        [0.,0.,1]])

D = np.array([4.,100.,0.,0.])

# create a random point
point = np.array([[[300.,300.],[300,400],[400,400],[400,300]]])

# get a knew for cv2.fisheye.undistortImage
Knew = K.copy()
Knew[(0,1),(0,1)] = Knew[(0,1),(0,1)]


for img_path in img_list:

        img = cv2.imread(img_path)

        # draw all four points on the original image
        cv2.circle(img,(300,300), 5, (0,0,255), -1)
        cv2.circle(img,(400,300), 5, (0,0,255), -1)
        cv2.circle(img,(300,400), 5, (0,0,255), -1)
        cv2.circle(img,(400,400), 5, (0,0,255), -1)

        # distort the images
        img_out = cv2.fisheye.undistortImage(img,K,D=D,Knew=Knew)
        # send the points to cv2.fisheye.undistortPoints
        point_out = cv2.fisheye.undistortPoints(point,K =K1, D=D)

        # looks like the out is around (-1,1) so i tried to recover back
        #cv2.circle(img,(600,300), 5, (0,0,255), -1)
        x = int((512.+(point_out[0][0][0]*1024)))
        y = int((288.+(point_out[0][0][1]*576)))
        cv2.circle(img_out,(x,y), 5, (0,255,0), 1)
        x = int((512.+(point_out[0][1][0]*1024)))
        y = int((288.+(point_out[0][1][1]*576)))
        cv2.circle(img_out,(x,y), 5, (0,255,0), 1)
        x = int((512.+(point_out[0][2][0]*1024)))
        y = int((288.+(point_out[0][2][1]*576)))
        cv2.circle(img_out,(x,y), 5, (0,255,0), 1)
        x = int((512.+(point_out[0][3][0]*1024)))
        y = int((288.+(point_out[0][3][1]*576)))
        cv2.circle(img_out,(x,y), 5, (0,255,0), 1)

        # save the img
        cv2.imwrite(img_path+'.jpg',img_out,[100])

enter image description here

This code is an experiment to try to get the output position after doing undistortImage(). First, I draw one red point on the original image, for instance (300,300). Then, I use undistortImage() to do a fisheye effect, so the red point might locate in a different place. However, I dont know how to compute the correct position.

I thought that undistortPoints() might get the right position. Unfortunately, the green circles shows my method was wrong. Can somebody tell how to get the right value?

1 Answers

You specify a camera matrix for the distorted image with Knew when calling fisheye.undistortImage. When you call fisheye.undistortPoints you need to do the same. If you read the documentation, you will see that you can give a P argument which is the " New camera matrix (3x3) or new projection matrix (3x4)". That's what you want.

for img_path in img_list:

    img = cv2.imread(img_path)

    # draw all four points on the original image
    cv2.circle(img,(300,300), 5, (0,0,255), -1)
    cv2.circle(img,(400,300), 5, (0,0,255), -1)
    cv2.circle(img,(300,400), 5, (0,0,255), -1)
    cv2.circle(img,(400,400), 5, (0,0,255), -1)

    # distort the images
    img_out = cv2.fisheye.undistortImage(img,K,D=D,Knew=Knew)
    # send the points to cv2.fisheye.undistortPoints
    point_out = cv2.fisheye.undistortPoints(point,K =K, D=D, P=Knew)[0]
    for point in point_out:
        cv2.circle(img_out, (int(point[0]), int(point[1])), 5, (0,255,0), 1)

    # save the img
    cv2.imwrite(img_path+'.jpg',img_out,[100])
Related