下面是教材《深入理解OpenCV 实用计算机视觉项目解析》78页的原话

摄像机的内参数可利用OpenCV发布包中的示例程序camera_cailbration.exe来计算。该程序会使用一系列模式图像来找到内部透镜参数,例如:焦距、主点、失真系数。例如:有一组来自于不同角度用于标定的模式图像,总共有8张图像。
通过以下命令方式执行标定
imageliet_creator imagelist.yaml *.png
calibration -w 9 -h 6 -o camera_intrinsic.yaml imagelist.yaml
第一条命令将创建YAML格式的一个图像列表,校验工具希望将当前目录中所有PNG文件作为输入,也可以使用完整的文件名。然后将生成的文件imagelist.yaml传递给标定程序。此外,标定工具可以从一个普通的摄像机获取图像
指定校正模式的维度、输入文件以及将写入标定数据的输出文件。
标定完成后,会得到一个YAML文件

开始

1.准备图片

使用openCV3.4.1源码自带的图片

https://github.com/opencv/opencv/releases/tag/3.4.1 github上下载:opencv-3.4.1-vc14_vc15.exe,安装,从文件夹找到:opencv\sources\samples\data,如图

opencv已知内参和图片怎么求外参矩阵 opencv相机内参_YAML

2.生成imglist.yaml文本

启动vs2017,在:F:\opencv3.4.1下创建C++空项目:Cameracalibration,添加新文件main.cpp,然后把:opencv\sources\samples\cpp目录下的:imagelist_creator.cpp复制到main.cpp,生成相应的:Cameracalibration.exe程序。
imagelist_creator.cpp如下

/*this creates a yaml or xml list of files from the command line args
 */

#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <string>
#include <iostream>

using std::string;
using std::cout;
using std::endl;

using namespace cv;

static void help(char** av)
{
  cout << "\nThis creates a yaml or xml list of files from the command line args\n"
      "usage:\n./" << av[0] << " imagelist.yaml *.png\n"
      << "Try using different extensions.(e.g. yaml yml xml xml.gz etc...)\n"
      << "This will serialize this list of images or whatever with opencv's FileStorage framework" << endl;
}

int main(int ac, char** av)
{
  cv::CommandLineParser parser(ac, av, "{help h||}{@output||}");
  if (parser.has("help"))
  {
    help(av);
    return 0;
  }
  string outputname = parser.get<string>("@output");

  if (outputname.empty())
  {
    help(av);
    return 1;
  }

  Mat m = imread(outputname); //check if the output is an image - prevent overwrites!
  if(!m.empty()){
    std::cerr << "fail! Please specify an output file, don't want to overwrite you images!" << endl;
    help(av);
    return 1;
  }

  FileStorage fs(outputname, FileStorage::WRITE);
  fs << "images" << "[";
  for(int i = 2; i < ac; i++){
    fs << string(av[i]);
  }
  fs << "]";
  return 0;
}

将left01-14.jpg,right01-14.jpg拷贝到Cameracalibration.exe所在文件夹
打开cmd,先跳转到Cameracalibration.exe(项目名为Cameracalibration)所在目录,输入:F:跳转到F盘,然后输入:cd opencv3.4.1\Cameracalibration\x64\Debug,执行如下命令行

.\Cameracalibration.exe imglist.yaml left01.jpg left02.jpg left03.jpg left04.jpg left05.jpg left06.jpgleft07.jpg left08.jpg left09.jpg  left11.jpg left12.jpg left13.jpgleft14.jpg right01.jpg right02.jpg right03.jpg right04.jpg right05.jpgright06.jpg right07.jpg right08.jpg right09.jpg right11.jpg right12.jpg right13.jpg right14.jpg

.\Cameracalibration.exe前面的.\表示当前目录下

opencv已知内参和图片怎么求外参矩阵 opencv相机内参_#include_02


可以看到,会在该目录下生成一个imglist.yaml文本。

opencv已知内参和图片怎么求外参矩阵 opencv相机内参_xml_03


imglist.yaml文本内容如下

%YAML:1.0
---
images:
   - "left01.jpg"
   - "left02.jpg"
   - "left03.jpg"
   - "left04.jpg"
   - "left05.jpg"
   - "left06.jpgleft07.jpg"
   - "left08.jpg"
   - "left09.jpg"
   - "left11.jpg"
   - "left12.jpg"
   - "left13.jpgleft14.jpg"
   - "right01.jpg"
   - "right02.jpg"
   - "right03.jpg"
   - "right04.jpg"
   - "right05.jpgright06.jpg"
   - "right07.jpg"
   - "right08.jpg"
   - "right09.jpg"
   - "right11.jpg"
   - "right12.jpg"
   - "right13.jpg"
   - "right14.jpg"

生成out_camera_data.yml文件

接下来将main.cpp内容换成:calibration.cpp (位置也在opencv\sources\samples\cpp),在VS2017中生成相应的Cameracalibration.exe程序。

期间出现错误:C4996 'localtime': This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

opencv已知内参和图片怎么求外参矩阵 opencv相机内参_xml_04


参考: https://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html

在工程文件名处右击鼠标打开快捷菜单,找到“属性”选项,进入项目属性页面,在属性页面中找到“C/C++"–>”预处理器“,在“预处理器定义” 中,添加 :_CRT_SECURE_NO_WARNINGS,再次编译并运行即可正常运行

此时calibration.exe和上面那些图片已经在同一目录,打开cmd,执行一下三步:
1.跳到F盘:F: 2.调到文件目录:cd opencv3.4.1\Cameracalibration\x64\Debug 3.执行命令行:.\Cameracalibration imglist.yaml left01.jpg left02.jpg left03.jpg left04.jpg left05.jpg left06.jpgleft07.jpg left08.jpg left09.jpg left11.jpg left12.jpg left13.jpgleft14.jpg right01.jpg right02.jpg right03.jpg right04.jpg right05.jpgright06.jpg right07.jpg right08.jpg right09.jpg right11.jpg right12.jpg right13.jpg right14.jpg -w=6 -h=9 会打印出

RMS error reported by calibrateCamera: 0.541522
Calibration succeeded. avg reprojection error = 0.54

opencv已知内参和图片怎么求外参矩阵 opencv相机内参_xml_05


还会在同一目录生成一个out_camera_data.yml文件,内容如下:

%YAML:1.0
---
calibration_time: "Mon May 13 09:26:56 2019"
image_width: 640
image_height: 480
board_width: 6
board_height: 9
square_size: 1.
aspectRatio: 1.
flags: 2
camera_matrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 5.3808562490205657e+02, 0., 3.3835479720806154e+02, 0.,
       5.3808562490205657e+02, 2.3777462223446776e+02, 0., 0., 1. ]
distortion_coefficients: !!opencv-matrix
   rows: 5
   cols: 1
   dt: d
   data: [ -2.5774802881531605e-01, -1.7575205891413051e-02,
       3.3574782433024733e-03, -1.6854401941563681e-03,
       1.1661231980890167e-01 ]
avg_reprojection_error: 5.4152148431251057e-01

搞定