Reconstrucción tridimensional de OpenCV (2) - proceso de calibración de paquetes

Reconstrucción tridimensional de OpenCV (2) - proceso de calibración de paquetes

Ahora que se ha encontrado el punto de calibración, la siguiente tarea es utilizar el resultado de la calibración. [La organización del contenido de este libro aquí es inexplicable] Pero al leer el código, se pueden vincular fácilmente.

/ ------------------------------------------------- -----------------------------------------
Este archivo contiene material de apoyo al capítulo 11 de la libro:
OpenCV3 Computer Vision Application Programming Cookbook
Third Edition
por Robert Laganiere, Packt Publishing, 2016.
Este programa es software gratuito; Por la presente se otorga permiso para usar, copiar, modificar
y distribuir este código fuente, o partes del mismo, para cualquier propósito, sin cargo,
sujeto a la restricción de que el aviso de derechos de autor no puede ser eliminado
o alterado de ninguna fuente o distribución de fuente alterada.
El software se publica tal cual y sin garantías de ningún tipo.
En particular, no se garantiza que el software sea tolerante a fallas o que esté libre de fallas.
El autor niega todas las garantías con respecto a este software, cualquier uso
y cualquier falla consiguiente, es puramente responsabilidad del usuario.
Copyright © 2016 Robert Laganiere, www.laganiere.name

* -------------------------------------- -------------------------------------------------- - * /

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features2d.hpp>
#include "CameraCalibrator.h"
int main()
{
    cv::Mat image;
    std::vector<std::string> filelist;
    // 按照规则读入27张图片
    // 名称为 chessboard01 to chessboard27 
    for (int i=1; i<=27; i++) {
        std::stringstream str;
        str << "E:/template/calibrateImages/calibrate" << std::setw(2) << std::setfill('0') << i << ".bmp";
        std::cout << str.str() << std::endl;
        filelist.push_back(str.str());
        image= cv::imread(str.str(),0);
    }
    // 创建Calibrator类
    CameraCalibrator cameraCalibrator;
    // 根据图片实际情况定下boardSize
    cv::Size boardSize(8,6);
    cameraCalibrator.addChessboardPoints(
        filelist,    // filenames of chessboard image
        boardSize, "Detected points");    // size of chessboard
    // calibrate the camera
    cameraCalibrator.setCalibrationFlag(true,true);
    cameraCalibrator.calibrate(image.size());
    // 测试标定获得的结果
    image = cv::imread(filelist[1],0);
    cv::Size newSize(static_cast<int>(image.cols*1.5), static_cast<int>(image.rows*1.5));
    cv::Mat uImage= cameraCalibrator.remap(image, newSize);
    // display camera matrix
    cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix();
    std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl;
    std::cout << cameraMatrix.at<double>(0,0) << " " << cameraMatrix.at<double>(0,1) << " " << cameraMatrix.at<double>(0,2) << std::endl;
    std::cout << cameraMatrix.at<double>(1,0) << " " << cameraMatrix.at<double>(1,1) << " " << cameraMatrix.at<double>(1,2) << std::endl;
    std::cout << cameraMatrix.at<double>(2,0) << " " << cameraMatrix.at<double>(2,1) << " " << cameraMatrix.at<double>(2,2) << std::endl;
    cv::namedWindow("Original Image");
    cv::imshow("Original Image", image);
    cv::namedWindow("Undistorted Image");
    cv::imshow("Undistorted Image", uImage);
    // Store everything in a xml file
    cv::FileStorage fs("calib.xml", cv::FileStorage::WRITE);
    fs << "Intrinsic" << cameraMatrix;
    fs << "Distortion" << cameraCalibrator.getDistCoeffs();
    cv::waitKey();
    return 0;
}

