相机的校正感悟

 在你看到这篇博文的时候,希望你能先看下我的上一篇博文,对相关的知识点有所了解后再看这篇博文

  下面的几个函数就是实现相机校正的关键

  • addChessboardPoints() 函数 - 用于读入一系列的棋盘图像并检测角点;
  • calibrate() 函数 - 用于进行相机校正,得到相机的参数矩阵和畸变系数;
  • remap() 函数 - 用于根据相机校正结果修复图像的畸变;//主要靠这个函数实现校正initUndistortRectifyMap
  • addPoints() 函数 - addChessboardPoints() 在检测完角点后会调用这个函数。也可自己手动调用这个函数添加已知的角点位置和对应的空间坐标点。
main.c 1 #include <QCoreApplication>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <vector>
 5 #include <opencv2/core/core.hpp>
 6 #include <opencv2/imgproc/imgproc.hpp>
 7 #include <opencv2/highgui/highgui.hpp>
 8 #include <opencv2/features2d/features2d.hpp>
 9
10 #include "CameraCalibrator.h"
11
12 int main()
13 {
14
15     cv::namedWindow("Image");
16     cv::Mat image;
17     std::vector<std::string> filelist;
18
19     // generate list of chessboard image filename
20     for (int i=1; i<=20; i++) {
21
22         std::stringstream str;
23         str << "/home/bi/pic/chessboards/chessboard" << std::setw(2) << std::setfill(‘0‘) << i << ".jpg";
24         std::cout << str.str() << std::endl;
25
26         filelist.push_back(str.str());
27         image= cv::imread(str.str(),0);//直接变为灰度图
28         //cvtColor(image,image,CV_BGR2GRAY);
29         cv::imshow("Image",image);
30
31          cv::waitKey(1000);
32     }
33
34     // Create calibrator object
35     CameraCalibrator cameraCalibrator;
36     // add the corners from the chessboard
37     cv::Size boardSize(6,4);
38     cameraCalibrator.addChessboardPoints(
39         filelist,    // filenames of chessboard image
40         boardSize);    // size of chessboard
41         // calibrate the camera
42     //    cameraCalibrator.setCalibrationFlag(true,true);
43     cameraCalibrator.calibrate(image.size());
44
45     // Image Undistortion
46     image = cv::imread(filelist[6]);
47     cv::Mat uImage= cameraCalibrator.remap(image);
48
49     // display camera matrix
50     cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix();
51     std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl;
52     std::cout << cameraMatrix.at<double>(0,0) << " " << cameraMatrix.at<double>(0,1) << " " << cameraMatrix.at<double>(0,2) << std::endl;
53     std::cout << cameraMatrix.at<double>(1,0) << " " << cameraMatrix.at<double>(1,1) << " " << cameraMatrix.at<double>(1,2) << std::endl;
54     std::cout << cameraMatrix.at<double>(2,0) << " " << cameraMatrix.at<double>(2,1) << " " << cameraMatrix.at<double>(2,2) << std::endl;
55
56     imshow("Original Image", image);
57     imshow("Undistorted Image", uImage);
58
59     cv::waitKey();
60     return 0;
61 }

CameraCalibrator.h 

  • addChessboardPoints() 函数 - 用于读入一系列的棋盘图像并检测角点;
  • calibrate() 函数 - 用于进行相机校正,得到相机的参数矩阵和畸变系数;
  • remap() 函数 - 用于根据相机校正结果修复图像的畸变;//主要靠这个函数实现校正initUndistortRectifyMap
  • addPoints() 函数addChessboardPoints() 在检测完角点后会调用这个函数。也可自己手动调用这个函数添加已知的角点位置和对应的空间坐标点。

 1 #ifndef CAMERACALIBRATOR_H
 2 #define CAMERACALIBRATOR_H
 3
 4 #include <vector>
 5 #include <iostream>
 6
 7 #include <opencv2/core/core.hpp>
 8 #include "opencv2/imgproc/imgproc.hpp"
 9 #include "opencv2/calib3d/calib3d.hpp"
