• 全景拼接学习-原理篇 (0) 相机标定 内参和外参


    https://blog.csdn.net/u013498583/article/details/71404323

    http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/calib3d/camera_calibration/camera_calibration.html#cameracalibrationopencv

    1原理

    1-1成像过程

    摄像机的成像过程主要是主要涉及到几个坐标系的变换(具体过程可以参考相机模型):

     从摄像机成像畸变的产生于是其“天生”的,不可避免的,这主要是由于透镜成像原理导致的。其畸变的原理可以参考相机模型)。

    1-2校正原理

    相机内参  像素的物理尺寸和焦距

     相机的畸变矫正

    图像像素坐标系 (uOv坐标系) 下的无畸变坐标 (U, V),经过 径向畸变 和 切向畸变 后落在了uOv坐标系 的 (Ud, Vd) 上。
    即就是说,真实图像 imgR 与 畸变图像 imgD 之间的关系为: imgR(U, V) = imgD(Ud, Vd) 

    最终公式

     其中,[x,y′]为畸变后的位置,[x,y]为畸变前的位置,[ki,pi]为畸变系数。当然,其实畸变系数远远不止这么四个,但通常情况下可以仅考虑这四个。

     

    2标定过程

    2-1 opencv自带的源码

    2-2 使用matlab

    最终获取标定文件

     XML/YAML file 

    Camera_Matrix type_id="opencv-matrix">
    <rows>3</rows>
    <cols>3</cols>
    <dt>d</dt>
    <data>
     6.5746697944293521e+002 0. 3.1950000000000000e+002 0.
     6.5746697944293521e+002 2.3950000000000000e+002 0. 0. 1.</data></Camera_Matrix>
    <Distortion_Coefficients type_id="opencv-matrix">
    <rows>5</rows>
    <cols>1</cols>
    <dt>d</dt>
    <data>
     -4.1802327176423804e-001 5.0715244063187526e-001 0. 0.
     -5.7843597214487474e-001</data></Distortion_Coefficients>
    

     

    畸变矫正 Distortion_Coefficients 5个失真参数

    内参矩阵 Camera_Matrix 新的变换矩阵

       联合   



    6.校正

    得到out_camera_data.xml文件后,我们可以直接使用该配置文件进行校正。

     这个代码比较简单 没有中间变量

    #include <opencv2/opencv.hpp>
    #include <opencv2/calib3d/calib3d.hpp>
    using namespace std;
    using namespace cv;
     
    /**
     * @主函数
     */
    int main( int argc, char** argv )
    {
     
    	/// 读取一副图片,不改变图片本身的颜色类型(该读取方式为DOS运行模式)
    		Mat src = imread( argv[1], 1 );
    		Mat distortion = src.clone();
    		Mat camera_matrix = Mat(3, 3, CV_32FC1);
    		Mat distortion_coefficients;
     
     
    		//导入相机内参和畸变系数矩阵
    		FileStorage file_storage("out_camera_data.xml", FileStorage::READ);
    		file_storage["Camera_Matrix"] >> camera_matrix;
    		file_storage["Distortion_Coefficients"] >> distortion_coefficients;
    		file_storage.release();
     
    		//矫正
    		undistort(src, distortion, camera_matrix, distortion_coefficients);
     
    		imshow("img", src);
    		imshow("undistort", distortion);
    		imwrite("undistort.jpg", distortion);
     
    		waitKey(0);
    		return 0;
    }
    

      第二个代码样例

    https://blog.csdn.net/billbliss/article/details/52527182?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

     我已经成功获取了摄像机的内参矩阵,以及畸变矩阵。也已经成功畸变矫正。但是我还希望获取原图中心点undistort之后的对应点。

    返回的map1,map2来直接获得undistort之后的对应点。
    主要函数

    initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
                                getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
                                imageSize, CV_16SC2, map1, map2);
    
    

      网友调试过程

    https://blog.csdn.net/qq_20289205/article/details/78632542

    相对完整的例程

    #include "opencv.hpp"
     
    using namespace std;
    using namespace cv;
     
    void ReadIntrinsics(Mat &cameraMatrix, Mat &distCoeffs, Size &imageSize, char *IntrinsicsPath)
    {
    	bool FSflag = false;
    	FileStorage readfs;
     
    	FSflag = readfs.open(IntrinsicsPath, FileStorage::READ);
    	if (FSflag == false) cout << "Cannot open the file" << endl;
    	readfs["Camera_Matrix"] >> cameraMatrix;
    	readfs["Distortion_Coefficients"] >> distCoeffs;
    	readfs["image_Width"] >> imageSize.width;
    	readfs["image_Height"] >> imageSize.height;
     
    	cout << cameraMatrix << endl << distCoeffs << endl << imageSize << endl;
     
    	readfs.release();
    }
     
    void Undistort_img(Mat map1, Mat map2, char *path)
    {
    	Mat img1, img2;
    	img1 = imread(path);
    	if (img1.empty()) cout << "Cannot open the image" << endl;
    	remap(img1, img2, map1, map2, INTER_LINEAR);
    // 	imwrite(path, img2);
    	imshow("src img", img1);
    	imshow("dst img", img2);
    	waitKey();
    }
     
    void main()
    {
    	Mat	cameraMatrix, distCoeffs, map1, map2;
    	Size imageSize;
    	char * IntrinsicsPath = "Intrinsics.yml";
    	ReadIntrinsics(cameraMatrix, distCoeffs, imageSize, IntrinsicsPath);
     
    	// 去畸变并保留最大图
    	initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
    		getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
    		imageSize, CV_16SC2, map1, map2);
     
    	Undistort_img(map1, map2, "E:/VS13/undistort/undistort/1.bmp");
     
    	// 去畸变至全图
    	initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(), Mat(),
    		imageSize, CV_16SC2, map1, map2);
     
        Undistort_img(map1, map2, "E:/VS13/undistort/undistort/1.bmp");
    }
    

      

  • 相关阅读:
    【二次开发】shopxo商城
    经典的PHPer为什么被认为是草根?
    PowerDesigner生成Access数据库
    NET开发学习项目资源
    ASP.NET程序开发范例宝典
    Web.Config文件配置小记
    NET开发学习项目资源(2)
    VS 2010一步步开发windows服务(windows service)
    jquery.mobile手机网页简要
    Android置底一个View后运行报错
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/13270069.html
Copyright © 2020-2023  润新知