下面 是 类库 :
/ -------------------------------------------- ----------------------------------------------
Este archivo contiene material el capítulo de apoyo 11 del libro:
OpenCV3 Computer Vision Application Programming Cookbook
Third Edition
por Robert Laganiere, Packt Publishing, 2016.
Este programa es software gratuito; Por la presente se otorga permiso para usar, copiar, modificar
y distribuir este código fuente, o partes del mismo, para cualquier propósito, sin cargo,
sujeto a la restricción de que el aviso de derechos de autor no puede ser eliminado
o alterado de ninguna fuente o distribución de fuente alterada.
El software se publica tal cual y sin garantías de ningún tipo.
En particular, no se garantiza que el software sea tolerante a fallas o que esté libre de fallas.
El autor niega todas las garantías con respecto a este software, cualquier uso
y cualquier falla consiguiente, es puramente responsabilidad del usuario.
Copyright © 2016 Robert Laganiere, www.laganiere.name

* -------------------------------------- -------------------------------------------------- - * /

#ifndef CAMERACALIBRATOR_H
#define CAMERACALIBRATOR_H
#include <vector>
#include <iostream>
#include <opencv2/core.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/calib3d.hpp"
#include <opencv2/highgui.hpp>
class CameraCalibrator {
    // 输入点:  
    // 世界坐标系中的点 
    //(每个正方形为一个单位) 
    std::vector<std::vector<cv::Point3f> > objectPoints;
    // 点在图像中的位置(以像素为单位) 
    std::vector<std::vector<cv::Point2f> > imagePoints;
    // 输出矩阵 
    cv::Mat cameraMatrix;
    cv::Mat distCoeffs;
    // 指定标定方式的标志
    int flag;
    // used in image undistortion 
    cv::Mat map1,map2; 
    bool mustInitUndistort;
  public:
    CameraCalibrator() : flag(0), mustInitUndistort(true) {}
    // Open the chessboard images and extract corner points
    int addChessboardPoints(const std::vector<std::string>& filelist, cv::Size & boardSize, std::string windowName="");
    // Add scene points and corresponding image points
    void addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners);
    // Calibrate the camera
    double calibrate(const cv::Size imageSize);
    // Set the calibration flag
    void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false);
    // Remove distortion in an image (after calibration)
    cv::Mat remap(const cv::Mat &image, cv::Size &outputSize = cv::Size(-1, -1));
    // Getters
    cv::Mat getCameraMatrix() { return cameraMatrix; }
    cv::Mat getDistCoeffs()   { return distCoeffs; }
};
#endif // CAMERACALIBRATOR_H

/ ------------------------------------------------- -----------------------------------------
Este archivo contiene material de apoyo al capítulo 11 de la libro:
OpenCV3 Computer Vision Application Programming Cookbook
Third Edition
por Robert Laganiere, Packt Publishing, 2016.
Este programa es software gratuito; Por la presente se otorga permiso para usar, copiar, modificar
y distribuir este código fuente, o partes del mismo, para cualquier propósito, sin cargo,
sujeto a la restricción de que el aviso de derechos de autor no puede ser eliminado
o alterado de ninguna fuente o distribución de fuente alterada.
El software se publica tal cual y sin garantías de ningún tipo.
En particular, no se garantiza que el software sea tolerante a fallas o que esté libre de fallas.
El autor niega todas las garantías con respecto a este software, cualquier uso
y cualquier falla consiguiente, es puramente responsabilidad del usuario.
Copyright © 2016 Robert Laganiere, www.laganiere.name

* -------------------------------------- -------------------------------------------------- - * /