10 #include <opencv2/highgui/highgui.hpp>
11
12 class CameraCalibrator {
13
14     // input points
15     std::vector<std::vector<cv::Point3f>> objectPoints;
16     std::vector<std::vector<cv::Point2f>> imagePoints;
17     // output Matrices
18     cv::Mat cameraMatrix;
19     cv::Mat distCoeffs;
20     // flag to specify how calibration is done
21     int flag;
22     // used in image undistortion
23     cv::Mat map1,map2;
24     bool mustInitUndistort;
25
26   public:
27     CameraCalibrator() : flag(0), mustInitUndistort(true) {};
28
29     // Open the chessboard images and extract corner points
30     int addChessboardPoints(const std::vector<std::string>& filelist, cv::Size & boardSize);
31     // Add scene points and corresponding image points
32     void addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners);
33     // Calibrate the camera
34     double calibrate(cv::Size &imageSize);
35     // Set the calibration flag
36     void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false);
37     // Remove distortion in an image (after calibration)
38     cv::Mat CameraCalibrator::remap(const cv::Mat &image);
39
40     // Getters
41     cv::Mat getCameraMatrix() { return cameraMatrix; }
42     cv::Mat getDistCoeffs()   { return distCoeffs; }
43 };
44
45 #endif // CAMERACALIBRATOR_H

CameraCalibrator.cpp

  1 #include "CameraCalibrator.h"
  2
  3 // Open chessboard images and extract corner points
  4 int CameraCalibrator::addChessboardPoints(
  5          const std::vector<std::string>& filelist,
  6          cv::Size & boardSize) {
  7
  8     // the points on the chessboard
  9     std::vector<cv::Point2f> imageCorners;
 10     std::vector<cv::Point3f> objectCorners;
 11
 12     // 3D Scene Points:
 13     // Initialize the chessboard corners
 14     // in the chessboard reference frame
 15     // The corners are at 3D location (X,Y,Z)= (i,j,0)
 16     for (int i=0; i<boardSize.height; i++) {
 17         for (int j=0; j<boardSize.width; j++) {
 18
 19             objectCorners.push_back(cv::Point3f(i, j, 0.0f));
 20         }
 21     }
 22
 23     // 2D Image points:
 24     cv::Mat image; // to contain chessboard image
 25     int successes = 0;
 26     // for all viewpoints
 27     for (int i=0; i<filelist.size(); i++) {
 28
 29         // Open the image
 30         image = cv::imread(filelist[i],0);
 31
 32         // Get the chessboard corners
 33         bool found = cv::findChessboardCorners(
 34                         image, boardSize, imageCorners);
 35
 36         // Get subpixel accuracy on the corners
 37         cv::cornerSubPix(image, imageCorners,
 38                   cv::Size(5,5),
 39                   cv::Size(-1,-1),
 40             cv::TermCriteria(cv::TermCriteria::MAX_ITER +
 41                           cv::TermCriteria::EPS,
 42              30,        // max number of iterations
 43              0.1));     // min accuracy
 44
 45           // If we have a good board, add it to our data
 46           if (imageCorners.size() == boardSize.area()) {
 47
 48             // Add image and scene points from one view
 49             addPoints(imageCorners, objectCorners);
 50             successes++;
 51           }
 52
 53         //Draw the corners
 54         cv::drawChessboardCorners(image, boardSize, imageCorners, found);
 55         cv::imshow("Corners on Chessboard", image);
 56         cv::waitKey(100);
 57     }
 58
 59     return successes;
 60 }
 61
 62 // Add scene points and corresponding image points
 63 void CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners) {
 64
 65     // 2D image points from one view
 66     imagePoints.push_back(imageCorners);
 67     // corresponding 3D scene points
 68     objectPoints.push_back(objectCorners);
 69 }
 70
 71 // Calibrate the camera
 72 // returns the re-projection error
 73 double CameraCalibrator::calibrate(cv::Size &imageSize)
 74 {
 75     // undistorter must be reinitialized
 76     mustInitUndistort= true;
 77
 78     //Output rotations and translations
 79     std::vector<cv::Mat> rvecs, tvecs;
 80
 81     // start calibration
 82     return
 83      calibrateCamera(objectPoints, // the 3D points
 84                     imagePoints,  // the image points
 85                     imageSize,    // image size
 86                     cameraMatrix, // output camera matrix
 87                     distCoeffs,   // output distortion matrix
 88                     rvecs, tvecs, // Rs, Ts
 89                     flag);        // set options
 90 //                    ,CV_CALIB_USE_INTRINSIC_GUESS);
 91
 92 }
 93
 94 // remove distortion in an image (after calibration)
 95 cv::Mat CameraCalibrator::remap(const cv::Mat &image) {
 96
 97     cv::Mat undistorted;
 98
 99     if (mustInitUndistort) { // called once per calibration
100
101         cv::initUndistortRectifyMap(
102             cameraMatrix,  // computed camera matrix
103             distCoeffs,    // computed distortion matrix
104             cv::Mat(),     // optional rectification (none)
105             cv::Mat(),     // camera matrix to generate undistorted
106             cv::Size(640,480),
107 //            image.size(),  // size of undistorted
108             CV_32FC1,      // type of output map
109             map1, map2);   // the x and y mapping functions
110
111         mustInitUndistort= false;
112     }
113
114     // Apply mapping functions
115     cv::remap(image, undistorted, map1, map2,
116         cv::INTER_LINEAR); // interpolation type
117
118     return undistorted;
119 }
120
121
122 // Set the calibration options
123 // 8radialCoeffEnabled should be true if 8 radial coefficients are required (5 is default)
124 // tangentialParamEnabled should be true if tangeantial distortion is present
125 void CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, bool tangentialParamEnabled) {
126
127     // Set the flag used in cv::calibrateCamera()
128     flag = 0;
129     if (!tangentialParamEnabled) flag += CV_CALIB_ZERO_TANGENT_DIST;
130     if (radial8CoeffEnabled) flag += CV_CALIB_RATIONAL_MODEL;
131 }

