Halcon标定参数(畸变系数)转OpenCV标定数据

it2025-01-09  7

标定板的质量对标定精度影响也是非常大的,我手上有一个陶瓷的Halcon原点标定板,使用Halcon标定效果很好。但由于想转用OpenCV开发,且不想放弃已有的图像数据,因此想将Halcon标定的数据(内参、外参,畸变系数),转换到OpenCV中。

当然,其参数不是一一对应的(也就是说,Halcon中的畸变系数与OpenCV中的畸变系数并不一一对应,按照官方的说法是其求解的畸变参数的形式是不一样的。一个是由校正前到校正后求解得到,一个是由校正后到校正前求解得到)。

依据Stack Overflow中的数据,写了一个转换的类,输入Halcon中的标定数据,就可以得到OpenCV中的参数,可以实现校正畸变,具体精度还有待进一步研究。

源地址:https://stackoverflow.com/questions/58606394/halcon-to-opencv-distortion-coefficients-convertion/58991972#58991972

———————————————————————————————————————— 更正:第一版中畸变计算出现错误(低级错误),内参矩阵误乘了一个尺度因子。 OpenCV中的畸变参数排列为 K1 K2 P1 P2 K3(Halcon中是 K1 K2 K3 P1 P2)大坑啊!

输入参数(畸变系数)

k 1 o p e n c v = k 1 h a l c o n ∗ f m m ∗ f m m ; k 2 o p e n c v = k 2 h a l c o n ∗ f m m ∗ f m m ∗ f m m ∗ f m m ; k 3 o p e n c v = k 3 h a l c o n ∗ f m m ∗ f m m ∗ f m m ∗ f m m ∗ f m m ∗ f m m ; p 1 o p e n c v = p 2 h a l c o n ∗ f m m ; ( 注 意 这 里 是 p 2 ) p 2 o p e n c v = p 1 h a l c o n ∗ f m m ; \begin{aligned} k1_{opencv} &= k1_{halcon} * fmm * fmm; \\ k2_{opencv} &= k2_{halcon} * fmm * fmm * fmm * fmm; \\ k3_{opencv} &= k3_{halcon} * fmm * fmm * fmm * fmm * fmm * fmm; \\ p1_{opencv} &= p2_{halcon} * fmm; (注意这里是p_{2}) \\ p2_{opencv} &= p1_{halcon} * fmm; \\ \end{aligned} k1opencvk2opencvk3opencvp1opencvp2opencv=k1halconfmmfmm;=k2halconfmmfmmfmmfmm;=k3halconfmmfmmfmmfmmfmmfmm;=p2halconfmm;(p2)=p1halconfmm;

f m m fmm fmm指代焦距Focal Length。

从Halcon中读入参数,转化为OpenCV中的标定参数

预先使用Halcon标定,得到标定参数模型(畸变模型选用多项式模型,不要用除法模型kappa),使用算子write_camera_setup_model保存参数模型,当然也可以直接读取,不保存参数~。

读取参数模型中的参数,得到焦距、Sx、Sy、Cx、Cy、k1、k2、k3、p1、p2以及R、T * 读取参数模型 read_camera_setup_model ('stereo_camera_setupOpenCV.csm', CameraSetupModelID) get_camera_setup_param (CameraSetupModelID, 0, 'params', CamParam0) // 提取相机的内参数 get_cam_par_data (CamParam0, 'focus', focus0) // 焦距 get_cam_par_data (CamParam0, 'sx', sx0) // Sx 像元尺寸 get_cam_par_data (CamParam0, 'sy', sy0) // Sy 像元尺寸 get_cam_par_data (CamParam0, 'cx', cx0) // 主点坐标 cx get_cam_par_data (CamParam0, 'cy', cy0) // 主点坐标 cy get_cam_par_data (CamParam0, 'k1', k10) // 畸变系数 get_cam_par_data (CamParam0, 'k2', k20) // 畸变系数 get_cam_par_data (CamParam0, 'k3', k30) // 畸变系数 get_cam_par_data (CamParam0, 'p1', p10) // 畸变系数 get_cam_par_data (CamParam0, 'p2', p20) // 畸变系数 change_radial_distortion_cam_par ('adaptive', CamParam0, [0,0,0,0,0], CamParamOut) // 为了生成内参矩阵 cam_par_to_cam_mat (CamParamOut, CamParam0Out, ImageWidth, ImageHeight) // 内参矩阵 * ** 外参数 * 0号相机 get_camera_setup_param (CameraSetupModelID, 0, 'pose', Pose3) pose_to_hom_mat3d (Pose3, HomMat3D_0)

