Reconstrução tridimensional OpenCV (2) - processo de calibração do pacote

Reconstrução tridimensional OpenCV (2) - processo de calibração do pacote

Agora que o ponto de calibração foi encontrado, a próxima tarefa é usar o resultado da calibração. [A organização do conteúdo deste livro aqui é inexplicável] Mas ao ler o código, ele pode ser facilmente vinculado.

/ ------------------------------------------------- -----------------------------------------
Este arquivo contém material de apoio ao capítulo 11 do livro:
OpenCV3 Computer Vision Application Programming Cookbook
Terceira edição
de Robert Laganiere, Packt Publishing, 2016.
Este programa é um software livre; permissão é concedida para usar, copiar, modificar
e distribuir este código-fonte, ou partes dele, para qualquer propósito, sem taxas,
sujeito à restrição de que o aviso de copyright não pode ser removido
ou alterado de qualquer fonte ou distribuição de fonte alterada.
O software é lançado no estado em que se encontra e sem garantias de qualquer tipo.
Em particular, não é garantido que o software seja tolerante a falhas ou livre de falhas.
O autor se isenta de todas as garantias com relação a este software, qualquer uso
e qualquer falha conseqüente, é puramente responsabilidade do usuário.
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 arquivo contém material capítulo de apoio 11 do livro:
OpenCV3 Computer Vision Application Programming Cookbook
Terceira edição
de Robert Laganiere, Packt Publishing, 2016.
Este programa é um software livre; permissão é concedida para usar, copiar, modificar
e distribuir este código-fonte, ou partes dele, para qualquer propósito, sem taxas,
sujeito à restrição de que o aviso de copyright não pode ser removido
ou alterado de qualquer fonte ou distribuição de fonte alterada.
O software é lançado no estado em que se encontra e sem garantias de qualquer tipo.
Em particular, não é garantido que o software seja tolerante a falhas ou livre de falhas.
O autor se isenta de todas as garantias com relação a este software, qualquer uso
e qualquer falha conseqüente, é puramente responsabilidade do usuário.
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 arquivo contém material de apoio ao capítulo 11 do livro:
OpenCV3 Computer Vision Application Programming Cookbook
Terceira edição
de Robert Laganiere, Packt Publishing, 2016.
Este programa é um software livre; permissão é concedida para usar, copiar, modificar
e distribuir este código-fonte, ou partes dele, para qualquer propósito, sem taxas,
sujeito à restrição de que o aviso de copyright não pode ser removido
ou alterado de qualquer fonte ou distribuição de fonte alterada.
O software é lançado no estado em que se encontra e sem garantias de qualquer tipo.
Em particular, não é garantido que o software seja tolerante a falhas ou livre de falhas.
O autor se isenta de todas as garantias com relação a este software, qualquer uso
e qualquer falha conseqüente, é puramente responsabilidade do usuário.
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;
}

Depois de três rodadas consecutivas, os resultados da calibração podem ser obtidos e parecem bons.O problema é a falta de quantificação.
Insira a descrição da imagem aqui

O efeito parece ser melhor:
Insira a descrição da imagem aquiInsira a descrição da imagem aqui

Pode-se ver a partir do limite que foi muito puxado, mas na verdade, se você não analisar cuidadosamente, você realmente não pode ver.

Do Wiz

Lista de anexos

Direção atual: costura e fusão de imagens, reconhecimento de imagens Contato: [email protected]

Acho que você gosta

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