findChessboardCorners

Finds the positions of internal corners of the chessboard.
C++: bool findChessboardCorners(InputArray image, Size patternSize, OutputArray corners, int
flags=CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE
)//如果找到了棋盘内部的角点,会返回true这个时候正好对应绘制角点的patternWasFound

Parameters
image – Source chessboard view. It must be an 8-bit grayscale or color image.
patternSize – Number of inner corners per a chessboard row and column ( patternSize
= cvSize(points_per_row,points_per_colum) = cvSize(columns,rows) ).
corners – Output array of detected corners.
flags – Various operation flags that can be zero or a combination of the following values:
– CV_CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image
to black and white, rather than a fixed threshold level (computed from the average
image brightness).
– CV_CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with
equalizeHist() before applying fixed or adaptive thresholding.
– CV_CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter,
square-like shape) to filter out false quads extracted at the contour retrieval stage.
– CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard
corners, and shortcut the call if none is found. This can drastically speed up the call in
the degenerate condition when no chessboard is observed.

drawChessboardCorners
Renders the detected chessboard corners.
C++: void drawChessboardCorners(InputOutputArray image, Size patternSize, InputArray corners, bool
patternWasFound)
Python: cv2.drawChessboardCorners(image, patternSize, corners, patternWasFound)! None
C: void cvDrawChessboardCorners(CvArr* image, CvSize patternSize, CvPoint2D32f* corners, int
count, int patternWasFound)
Python: cv.DrawChessboardCorners(image, patternSize, corners, patternWasFound)! None
Parameters
image – Destination image. It must be an 8-bit color image.
patternSize – Number of inner corners per a chessboard row and column (patternSize =
cv::Size(points_per_row,points_per_column)).//注意这里表示的是棋盘的大小,别弄错了
corners – Array of detected corners, the output of findChessboardCorners.
patternWasFound – Parameter indicating whether the complete board was found or not.
The return value of findChessboardCorners() should be passed here.
The function draws individual chessboard corners detected either as red circles if the board was not found, or as
colored corners connected with lines if the board was found.

initUndistortRectifyMap
Computes the undistortion and rectification transformation map.
C++: void initUndistortRectifyMap(InputArray cameraMatrix, InputArray distCoeffs, InputArray R,
InputArray newCameraMatrix, Size size, int m1type, OutputArray
map1, OutputArray map2)

Parameters

cameraMatrix – Input camera matrix A =

cameraMatrix //不用解释了吧 相机的内参矩阵

distCoeffs畸变矩阵 – Input vector of distortion coefficients (k1; k2; p1; p2[; k3[; k4; k5; k6]]) of 4,

5, or 8 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed.

R代表的是旋转矩阵

R – Optional rectification transformation in the object space (3x3 matrix). R1 or R2 , computed
by stereoRectify() can be passed here. If the matrix is empty, the identity transformation
is assumed. In cvInitUndistortMap R assumed to be an identity matrix.


newCameraMatrix – New camera matrix A0 =

size – Undistorted image size.
m1type – Type of the first output map that can be CV_32FC1 or CV_16SC2 . See
convertMaps() for details.
map1 – The first output map.//即是 u

map2 – The second output map.//即是 v

时间: 2024-08-28 12:21:50

相机的校正感悟的相关文章

基于OpenCV立体视觉标定和校正

这几天学习双目视觉标定,分别使用了两种工具:OpenCV和Matlab.Matlab的效果非常稳定,但是一开始OpenCV的效果很糟糕,要不是出现中断就是标定出来的结果数值很大.经过了几天的不断调试和更改,终于把OpenCV的立体视觉标定和校正的程序写出来了.立体标定时计算空间上的两台摄像机几何关系的过程,立体校正则是对个体图像进行纠正,保证这些图像可以从平面对准的两幅图像获得.程序的框架如下: 1.读取左右相机图片序列 双目相机的图片序列放在Demon的路径下,左右相机的图像的名字分别存放在两

