void CCeresProblem::halconToCvParam(HTuple camParam, cv::Mat &cvParam, cv::Mat &D)
{
D = (cv::Mat_<double>(1, 5) << 0, 0, 0, 0, 0);
cvParam = (cv::Mat_<double>(3, 3) << 0, 0, 0, 0, 0, 0, 0, 0, 0);
HTuple focus;
HTuple k1, k2, k3, p1, p2, sx, sy, cx, cy;
locate.get_cam_par_data(camParam, "focus", &focus);
locate.get_cam_par_data(camParam, "k1", &k1);
locate.get_cam_par_data(camParam, "k2", &k2);
locate.get_cam_par_data(camParam, "k3", &k3);
locate.get_cam_par_data(camParam, "p1", &p1);
locate.get_cam_par_data(camParam, "p2", &p2);
locate.get_cam_par_data(camParam, "sx", &sx);
locate.get_cam_par_data(camParam, "sy", &sy);
locate.get_cam_par_data(camParam, "cx", &cx);
locate.get_cam_par_data(camParam, "cy", &cy);
//一英寸:12.7*9.6
/*
[f/dx 0 u0
0 f/dy v0
0 0 1]
*/
D.at<double>(0, 0) = k1 * focus*focus;
D.at<double>(0, 1) = k2 * focus*focus*focus*focus;
D.at<double>(0, 4) = k3 * focus*focus*focus*focus*focus*focus; // K3为OpenCV畸变中的最后一个
D.at<double>(0, 2) = p2 * focus;
D.at<double>(0, 3) = p1 * focus;
// CameraMatrix
cvParam.at<double>(0, 0) = (focus / sx);
cvParam.at<double>(0, 1) = 0.0;
cvParam.at<double>(0, 2) = cx;
cvParam.at<double>(1, 0) = 0.0;
cvParam.at<double>(1, 1) = (focus / sy);
cvParam.at<double>(1, 2) = cy;
cvParam.at<double>(2, 0) = 0.0;
cvParam.at<double>(2, 1) = 0.0;
cvParam.at<double>(2, 2) = 1.0;
}
没错上代码纯属脑残,完全是错的,(当然你能接受这个误差当我没说),我不知到内参算错了还是畸变系数是不是像这样算的,halcon官方毕竟是商业软件,人家也没打算把计算方式完全给你,所以我向广大网友一样内网外网全查了一遍才找到诸如上面的错误代码,请大家引以为戒,不要按照上面的方法继续犯错了,下面是我验证的方法。
这张四组数据分别是模板匹配的得到的四个点、通过halcon内参重投影、把OpenCV内参转halcon然后重投影,最后直接通过opencv内参投影得到的点;可以看到以模板匹配得到的点为准,第三组数据误差非常大,所以OpenCV内参(畸变)转halcon内参(畸变)方法纯属错误!!!
可以看到,最后一组数据相对于模板匹配的很接近了;
那为什么我要转?估计很多人和我一样,需要用到其他开源库,一个halcon库似乎满足不了本项目,需要提取RT;并且OpenCV圆点标定板找圆鲁棒性让我当场泪目
我项目中还是不对称圆mark点的新型halcon标定板;我决定先找点然后提取cpd文件带入opencv标定函数得到结果,然后得到上上图对比的座标点对,怎么提取文件和标定就不说了,调一下opencv api很简单;对了,提取描述文件时候z设置为0,OpenCV规定的!!主要是根据下面的公式,我先将mark的xyz点坐标转到工具坐标下,然后又转到图像坐标是投影得到的数据;
感谢OpenCV官方,yyds
https://docs.opencv.org/3.4.15/d9/d0c/group__calib3d.html#ga549c2075fac14829ff4a58bc931c033d