得到参数:

导入到C++程序中

其实,setcameraMatrix_Halcon没什么用,可以不用添加。

使用转化后的OpenCV畸变系数实现校正

源文件

main.cpp主文件

设置参数并测试

// // Created by zzl on 10/21/20. // #include <iostream> #include "opencv2/opencv.hpp" #include "ParamsConvert.h" // 转化用的头文件 using namespace std; using namespace cv; int main(int argc,char** argv) { CameraParams camera0; // 声明类 camera0.setcameraMatrix_Halcon(2284.79, 2273.73, 444.25, 579.716); // 导入参数,这个函数没什么用 camera0.setcameraParams_Halcon(0.00861914, 3.75142e-06, 3.75e-06, 445.868, 582.908); // 导入Halcon中的数据,内参 camera0.setcameraDistCoeffs_Halcon(954.86, 2.8045e+08, -2.35577e+13, 0.451309, 0.457282); // 导入Halcon中的数据,畸变系数(5参数,注意p2,p1位置交换了) camera0.setcameraRotation(0.0808079, 0.0137326, 0.996635, 0.996676, -0.0114733, -0.0806531, 0.0103271, 0.99984, -0.0146141); // 导入Halcon中的数据,旋转矩阵 camera0.setcameraTranspose(-0.129098 , -0.00118334 , 0.122701 ); // 导入Halcon中的数据,平移向量(注意单位) // Camera0 // Read Image and Test Mat src_0 = imread("./0-0.bmp", 1); namedWindow("Input_0", WINDOW_NORMAL); imshow("Input_0", src_0); // Convert Params camera0.Halcon2OpenCV(); Mat cameraMatrix0_OpenCV = camera0.cameraMatrix_OpenCV; // 读取类中的内参矩阵 Mat cameraDist0_OpenCV = camera0.distCoeffs_OpenCV; // 读取类中的畸变矩阵 Mat dst_0; undistort(src_0, dst_0, cameraMatrix0_OpenCV, cameraDist0_OpenCV, noArray()); namedWindow("Output_0", WINDOW_NORMAL); imshow("Output_0", dst_0); waitKey(); cout<<"Hello World"<<endl; return 0; }

转换用的头文件ParamsConvert.h:

// header // Created by zzl on 10/20/20. // #include "opencv2/opencv.hpp" #include "opencv2/calib3d.hpp" #ifndef HALCONPARAMS2OPENCV_PARAMSCONVERT_H #define HALCONPARAMS2OPENCV_PARAMSCONVERT_H class CameraParams { // 转换畸变系数 public: void Halcon2OpenCV(); void setcameraMatrix_Halcon(float fx,float fy,float cx,float cy); // 导入Halcon中的数据 void setcameraParams_Halcon(float focal_Halcon,float sx_Halcon,float sy_Halcon,float Cx,float Cy); // 导入Halcon中的数据 void setcameraDistCoeffs_Halcon(float k1,float k2,float k3,float p2,float p1); // 导入Halcon中的数据,注意畸变系数p1、p2 void setcameraRotation(float x1,float x2,float x3,float y1,float y2,float y3,float z1,float z2,float z3); // 设置旋转矩阵 void setcameraTranspose(float t1,float t2,float t3); // 设置平移矩阵 cv::Mat cameraMatrix_OpenCV = cv::Mat::zeros(3, 3, CV_32F); // 输出的相机内参矩阵 cv::Mat distCoeffs_OpenCV = cv::Mat::zeros(1, 5, CV_32F); // 输出的相机畸变系数 cv::Mat cameraRotation= cv::Mat::zeros(3,3,CV_32F); // 输出的相机旋转矩阵 cv::Mat cameraTrans = cv::Mat::zeros(3,1,CV_32F); // 输出的相机平移向量 private: // 定义Halcon的基本参数 cv::Mat cameraMatrix_Halcon = cv::Mat::zeros(3, 3, CV_32F); cv::Mat distCoeffs_Halcon = cv::Mat::zeros(1, 5, CV_32F); // 以k1,k2,k3,p2,p1 double focal_Halcon, sx_Halcon, sy_Halcon, Cx, Cy; }; // 函数实现 void CameraParams::Halcon2OpenCV() { //cv::Mat OpenCVMatrix = cv::Mat::zeros(1,5,CV_32F); // DistCoeffs distCoeffs_OpenCV.at<float>(0, 0) = distCoeffs_Halcon.at<float>(0, 0) * focal_Halcon * focal_Halcon; // K1 distCoeffs_OpenCV.at<float>(0, 1) = distCoeffs_Halcon.at<float>(0, 1) * focal_Halcon * focal_Halcon * focal_Halcon * focal_Halcon; // K2 distCoeffs_OpenCV.at<float>(0, 4) = distCoeffs_Halcon.at<float>(0, 2) * focal_Halcon * focal_Halcon * focal_Halcon * focal_Halcon * focal_Halcon * focal_Halcon; // K3为OpenCV畸变中的最后一个 // P1 distCoeffs_OpenCV.at<float>(0, 2) = distCoeffs_Halcon.at<float>(0, 3) * focal_HalconMM; // P2 distCoeffs_OpenCV.at<float>(0, 3) = distCoeffs_Halcon.at<float>(0, 4) * focal_HalconMM; // P1 // CameraMatrix cameraMatrix_OpenCV.at<float>(0, 0) = (focal_Halcon / sx_Halcon) ; // 尺度因子 focal_Halcon单位为mm,Sx_Halcon为 mm/像素 注意单位 mm还是um cameraMatrix_OpenCV.at<float>(0, 1) = 0.0; cameraMatrix_OpenCV.at<float>(0, 2) = Cx; cameraMatrix_OpenCV.at<float>(1, 0) = 0.0; cameraMatrix_OpenCV.at<float>(1, 1) = (focal_Halcon / sy_Halcon) ; cameraMatrix_OpenCV.at<float>(1, 2) = Cy; cameraMatrix_OpenCV.at<float>(2, 0) = 0.0; cameraMatrix_OpenCV.at<float>(2, 1) = 0.0; cameraMatrix_OpenCV.at<float>(2, 2) = 1.0; } void CameraParams::setcameraMatrix_Halcon(float fx,float fy,float cx,float cy){ cameraMatrix_Halcon.at<float>(0,0) = fx; cameraMatrix_Halcon.at<float>(0,2) = cx; cameraMatrix_Halcon.at<float>(1,1) = fy; cameraMatrix_Halcon.at<float>(1,3) = cy; } void CameraParams::setcameraParams_Halcon(float focal_HalconIN, float sx_HalconIN, float sy_HalconIN, float CxIN, float CyIN) { focal_Halcon = focal_HalconIN; sx_Halcon = sx_HalconIN; sy_Halcon = sy_HalconIN; Cx = CxIN; Cy = CyIN; } void CameraParams::setcameraDistCoeffs_Halcon(float k1, float k2, float k3, float p2, float p1) { distCoeffs_Halcon.at<float>(0,0) = k1; distCoeffs_Halcon.at<float>(0,1) = k2; distCoeffs_Halcon.at<float>(0,2) = k3; distCoeffs_Halcon.at<float>(0,3) = p2; distCoeffs_Halcon.at<float>(0,4) = p1; } void CameraParams::setcameraRotation(float x1,float x2,float x3,float y1,float y2,float y3,float z1,float z2,float z3){ cameraRotation.at<float>(0,0) = x1; cameraRotation.at<float>(0,1) = x2; cameraRotation.at<float>(0,2) = x3; cameraRotation.at<float>(1,0) = y1; cameraRotation.at<float>(1,1) = y2; cameraRotation.at<float>(1,2) = y3; cameraRotation.at<float>(2,0) = z1; cameraRotation.at<float>(2,1) = z2; cameraRotation.at<float>(2,2) = z3; } void CameraParams::setcameraTranspose(float t1, float t2, float t3) { cameraTrans.at<float>(0,0) = t1; cameraTrans.at<float>(1,0) = t2; cameraTrans.at<float>(2,0) = t3; } #endif //HALCONPARAMS2OPENCV_PARAMSCONVERT_H

CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.10) project(HalconParams2OpenCV) set(CMAKE_CXX_STANDARD 14) find_package(OpenCV REQUIRED) message(STATUS "OpenCV Version:\t " ${OpenCV_VERSION}) include_directories(${OpenCV_INCLUDES}) add_executable(HalconParams2OpenCV main.cpp ParamsConvert.h ) target_link_libraries(HalconParams2OpenCV ${OpenCV_LIBS} )

具体精度有待进一步研究!~

最新回复(0)