全景视频拼接(二)--OpenCV源码解析

本文参考:http://blog.csdn.net/skeeee/article/details/19480693,做了一定修改和补充. 一.stitching_detail程序运行流程 1.命令行调用程序,输入源图像以及程序的参数 2.特征点检测,判断是使用surf还是orb,默认是surf. 3.对图像的特征点进行匹配,使用最近邻和次近邻方法,将两个最优的匹配的置信度保存下来. 4.对图像进行排序以及将置信度高的图像保存到同一个集合中,删除置信度比较低的图像间的匹配,得到能正确匹配的图像序列

stitching_detail算法介绍

一.stitching_detail程序运行流程 1.命令行调用程序,输入源图像以及程序的参数 2.特征点检测,判断是使用surf还是orb,默认是surf. 3.对图像的特征点进行匹配,使用最近邻和次近邻方法,将两个最优的匹配的置信度保存下来. 4.对图像进行排序以及将置信度高的图像保存到同一个集合中,删除置信度比较低的图像间的匹配,得到能正确匹配的图像序列.这样将置信度高于门限的所有匹配合并到一个集合中. 5.对所有图像进行相机参数粗略估计,然后求出旋转矩阵 6.使用光束平均法进一步精准的估

任意n张图像拼接_效果很好_计算机视觉大作业1终版

#include <iostream> #include <fstream> #include <string> #include "opencv2/opencv_modules.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/stitching/detail/autocalib.hpp" #include "opencv2/

视觉SLAM方向找工作经历

秋招已经过去了两个多月了,一直拖到现在2017年快完了才"舍得"写== 先说一下自己的基本情况,985硕士一枚,有还不错的一作会议论文,一直专注在视觉SLAM和三维重建方面,SLAM和三维重建内容都很多,我懂的并不够精. 虽然心里一直想早点开始准备,但是实验室的事情也比较多,还是拖到了2017年年初才开始花时间去准备,同时还在写一篇论文.实习很重要,实习基本都能留下,多一次实习多一个机会,有机会去的话能去就去.大厂的实习招聘大概在3~4月份,过完年之后就开始准备数据结构这块的知识,主要

ubuntu16.04下笔记本自带摄像头编译运行PTAM

转载请注明链接:https://i.cnblogs.com/EditPosts.aspx?postid=9014147 个人邮箱:[email protected] 北航飞控一体化技术重点实验室 PTAM是视觉slam的一种开源算法,并做了关于增强现实的应用.代码是完全开源的,可以从github上获取:地址 作者2008年的文章 Parallel tracking and mapping for Small AR workspaces 支持多个系统上编译运行,可以在作者的项目主页上获取一些在其他

ros下单目相机校正

1. 安装相应的驱动与程序包. 图像相应包   http://wiki.ros.org/camera_calibration          在gitbub下载image_pipeline :      https://github.com/ros-perception/image_pipeline 安装相应的驱动 1)uvc_camera          ktossell/camera_umd                   sudo apt-get install ros-indig

双摄像头立体成像(三)-畸变矫正与立体校正

畸变矫正是上一篇博文的遗留问题,当畸变系数和内外参数矩阵标定完成后,就应该进行畸变的矫正,以达到消除畸变的目的,此其一. 在该系列第一部分的博文中介绍的立体成像原理中提到,要通过两幅图像估计物点的深度信息,就必须在两幅图像中准确的匹配到同一物点,这样才能根据该物点在两幅图像中的位置关系,计算物体深度.为了降低匹配的计算量,两个摄像头的成像平面应处于同一平面.但是,单单依靠严格的摆放摄像头来达到这个目的显然有些困难.立体校正就是利用几何图形变换(Geometric Image Transforma

双目相机标定以及立体测距原理及OpenCV实现

作者:dcrmg 单目相机标定的目标是获取相机的内参和外参,内参(1/dx,1/dy,Cx,Cy,f)表征了相机的内部结构参数,外参是相机的旋转矩阵R和平移向量t.内参中dx和dy是相机单个感光单元芯片的长度和宽度,是一个物理尺寸,有时候会有dx=dy,这时候感光单元是一个正方形.Cx和Cy分别代表相机感光芯片的中心点在x和y方向上可能存在的偏移,因为芯片在安装到相机模组上的时候,由于制造精度和组装工艺的影响,很难做到中心完全重合.f代表相机的焦距. 双目标定的第一步需要分别获取左右相机的内外参