opencv相机标定
来源:互联网 发布:布鲁克大学 知乎 编辑:程序博客网 时间:2024/06/10 07:08
主要是参照opencv2那本书,注视写的都很详细,方便以后查找!
CameraCalibrator.h头文件
#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/calib3d/calib3d.hpp>class CameraCalibrator {private: // 输入点 //位于世界坐标的点 std::vector<std::vector<cv::Point3f>> objectPoints; //像素坐标的点 std::vector<std::vector<cv::Point2f>> imagePoints; std::vector<cv::Mat> rvecs, tvecs; // 输出矩阵,内参数阵和畸变系数真 cv::Mat cameraMatrix; cv::Mat distCoeffs; cv::Mat cameraRotation ;//保存外参数矩阵 cv::Mat cameraTranslation ;//保存平移量 // 标定的方式 int flag; // 用于图像去畸变 cv::Mat map1,map2; bool mustInitUndistort;public: CameraCalibrator() : flag(0), mustInitUndistort(true) {}; // 打开棋盘图像并提取角点 int addChessboardPoints(const std::vector<std::string>& filelist, cv::Size & boardSize); void addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners); double calibrate(cv::Size &imageSize); void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false); cv::Mat CameraCalibrator::remap(const cv::Mat &image); //获取指定棋盘格的外方位矩阵 void CalExtrinx(int i) ; //获得相机的内参数矩阵 cv::Mat getCameraExtrinsic(){return cameraRotation ;} void saveRotation(std::string str) ; //获取相机的内参数矩阵 cv::Mat getCameraMatrix() { return cameraMatrix; } //保存相机的内参数矩阵 void saveCameraMatrix(std::string str) ; //获得指定棋盘格的平移量 cv::Mat getTranslations(){ return cameraTranslation ;} //保存平移量 void saveTranslations(std::string str) ; //获取相机的畸变系数 cv::Mat getDistCoeffs() { return distCoeffs; } void printMatrix(const cv::Mat matrix) ; //读取棋盘格列表 void readImagelist(const char* path , std::vector<std::string> &filelist) ; //获取棋盘格角点物理坐标 std::vector<std::vector<cv::Point3f>> getObjectPoints() const {return objectPoints ;} //获取棋盘格角点像点坐标 std::vector<std::vector<cv::Point2f>> getImagepoints() const {return imagePoints ;}};#endif // CAMERACALIBRATOR_H
CameraCalibrator.cpp源文件
#include "CameraCalibrator.h"#include <fstream>#include <algorithm>const int squraewidth = 26 ;/************************************************************************//* 函数说明 打开棋盘图像并且提取角点 * @Input filelist图像列表 * @Input boardSize棋盘尺寸 @ 返回 检测棋盘格图像的数量*//************************************************************************/int CameraCalibrator::addChessboardPoints( const std::vector<std::string>& filelist, cv::Size & boardSize) { // 棋盘上点的两种坐标 std::vector<cv::Point2f> imageCorners; std::vector<cv::Point3f> objectCorners; // 3D 场景中得点 // 在棋盘坐标系中初始化棋盘角点 // 这些点位于(X,Y,Z)=(i,j,0) for (int i=0; i<boardSize.height; i++) { for (int j=0; j<boardSize.width; j++) { objectCorners.push_back(cv::Point3f(i * squraewidth , j * squraewidth , 0.0f)); } } cv::Mat image; // 为了保存棋盘图像 int successes = 0; // 所有视图 for (int i=0; i<filelist.size(); i++) { // 打开图像 image = cv::imread(filelist[i],0); // 得到角点 bool found = cv::findChessboardCorners(image, boardSize, imageCorners); // 获取亚像素级精度 cv::cornerSubPix(image, imageCorners, cv::Size(5,5), cv::Size(-1,-1), cv::TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, //maxCount=40 0.001 )); // 最小精度 // 如果角点数据满足要求,那么将它加入数据(全部角点检测出) if (imageCorners.size() == boardSize.area()) { // 添加一个视角中得图像点及场景点 addPoints(imageCorners, objectCorners); successes++; } cv::drawChessboardCorners(image, boardSize, imageCorners, found); cv::imshow("Corners on Chessboard", image); cv::waitKey(100); } return successes;}/************************************************************************//* 函数说明: 添加场景点与对应的图像点 * @Input imageCorners图像点 * @Input objectCorners场景点*//************************************************************************/void CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners) { // 2D 图像点 imagePoints.push_back(imageCorners); // 对应3D场景中得点 objectPoints.push_back(objectCorners);}/************************************************************************//* 函数说明: 进行标定,返回重投影误差 * @Input imageSize图片尺寸*//************************************************************************/double CameraCalibrator::calibrate(cv::Size &imageSize){ //必须进行去畸变 mustInitUndistort= true; //输出旋转和平移/* std::vector<cv::Mat> rvecs, tvecs;*/ calibrateCamera(objectPoints, // 3D点 imagePoints, // 图像点 imageSize, // 图像尺寸 cameraMatrix, // 输出的相机矩阵 distCoeffs, // 输出的畸变矩阵 rvecs, tvecs, // 旋转和平移 flag); // 额外选项 // ,CV_CALIB_USE_INTRINSIC_GUESS); return 1;}/************************************************************************//* 函数说明: 利用标定结果去除图像的畸变 * 参数:@Input image输入待矫正的图像 * 返回:@Return 去畸变后的图像 */ /************************************************************************/cv::Mat CameraCalibrator::remap(const cv::Mat &image) { cv::Mat undistorted; if (mustInitUndistort) { //每次标定只需初始化一次 cv::initUndistortRectifyMap( cameraMatrix, // 相机内参矩阵 distCoeffs, // 计算得到的畸变矩阵 cv::Mat(), // optional rectification (none) cv::Mat(), // camera matrix to generate undistorted // cv::Size(640,480), image.size(), // 无畸变图像的尺寸 CV_32FC1, // 输出映射图像的类型 map1, map2); // x坐标和y坐标映射函数 mustInitUndistort= false; } // 应用映射函数 cv::remap(image, undistorted, map1, map2, cv::INTER_LINEAR); // interpolation type return undistorted;}void CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, bool tangentialParamEnabled) { // Set the flag used in cv::calibrateCamera() flag = 0; if (!tangentialParamEnabled) flag += CV_CALIB_ZERO_TANGENT_DIST; if (radial8CoeffEnabled) flag += CV_CALIB_RATIONAL_MODEL;}/************************************************************************//* 函数说明: 打印矩阵 *//************************************************************************/void CameraCalibrator::printMatrix(const cv::Mat matrix){ int w = matrix.cols ; int h = matrix.rows ; for (int i = 0 ; i < h ; ++i) { for (int j = 0 ; j < w ; ++j) { std::cout<< matrix.at<double>(i , j)<<"\t" ; } std::cout<<"\n" ; }}/************************************************************************//* 函数说明: 保存相机的内参数矩阵 * 参数:@Input str 保存路径*//************************************************************************/void CameraCalibrator::saveCameraMatrix(std::string str){ if (cameraMatrix.empty()) { std::cout<<"相机内参数矩阵为空!\n" ; return ; } int w = cameraMatrix.cols ; int h = cameraMatrix.rows ; std::ofstream out(str , std::ios::out) ; if (!out) { std::cout<<"打开失败!\n" ; return ; } for (int i = 0 ; i < h ; ++i) { for (int j = 0 ; j < w ; ++j) { out<<cameraMatrix.at<double>(i , j)<<"\t" ; } out<<"\n" ; } out.close() ;}/************************************************************************//* 函数说明: 读取图像列表 * 参数@Input path 保存图像列表路径 * 参数@Output filelist保存所有图片路径*//************************************************************************/void CameraCalibrator::readImagelist(const char* path , std::vector<std::string> &filelist){ std::ifstream in(path , std::ios::in) ; if (!in) { return ; } std::string str ; int i = 0 ; while (!in.eof()) { in>>str ; filelist.push_back(str) ; ++i ; } in.close() ;}/************************************************************************//*函数说明: 保存外方位矩阵 *参数 @Input str 保存路径*//************************************************************************/void CameraCalibrator::saveRotation(std::string str){ if (cameraRotation.empty()) { std::cout<<"外方位矩阵为空!\n" ; return ; } //获取矩阵的行数和列数 int w = cameraRotation.cols ; int h = cameraRotation.rows ; std::ofstream out(str , std::ios::out) ; if (!out) { std::cout<<"保存文件失败!\n" ; return ; } else { for (int i = 0 ; i < h ; ++i) { for (int j = 0 ; j < w ; ++j) { out<<cameraRotation.at<double>(i , j)<<"\t" ; } out<<"\n" ; } }}/************************************************************************//* 获取指定棋盘格的外方位元素 * Input i 表示第i张图像 *//************************************************************************/ void CameraCalibrator::CalExtrinx(int i){ Rodrigues(rvecs[i] , cameraRotation) ; cameraTranslation = tvecs[i] ;} /************************************************************************/ /* 函数说明: 保持平移量 * @Input str 保存文件名称*/ /************************************************************************/ void CameraCalibrator::saveTranslations(std::string str) { if (cameraTranslation.empty()) { std::cout<<"相机外参数的平移量量为空!\n" ; return ; } int w = cameraTranslation.cols ; int h = cameraTranslation.rows ; std::ofstream out(str , std::ios::out) ; if (!out) { std::cout<<"写入文件失败!\n" ; return ; } for (int i = 0 ; i < w ; ++i) { for (int j = 0 ; j < h ; ++j) { out<<cameraTranslation.at<double>(i , j)<<"\t" ; } out<<"\n" ; } }
main.cpp文件
#include <iostream>#include <iomanip>#include <vector>#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/features2d/features2d.hpp>#include <fstream>#include "CameraCalibrator.h"int main(){ cv::Mat image; CameraCalibrator cameraCalibrator; std::vector<std::string> filelist; cameraCalibrator.readImagelist("文件.txt" , filelist) ;//读取文件列表 cv::Mat mat ; cv::Size boardSize(9,6); cameraCalibrator.addChessboardPoints(filelist , boardSize); // 棋盘尺寸 // cameraCalibrator.setCalibrationFlag(true,true); image = cv::imread(filelist[6]); cameraCalibrator.calibrate(image.size()); image = cv::imread(filelist[6]); cv::Mat uImage= cameraCalibrator.remap(image); cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix(); std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl; cameraCalibrator.printMatrix(cameraMatrix) ; cameraCalibrator.saveCameraMatrix("neican.txt") ; std::cout<<"第"<<1<<"张图像的旋转矩阵为:\n" ; cameraCalibrator.CalExtrinx(1) ; cv::Mat rotationMatrix = cameraCalibrator.getCameraExtrinsic() ; cameraCalibrator.printMatrix(rotationMatrix) ; std::cout<<"第"<<1<<"张图像的平移向量为:\n" ; cv::Mat translationMatrix = cameraCalibrator.getTranslations() ; cameraCalibrator.printMatrix(translationMatrix) ; imshow("Original Image", image); imshow("Undistorted Image", uImage); cv::waitKey(); return 0;}
0 0
- OpenCV相机标定函数
- OPenCV相机标定函数
- opencv相机标定
- OpenCV相机标定
- opencv相机标定
- OpenCV相机标定
- OpenCV相机标定
- OpenCV相机标定
- OpenCV相机标定
- opencv相机标定
- opencv相机标定
- OpenCV相机标定
- opencv---相机标定
- Opencv标定相机
- OpenCV相机标定
- 相机标定之OpenCV&Matlab
- 相机标定之OpenCV&Matlab
- 相机标定之OpenCV&Matlab
- UIView动画——钟表的制作
- Unity3d 综合性能窍门
- 错误解决方案:FATAL: Error inserting cmemk (/lib/modules/2.6.37/kernel/drivers/dsp/cmemk.ko): Bad address
- 2016年1月19日若干笔记(CFileFind,RadioButton)
- Unity3d 综合性能窍门
- opencv相机标定
- 《从零开始自学iOS》_05
- modprobe FATAL: Module cmemk not found. 解决方案
- Android自定义控件之轮播图控件
- MSP430F1232针对ADC10(使用DTC+SA)的内存中采样结果读取
- 欢迎使用CSDN-markdown编辑器
- Xcode7 使用NSURLRequest进行HTTP请求出错解决方案
- JavaScript两大支柱-PART1:如何逃脱第七层地狱(译)
- AJAX => 入门学习