I’m currently working on a camera that have a fisheye (which is not much but still) and I’m trying to undistort it.
As starter : I’m not that familiar with opencv, I’m like always on the documentation while trying to do anything. (and/or here looking for answer to my problem(s)).
So I saw few example on the web, I tried the solutions and got some results on my part.
Here what I found :
DIM=(1094, 729)
K=np.array([
[1307.2807020496643, 0.0, 530.3754311563506],
[0.0, 1318.342691460933, 354.98352268131123],
[0.0, 0.0, 1.0]
])
D=np.array([
[-0.2994762856767568],
[0.5036082961388784],
[-4.231072729639434],
[3.8646397788794578]
])
def undistort(img_path):
img = cv2.imread(img_path)
h,w = img.shape[:2]
print(K)
print(D)
print(np.eye(3))
print(DIM)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
cv2.imshow("undistorted", undistorted_img)
cv2.imwrite("test.jpg", undistorted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
for p in sys.argv[1:]:
undistort(p)
This is the python script I use to undistort image. The data at the top (K & D) are generated through another script. I didn’t mentioned it because I have a translation in C++ that show same result for the same base_picture
And for this function if I give a distorted image like :
I got this result :
So I can see that the tiny distortion has been resolved.
But when I try to implement this same function in C++ as follow :
src = cv::imread(“path/to/image.jpg");
cv::Size size = {src.cols, src.rows};
cv::Mat K(3, 3, cv::DataType<double>::type);
K.at<double>(0, 0) = 1307.2807020496643;
K.at<double>(0, 1) = 0.0;
K.at<double>(0, 2) = 530.3754311563506;
K.at<double>(1, 0) = 0.0;
K.at<double>(1, 1) = 1318.342691460933;
K.at<double>(1, 2) = 354.98352268131123;
K.at<double>(2, 0) = 0.0;
K.at<double>(2, 1) = 0.0;
K.at<double>(2, 2) = 1.0;
cv::Mat D(4, 1, cv::DataType<double>::type);
D.at<double>(0, 0) = -0.2994762856767568;
D.at<double>(1, 0) = 0.5036082961388784;
D.at<double>(2, 0) = -4.231072729639434;
D.at<double>(3, 0) = 3.8646397788794578;
cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);
cv::Mat map1;
cv::Mat map2;
std::cout << K << std::endl;
std::cout << D << std::endl;
std::cout << E << std::endl;
std::cout << size << std::endl;
cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::Mat undistort;
cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
CV_HAL_BORDER_CONSTANT);
The base image is still the same BUT I got this as result :
And as you can tell, it went worse…
I dumped K, D & E in my python script and c++ program (both gives the same result for the same base picture) (I mean when I compute the datas)
It goes wrong from the initUndistortRectifyMap up to the remap and finally imshow is totally not what I was expecting.
I try to dump map1 & map2 in python script & C++ program (wasn’t looking at ALL of the data) and I could notice that at the end of one of the map (didn’t look both) the results were differents.
Since I call the function using the same parameter (as far as I’m aware of) I expected for the map to be equal between both programs.
Is there something I’m doing wrong ? Like messing with the types or whatsoever ?
Does it change anything to compute the image from a cv::imread or from a frame acquisition from a camera ?
(Just to let you know, the frame (.jpg) with which computation is made, is a cv::imwrite from the frame acquisition of the camera, then I intend not to use images anymore but only work with cv::Mat filled with data from camera acquisition.)
(I know that at the end the enum aren't the same, but even using cv::BORDER_CONSTANT
I still have the same issue.)
You've used the cv::initUndistortRectifyMap
instead of cv::fisheye::initUndistortRectifyMap
using this code instead I get the proper result:
int main()
{
cv::Mat src = cv::imread("C:/StackOverflow/Input/fisheyeCalib.jpg");
cv::Size size = { src.cols, src.rows };
cv::Mat K(3, 3, cv::DataType<double>::type);
K.at<double>(0, 0) = 1307.2807020496643;
K.at<double>(0, 1) = 0.0;
K.at<double>(0, 2) = 530.3754311563506;
K.at<double>(1, 0) = 0.0;
K.at<double>(1, 1) = 1318.342691460933;
K.at<double>(1, 2) = 354.98352268131123;
K.at<double>(2, 0) = 0.0;
K.at<double>(2, 1) = 0.0;
K.at<double>(2, 2) = 1.0;
cv::Mat D(4, 1, cv::DataType<double>::type);
D.at<double>(0, 0) = -0.2994762856767568;
D.at<double>(1, 0) = 0.5036082961388784;
D.at<double>(2, 0) = -4.231072729639434;
D.at<double>(3, 0) = 3.8646397788794578;
cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);
cv::Mat map1;
cv::Mat map2;
std::cout << K << std::endl;
std::cout << D << std::endl;
std::cout << E << std::endl;
std::cout << size << std::endl;
// Here's the error:
//cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::fisheye::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::Mat undistort;
cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
CV_HAL_BORDER_CONSTANT);
cv::imwrite("C:/StackOverflow/Input/fisheyeCalib_output.jpg", undistort);
cv::imshow("undist", undistort);
cv::waitKey(0);
}