关于opencv通过initUndistortRectifyMap函数获取undistort后的对应点的方法
2017-11-25 16:17
671 查看
关于opencv通过initUndistortRectifyMap函数获取undistort后的对应点的方法
关于opencv通过initUndistortRectifyMap函数获取undistort后的对应点的方法环境与简介
前置代码
Attempt1undistortPoints
attempt2initUndistortRectifyMap的map
环境与简介
我用的是opencv2.4.13.2,然后是c++的。我已经成功获取了摄像机的内参矩阵,以及畸变矩阵。也已经成功畸变矫正。但是我还希望获取原图中心点undistort之后的对应点。
前置代码
这部分代码的作用是畸变矫正。实际上和题目关系不大,而且你们也很容易在网上找到(当然是有不少错误的版本)。不过我还是放上来:Mat cameraMatrix = Mat::eye(3, 3, CV_64F); //内参矩阵, 就算复制代码,也不要用我的参数。摄像头都不一样... cameraMatrix.at<double>(0, 0) = 2.075319928848340e+03; cameraMatrix.at<double>(0, 1) = 0; cameraMatrix.at<double>(0, 2) = 1.273350420020438e+03; cameraMatrix.at<double>(1, 1) = 2.073416138777327e+03; cameraMatrix.at<double>(1, 2) = 6.898818022397845e+02; //畸变参数,不要用我的参数~ Mat distCoeffs = Mat::zeros(5, 1, CV_64F); distCoeffs.at<double>(0, 0) = 0.005961692158170; distCoeffs.at<double>(1, 0) = 0.014892085926656; distCoeffs.at<double>(2, 0) = -0.007714274148788; distCoeffs.at<double>(3, 0) = -0.010548832296675; distCoeffs.at<double>(4, 0) = 0; Mat view, rview, map1, map2; Size imageSize; imageSize = image.size(); initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(), getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize, CV_16SC2, map1, map2); remap(image, image, map1, map2, INTER_LINEAR);
那么,在remap函数之后,image就是我们畸变矫正的结果了。
Attempt1:undistortPoints
首先,我在网上一搜,这个函数就冒了出来。undistortPoints, 矫正后的点,emmmmmmm,看起来很美。从结果来说,实际上是坑爹的。std::vector<Point2d> obj_corners(1); obj_corners[0] = Point2d((double)input_center_point.x,(double)input_center_point.y); std::vector<Point2d> scene_corners(1); //obj_corners:输入 //scene_corners:输出 undistortPoints(obj_corners,scene_corners,cameraMatrix,distCoeffs);
结果怎么这么小?
11-24 23:03:38.971 9133-9410/? I/MyCV: scene_corners width is 0.034107 11-24 23:03:38.971 9133-9410/? I/MyCV: scene_corners height is 0.031944
实际上,在得到结果之后,还要有一步:
//Focus_length: 焦距,分fx和fy的。看不懂的同学请从头学习内参矩阵或者考虑换个导师或者科研题目 //Principle_Point.x:主点坐标,也是内参矩阵的一部分,同上 //scene_corners[0]: 上面undistortPoints函数的输出 result_point.x = scene_corners[0].x*Focus_length.x+Principle_Point.x; result_point.y = scene_corners[0].y*Focus_length.y+Principle_Point.y;
这样,就能够算出结果。
我自己的输入是:(1344,756),而我的输出是:
11-24 23:03:38.971 9133-9410/? I/MyCV: result width is 1344.132696 11-24 23:03:38.971 9133-9410/? I/MyCV: result height is 756.114362
根本没多大变化啊?!
所以,就如我在开头说的,这个是坑爹的…它应该有其他作用,但是并不能解决我现在的问题。
attempt2:initUndistortRectifyMap()的map
然后我又查查找找,最终找到下面两个:https://stackoverflow.com/questions/34265650/can-i-get-the-point-position-using-remap-in-opencv
https://stackoverflow.com/questions/22323410/opencvremap-how-to-remap-an-image-to-another-image-with-different-size
它们都说的是什么呢?两个说了一件事:那就是通过initUndistortRectifyMap函数:
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(), getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize, CV_16SC2, map1, map2);
返回的map1,map2来直接获得undistort之后的对应点。
于是我就试试试,这个怎么样?
map1.at<float>(row,col) map2.at<float>(row,col)
这个又怎么样?
map1.at<uchar>(row,col) map2.at<uchar>(row,col)
具体结果我忘了,但是都明显不对。原因是map1,和map2的格式早就由initUndistortRectifyMap函数决定了。仔细看看其中的参数,CV_16SC2定义了map1的格式。map2的type我打出来是:
11-24 23:03:37.687 9133-9426/? I/MyCV: map2 16UC1
于是我根据这里的type和mat格式的对应关系又试了这个:
map1.at<int16_t>(row,col) map2.at<unit16_t>(row,col)
结果还是不对。
我又试了convertMaps函数,未果。
之后,我看了眼map1的CV_16SC2格式,发现事情并不简单。map1啊,明明你只是一个mat,应该和你的好基友map2一起返回结果x坐标和y坐标,为嘛你有两个通道啊?
于是我怀着侥幸心理,再试了两个通道分别的值:
typedef Vec<int16_t, 2> Vec2myi; __android_log_print(ANDROID_LOG_INFO, LOG, "map1 %d",map1.at<Vec2myi>( y , x )[0]); __android_log_print(ANDROID_LOG_INFO, LOG, "map2 %d",map1.at<Vec2myi>( y , x )[1]);
11-24 23:03:37.785 9133-9426/? I/MyCV: map1 1372 11-24 23:03:37.785 9133-9426/? I/MyCV: map2 767
大家还记不记得,我的输入是多少?
(1344,756)对吧,已经和这个十分接近了。
貌似是十分靠谱的。
结果,我把点打在图上,还是差不少,究竟是哪里出错了呢?
我输入的图片尺寸为:2688*1512
我又看了看点的位置,灵机一动,决定这样:
new_x = input_image.size().width - map1.at<Vec2myi>( y , x )[0]; new_y = input_image.size().height - map1.at<Vec2myi>( y , x )[1];
完美。
别问我为什么坐标是反过来的,我什么也不知道。なにも知らない!
PS: 当前搞计算机视觉的人,究竟有多少主要用的是tensorflow,caffe而非OpenCV?机器学习眼下的大热,真是能让我凭空生出很多没有营养的感慨。十年前的计算机视觉,和2012年之后的完全是两个学科嘛。SVM都没人用了。算了,没什么所谓。
相关文章推荐
- InitUndistortMap矫正函数
- initUndistortRectifyMap
- cvInitUndistortRectifyMap;initUndistortRectifyMap()
- 图像去畸变remap和initUndistortRectifyMap
- 关于window下和Ubuntu下获取本地ip地址的方法;2.关于通过槽函数名执行槽函数的办法,3.QString初始化的意义
- 关于OE7.0中通过登录uid获取其部门的方法
- 关于在recycleview中点击item获取对应的viewholder的方法
- 关于平台驱动获取资源的函数platform_get_resourc的获取方法及参数介绍
- 获取Map的keyset使用remove方法Map中对应的键值也会被移除
- 关于opencv从视频获取单帧图片函数cvQueryFrame
- 关于VC++6.0加载控件出现Unable to register this add-in because its DllRegisterServer returns an error 的解决方法
- Unity 关于GetComponentsInChildren 利用扩展方法如何避免获取父物体
- 通过spy++查找应用程序菜单对应函数的方法
- JNI:通过函数名对应表的方式来加载对应的native方法
- MAP定义方法通过key获取value值
- Java 编程下通过反射获取一个类中的方法名和对应参数名
- 关于通过php获取mysql表里的字段名的方法的整理
- Python通过正则表达式获取,去除(过滤)或者替换HTML标签的几种方法(本文由169it.com搜集整理)
- JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
- Java 编程下通过反射获取一个类中的方法名和对应参数名