#include "stdafx.h"
#include "CameraCalibrator.h"
// 打开棋盘图像,提取角点 
int CameraCalibrator::addChessboardPoints(
         const std::vector<std::string>& filelist, // 文件名列表
         cv::Size & boardSize,                     // 标定面板的大小 
         std::string windowName) {                 // name of window to display results
                                                   // if null, no display shown
    // 棋盘上的角点 
    std::vector<cv::Point2f> imageCorners;
    std::vector<cv::Point3f> objectCorners;
    // 场景中的三维点: 
    // 在棋盘坐标系中,初始化棋盘中的角点 
    // 角点的三维坐标(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, j, 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); // 检测到角点的列表
        // 取得角点上的亚像素级精度
        if (found) {
            cv::cornerSubPix(image, imageCorners,
                cv::Size(5, 5), // 搜索窗口的半径 
                cv::Size(-1, -1),
                cv::TermCriteria(cv::TermCriteria::MAX_ITER +
                    cv::TermCriteria::EPS,
                    30,        // 最大迭代次数 
                    0.1));  // 最小精度 
            // 如果棋盘是完好的,就把它加入结果  
            if (imageCorners.size() == boardSize.area()) {
                // 加入从同一个视角得到的图像和场景点 
                addPoints(imageCorners, objectCorners);
                successes++;
            }
        }
        if (windowName.length()>0 && imageCorners.size() == boardSize.area()) {
        
            //Draw the corners
            cv::drawChessboardCorners(image, boardSize, imageCorners, found);
            cv::imshow(windowName, image);
            cv::waitKey(100);
        }
    }
    return successes;
}
// Add scene points and corresponding image points
void CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners) {
    // 2D image points from one view
    imagePoints.push_back(imageCorners);          
    // corresponding 3D scene points
    objectPoints.push_back(objectCorners);
}
// 标定相机 
// 返回重投影误差 
double CameraCalibrator::calibrate(const cv::Size imageSize)
{
    mustInitUndistort= true;
    // 输出旋转量和平移量 
    std::vector<cv::Mat> rvecs, tvecs;
    // 开始标定
    return 
     calibrateCamera(objectPoints, // 三维点 
                    imagePoints,   // 图像点 
                    imageSize,     // 图像尺寸 
                    cameraMatrix,  // 输出相机矩阵 
                    distCoeffs,    // 输出畸变矩阵 
                    rvecs, tvecs,  // Rs、Ts 
                    flag);         // 设置选项 
//                    ,CV_CALIB_USE_INTRINSIC_GUESS);
}
// 去除图像中的畸变(标定后) 
cv::Mat CameraCalibrator::remap(const cv::Mat &image, cv::Size &outputSize) {
    cv::Mat undistorted;
    if (outputSize.height == -1)
        outputSize = image.size();
    if (mustInitUndistort) { // 每个标定过程调用一次  
    
        cv::initUndistortRectifyMap(
            cameraMatrix,  // 计算得到的相机矩阵 
            distCoeffs,    // 计算得到的畸变矩阵 
            cv::Mat(),     // 可选矫正项(无) 
            cv::Mat(),     // 生成无畸变的相机矩阵
            outputSize,    // 无畸变图像的尺寸
            CV_32FC1,      // 输出图片的类型 
            map1, map2);   // x 和 y 映射功能 
        mustInitUndistort= false;
    }
    // Apply mapping functions
    cv::remap(image, undistorted, map1, map2, 
        cv::INTER_LINEAR); // interpolation type
    return undistorted;
}
// Set the calibration options
// 8radialCoeffEnabled should be true if 8 radial coefficients are required (5 is default)
// tangentialParamEnabled should be true if tangeantial distortion is present
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;
}

Después de tres rondas consecutivas, los resultados de la calibración se pueden obtener y se ven bien. El problema es la falta de cuantificación.
Inserte la descripción de la imagen aquí

El efecto parece ser mejor:
Inserte la descripción de la imagen aquíInserte la descripción de la imagen aquí

Desde el límite se puede ver que se ha tirado mucho, pero de hecho, si no lo analizas con cuidado, realmente no puedes verlo.

De Wiz

Lista de adjuntos

Dirección actual: costura y fusión de imágenes, reconocimiento de imágenes Contacto: [email protected]

Supongo que te gusta

Origin blog.csdn.net/m0_51233386/article/details/113487555
Recomendado
Clasificación