Halcon 标定参数(畸变系数)转OpenCV 标定数据
标定板的质量对标定精度影响也是⾮常⼤的,我⼿上有⼀个陶瓷的Halcon原点标定板,使⽤Halcon标定效果很好。但由于想转⽤OpenCV 开发,且不想放弃已有的图像数据,因此想将Halcon标定的数据(内参、外参,畸变系数),转换到OpenCV中。
当然,其参数不是⼀⼀对应的(也就是说,Halcon中的畸变系数与OpenCV中的畸变系数并不⼀⼀对应,按照官⽅的说法是其求解的畸变参数的形式是不⼀样的。⼀个是由校正前到校正后求解得到,⼀个是由校正后到校正前求解得到)。
依据Stack Overflow中的数据,写了⼀个转换的类,输⼊Halcon中的标定数据,就可以得到OpenCV中的参数,可以实现校正畸变,具体精度还有待进⼀步研究。
————————————————————————————————————————
更正:第⼀版中畸变计算出现错误(低级错误),内参矩阵误乘了⼀个尺度因⼦。
OpenCV中的畸变参数排列为 K1 K2 P1 P2 K3(Halcon中是 K1 K2 K3 P1 P2)⼤坑啊!
输⼊参数(畸变系数)
指代焦距Focal Length。
从Halcon 中读⼊参数,转化为OpenCV 中的标定参数
1. 预先使⽤Halcon标定,得到标定参数模型(畸变模型选⽤多项式模型,不要⽤除法模型kappa),使⽤算⼦
write_camera_tup_model保存参数模型,当然也可以直接读取,不保存参数~。
2. 读取参数模型中的参数,得到焦距、Sx、Sy、Cx、Cy、k1、k2、k3、p1、p2以及R、T
* 读取参数模型
read_camera_tup_model ('stereo_camera_tupOpenCV.csm', CameraSetupModelID )
get_camera_tup_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_tup_param (CameraSetupModelID , 0, 'po', Po3)
po_to_hom_mat3d (Po3, HomMat3D_0)
k 1opencv k 2opencv k 3opencv p 1opencv p 2opencv =k 1∗fmm ∗fmm ;
halcon =k 2∗fmm ∗fmm ∗fmm ∗fmm ;
halcon =k 3∗fmm ∗fmm ∗fmm ∗fmm ∗fmm ∗fmm ;
halcon =p 2∗fmm ;(注意这⾥是p )
halcon 2=p 1∗fmm ;
事故灾害halcon fmm
得到参数:
3. 导⼊到C++程序中
其实,tcameraMatrix_Halcon没什么⽤,可以不⽤添加。
4. 使⽤转化后的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;// 声明类
-0.0146141);// 导⼊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;
return0;
}
转换⽤的头⽂件ParamsConvert.h:
// header
// Created by zzl on 10/20/20.
// 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 tcameraMatrix_Halcon(float fx,float fy,float cx,float cy);// 导⼊Halcon中的数据
void tcameraParams_Halcon(float focal_Halcon,float sx_Halcon,float sy_Halcon,float Cx,float Cy);// 导⼊Halcon中的数据
void tcameraDistCoeffs_Halcon(float k1,float k2,float k3,float p2,float p1);// 导⼊Halcon中的数据,注意畸变系数p1、p2
void tcameraRotation(float x1,float x2,float x3,float y1,float y2,float y3,float z1,float z2,float z3);// 设置旋转矩阵
void tcameraTranspo(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::tcameraMatrix_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;
cameraMatrix_Halcon.at<float>(1,3)= cy;
}
void CameraParams::tcameraParams_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::tcameraDistCoeffs_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::tcameraRotation(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::tcameraTranspo(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
<⽂件:
cmake_minimum_required(VERSION 3.10)
project(HalconParams2OpenCV)
t(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})
具体精度有待进⼀步研究!~