1. 程式人生 > >opencv---相機標定

opencv---相機標定

參考文章

座標系之間的關係

計算機視覺領域中常見的三個座標系:影象座標系,相機座標系,世界座標系

影象座標系—理想影象座標系和實際影象座標系

這裡寫圖片描述

上圖中:

這裡寫圖片描述
實際的影象座標系原點為這裡寫圖片描述
二者之間的關係式為(1)(2),(1)(2)也可以用矩陣(3)表示出來.

相機座標系(C)和世界座標系(W)

這裡寫圖片描述
通過相機與影象的投影關係,我們得到了等式(4)和等式(5),可以用矩陣形式(6)表示

同時,相機座標系與世界座標的關係可以用等式(7)來表示
這裡寫圖片描述

影象座標系和世界座標系的關係

由等式(3),等式(6)和等式(7)我們可以推導二者之間的關係。

這裡寫圖片描述

其中M1稱為相機的內參矩陣,包含內參(fx,fy,u0,v0)。
M2稱為相機的外參矩陣,包含外參(R:旋轉矩陣,T:平移矩陣)

畸變

這裡寫圖片描述
k1,k2,k3,k4,k5,k6為徑向畸變,p1,p2為切向畸變

張正友相機標定法

在OpenCV中我們使用張正友相機標定法通過10幅不同角度的棋盤影象來標定相機獲得相機內參和畸變係數。

相機標定的基本概念

相機標定的目的

獲取攝像機的內參和外參矩陣(同時也會得到每一幅標定影象的選擇和平移矩陣),內參和外參係數可以對之後相機拍攝的影象就進行矯正,得到畸變相對很小的影象。

相機標定的輸入

標定影象上所有內角點的影象座標,標定板影象上所有內角點的空間三維座標(一般情況下假定影象位於Z=0平面上)。

相機標定的輸出

攝像機的內參、外參係數。

矯正原始影象的完整流程

1. 準備標定圖片

標定圖片需要使用標定板在不同位置、不同角度、不同姿態下拍攝,最少需要3張,以10~20張為宜。標定板需要是黑白相間的矩形構成的棋盤圖,製作精度要求較高,如下圖所示
這裡寫圖片描述

2. 對每一張標定圖片,提取角點資訊

需要使用findChessboardCorners函式提取角點,這裡的角點專指的是標定板上的內角點,這些角點與標定板的邊緣不接觸

findChessboardCorners函式原型
bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,
                                         int
flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
  • Image,傳入拍攝的棋盤圖Mat影象,必須是8位的灰度或者彩色影象;
  • patternSize,每個棋盤圖上內角點的行列數,一般情況下,行列數不要相同,便於後續標定程式識別標定板的方向;
    -corners,用於儲存檢測到的內角點影象座標位置,一般用元素是Point2f的向量來表示:vector image_points_buf;
  • flags:用於定義棋盤圖上內角點查詢的不同處理方式,有預設值。

對每一張標定圖片,進一步提取亞畫素角點資訊

為了提高標定精度,需要在初步提取的角點資訊上進一步提取亞畫素資訊,降低相機標定偏差,常用的方法是cornerSubPix

cornerSubPix函式原型
void cornerSubPix( InputArray image, InputOutputArray corners,
                                Size winSize, Size zeroZone,
                                TermCriteria criteria );

-image,輸入的Mat矩陣,最好是8位灰度影象,檢測效率更高;
- corners,初始的角點座標向量,同時作為亞畫素座標位置的輸出,所以需要是浮點型資料,一般用元素是Pointf2f/Point2d的向量來表示:vector

find4QuadCornerSubpix函式原型
bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size );
  • 第一個引數img,輸入的Mat矩陣,最好是8位灰度影象,檢測效率更高;
  • 第二個引數corners,初始的角點座標向量,同時作為亞畫素座標位置的輸出,所以需要是浮點型資料,一般用元素是Pointf2f/Point2d的向量來表示:vector

在棋盤標定圖上繪製找到的內角點(非必須,僅為了顯示)

drawChessboardCorners函式用於繪製被成功標定的角點

 drawChessboardCorners( InputOutputArray image, Size patternSize,
                        InputArray corners, bool patternWasFound );
  • image,8位灰度或者彩色影象;
  • patternSize,每張標定棋盤上內角點的行列數;
  • corners,初始的角點座標向量,同時作為亞畫素座標位置的輸出,所以需要是浮點型資料,一般用元素是Pointf2f/Point2d的向量來表示:vector

相機標定

  • 對標定結果進行評價
double calibrateCamera( InputArrayOfArrays objectPoints,
                        InputArrayOfArrays imagePoints, Size imageSize,
                        InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
                        OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
                        int flags = 0, TermCriteria criteria = TermCriteria(
                        TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );
  • objectPoints: 一組世界座標系中的3D
  • imagePoints: 超過10張圖片的角點集合
  • imageSize: 每張圖片的大小
  • cameraMatrix: 內參矩陣
  • distCoeffs: 畸變矩陣(預設獲得5個即便引數k1,k2,p1,p2,k3,可修改)
  • rvecs: 外參:旋轉向量
  • tvecs: 外參:平移向量
  • flag: 標定時的一些選項:
    CV_CALIB_USE_INTRINSIC_GUESS:使用該引數時,在cameraMatrix矩陣中應該有fx,fy,u0,v0的估計值。否則的話,將初始化(u0,v0)影象的中心點,使用最小二乘估算出fx,fy。
    CV_CALIB_FIX_PRINCIPAL_POINT:在進行優化時會固定光軸點。當CV_CALIB_USE_INTRINSIC_GUESS引數被設定,光軸點將保持在中心或者某個輸入的值。
    CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只將fy作為可變數,進行優化計算。當CV_CALIB_USE_INTRINSIC_GUESS沒有被設定,fx和fy將會被忽略。只有fx/fy的比值在計算中會被用到。
    CV_CALIB_ZERO_TANGENT_DIST:設定切向畸變引數(p1,p2)為零。
    CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:對應的徑向畸變在優化中保持不變。
    CV_CALIB_RATIONAL_MODEL:計算k4,k5,k6三個畸變引數。如果沒有設定,則只計算其它5個畸變引數。

對標定結果進行評價

對標定結果進行評價的方法是通過得到的攝像機內外引數,對空間的三維點進行重新投影計算,得到空間三維點在影象上新的投影點的座標,計算投影座標和亞畫素角點座標之間的偏差,偏差越小,標定結果越好。

對空間三維座標點進行反向投影的函式是projectPoints
 void projectPoints( InputArray objectPoints,
                                 InputArray rvec, InputArray tvec,
                                 InputArray cameraMatrix, InputArray distCoeffs,
                                 OutputArray imagePoints,
                                 OutputArray jacobian=noArray(),
                                 double aspectRatio=0 );
  • 第一個引數objectPoints,為相機座標系中的三維點座標;
  • 第二個引數rvec為旋轉向量,每一張影象都有自己的選擇向量;
  • 第三個引數tvec為位移向量,每一張影象都有自己的平移向量;
  • 第四個引數cameraMatrix為求得的相機的內參數矩陣;
  • 第五個引數distCoeffs為相機的畸變矩陣;
  • 第六個引數iamgePoints為每一個內角點對應的影象上的座標點;
  • 第七個引數jacobian是雅可比行列式;
  • 第八個引數aspectRatio是跟相機感測器的感光單元有關的可選引數,如果設定為非0,則函式預設感光單元的dx/dy是固定的,會依此對雅可比矩陣進行調整;

檢視標定效果——利用標定結果對棋盤圖進行矯正

利用求得的相機的內參和外引數據,可以對影象進行畸變的矯正

方法一:使用initUndistortRectifyMap和remap兩個函式配合實現。

initUndistortRectifyMap用來計算畸變對映,remap把求得的對映應用到影象上。

initUndistortRectifyMap的函式原型:

 void initUndistortRectifyMap( InputArray cameraMatrix, InputArray distCoeffs,
                               InputArray R, InputArray newCameraMatrix,
                               Size size, int m1type, OutputArray map1, OutputArray map2 );
  • 第一個引數cameraMatrix為之前求得的相機的內參矩陣;
  • 第二個引數distCoeffs為之前求得的相機畸變矩陣;
  • 第三個引數R,可選的輸入,是第一和第二相機座標之間的旋轉矩陣;
  • 第四個引數newCameraMatrix,輸入的校正後的3X3攝像機矩陣;
  • 第五個引數size,攝像機採集的無失真的影象尺寸;
  • 第六個引數m1type,定義map1的資料型別,可以是CV_32FC1或者CV_16SC2;
  • 第七個引數map1和第八個引數map2,輸出的X/Y座標重對映引數;

remap函式

 void remap( InputArray src, OutputArray dst,
                         InputArray map1, InputArray map2,
                         int interpolation, int borderMode=BORDER_CONSTANT,
                         const Scalar& borderValue=Scalar());引數src,輸入引數,代表畸變的原始影象;
  • 第二個引數dst,矯正後的輸出影象,跟輸入影象具有相同的型別和大小;
  • 第三個引數map1和第四個引數map2,X座標和Y座標的對映;
  • 第五個引數interpolation,定義影象的插值方式;
  • 第六個引數borderMode,定義邊界填充方式;
方法二:使用undistort函式實現

undistort函式原型:

 void undistort( InputArray src, OutputArray dst,
                 InputArray cameraMatrix,
                 InputArray distCoeffs,
                 InputArray newCameraMatrix=noArray() );
  • 第一個引數src,輸入引數,代表畸變的原始影象;
  • 第二個引數dst,矯正後的輸出影象,跟輸入影象具有相同的型別和大小;
  • 第三個引數cameraMatrix為之前求得的相機的內參矩陣;
  • 第四個引數distCoeffs為之前求得的相機畸變矩陣;
  • 第五個引數newCameraMatrix,預設跟cameraMatrix保持一致;

方法一相比方法二執行效率更高一些,推薦使用。

函式原型

The algorithm performs the following steps:

-   Compute the initial intrinsic parameters (the option only available for planar calibration
    patterns) or read them from the input parameters. The distortion coefficients are all set to
    zeros initially unless some of CV_CALIB_FIX_K? are specified.

-   Estimate the initial camera pose as if the intrinsic parameters have been already known. This is
    done using solvePnP .

-   Run the global Levenberg-Marquardt optimization algorithm to minimize the reprojection error,
    that is, the total sum of squared distances between the observed feature points imagePoints and
    the projected (using the current estimates for camera parameters and the poses) object points
    objectPoints. See projectPoints for details.

The function returns the final re-projection error.

@note
   If you use a non-square (=non-NxN) grid and findChessboardCorners for calibration, and
    calibrateCamera returns bad values (zero distortion coefficients, an image center very far from
    (w/2-0.5,h/2-0.5), and/or large differences between \f$f_x\f$ and \f$f_y\f$ (ratios of 10:1 or more)),
    then you have probably used patternSize=cvSize(rows,cols) instead of using
    patternSize=cvSize(cols,rows) in findChessboardCorners .

@sa
   findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, undistort
double calibrateCamera( InputArrayOfArrays objectPoints,
                        InputArrayOfArrays imagePoints, Size imageSize,
                        InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
                        OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
                        int flags = 0, TermCriteria criteria = TermCriteria(
                        TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );
  • objectPoints: 一組世界座標系中的3D
  • imagePoints: 超過10張圖片的角點集合
  • imageSize: 每張圖片的大小
  • cameraMatrix: 內參矩陣
  • distCoeffs: 畸變矩陣(預設獲得5個即便引數k1,k2,p1,p2,k3,可修改)
  • rvecs: 外參:旋轉向量
  • tvecs: 外參:平移向量
  • flag: 標定時的一些選項:
    CV_CALIB_USE_INTRINSIC_GUESS:使用該引數時,在cameraMatrix矩陣中應該有fx,fy,u0,v0的估計值。否則的話,將初始化(u0,v0)影象的中心點,使用最小二乘估算出fx,fy。
    CV_CALIB_FIX_PRINCIPAL_POINT:在進行優化時會固定光軸點。當CV_CALIB_USE_INTRINSIC_GUESS引數被設定,光軸點將保持在中心或者某個輸入的值。
    CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只將fy作為可變數,進行優化計算。當CV_CALIB_USE_INTRINSIC_GUESS沒有被設定,fx和fy將會被忽略。只有fx/fy的比值在計算中會被用到。
    CV_CALIB_ZERO_TANGENT_DIST:設定切向畸變引數(p1,p2)為零。
    CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:對應的徑向畸變在優化中保持不變。
    CV_CALIB_RATIONAL_MODEL:計算k4,k5,k6三個畸變引數。如果沒有設定,則只計算其它5個畸變引數。

執行程式碼

#include "mainwindow.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <QTextCodec>
#include <iostream>
#include <fstream>
#include<opencv2/features2d/features2d.hpp>
using namespace std;
using namespace cv;

enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 };


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /************************************************************************
               從攝像機中讀取多幅影象,從中提取出角點,然後對角點進行亞畫素精確化
     *************************************************************************/
    int image_count=  10;                    /****    影象數量     ****/
    Mat frame;
    Size image_size;                         /****     影象的尺寸      ****/
    Size board_size = Size(9,6);            /****    定標板上每行、列的角點數       ****/

    vector<Point2f> corners;                  /****    快取每幅影象上檢測到的角點       ****/
    vector<vector<Point2f>>  corners_Seq;    /****  儲存檢測到的所有角點       ****/
    ofstream fout("calibration_result.txt");  /**    儲存定標結果的檔案     **/
    int mode = DETECTION;//初始化模式為detection

    VideoCapture cap(0);
    cap.set(CV_CAP_PROP_FRAME_WIDTH,640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,480);
    if(!cap.isOpened()){
        std::cout<<"開啟攝像頭失敗,退出";
        exit(-1);
    }
    namedWindow("Calibration");
    std::cout<<"Press 'g' to start capturing images!"<<endl;

    int count = 0,n=0;
    stringstream tempname;
    string filename;
    int key;
    string msg;
    int baseLine;
    Size textSize;
    while(n < image_count )
    {
        frame.setTo(0);//將frame設定為空
        cap>>frame;
        if(mode == DETECTION)
        {
            key = 0xff & waitKey(30);
            if( (key & 255) == 27 )//如果key的值為ESC
                break;

            if( cap.isOpened() && key == 'g' )//如果按鍵為'g',將模式轉為CAPTURING
            {
                mode = CAPTURING;
            }
        }

        if(mode == CAPTURING)//當模式為CAPTURING時
        {
            key = 0xff & waitKey(30);
            if( (key & 255) == 32 )//判斷按鍵是否為‘space’
            {
                image_size = frame.size();
                /* 提取角點 */
                Mat imageGray;
                cvtColor(frame, imageGray , CV_RGB2GRAY);
                bool patternfound = findChessboardCorners(frame, board_size, corners,CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK );
                if (patternfound)
                {
                    n++;
                    tempname<<n;
                    tempname>>filename;
                    filename+=".jpg";
                    /* 亞畫素精確化 */
                    cornerSubPix(imageGray, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
                    count += corners.size();
                    corners_Seq.push_back(corners);
                    imwrite(filename,frame);
                    tempname.clear();
                    filename.clear();
                }
                else
                {
                    std::cout<<"Detect Failed.\n";
                }
            }
        }
        msg = mode == CAPTURING ? "100/100/s" : mode == CALIBRATED ? "Calibrated" : "Press 'g' to start";
        baseLine = 0;
        textSize = getTextSize(msg, 1, 1, 1, &baseLine);
        Point textOrigin(frame.cols - 2*textSize.width - 10, frame.rows - 2*baseLine - 10);

        if( mode == CAPTURING )
        {
            msg = format( "%d/%d",n,image_count);
        }

        putText( frame, msg, textOrigin, 1, 1,mode != CALIBRATED ? Scalar(0,0,255) : Scalar(0,255,0));

        imshow("Calibration",frame);
        key = 0xff & waitKey(1);
        if( (key & 255) == 27 )
            break;
    }

    std::cout<<"角點提取完成!\n";

    /************************************************************************
               攝像機定標
        *************************************************************************/
    std::cout<<"開始定標………………"<<endl;
    Size square_size = Size(25,25);                                      /**** 實際測量得到的定標板上每個棋盤格的大小   ****/
    vector<vector<Point3f>>  object_Points;                                      /****  儲存定標板上角點的三維座標   ****/

    Mat image_points = Mat(1, count , CV_32FC2, Scalar::all(0));          /*****   儲存提取的所有角點   *****/
    vector<int>  point_counts;                                          /*****    每幅影象中角點的數量    ****/
    Mat intrinsic_matrix = Mat(3,3, CV_32FC1, Scalar::all(0));                /*****    攝像機內參數矩陣    ****/
    Mat distortion_coeffs = Mat(1,5, CV_32FC1, Scalar::all(0));            /* 攝像機的5個畸變係數:k1,k2,p1,p2,k3 */
    vector<Mat> rotation_vectors;                                      /* 每幅影象的旋轉向量 */
    vector<Mat> translation_vectors;                                  /* 每幅影象的平移向量 */

    /* 初始化定標板上角點的三維座標 */
    for (int t=0;t<image_count;t++)
    {
        vector<Point3f> tempPointSet;
        for (int i=0;i<board_size.height;i++)//9
        {
            for (int j=0;j<board_size.width;j++)//6
            {
                /* 假設定標板放在世界座標系中z=0的平面上 */
                Point3f tempPoint;
                tempPoint.x = i*square_size.width;
                tempPoint.y = j*square_size.height;
                tempPoint.z = 0;
                tempPointSet.push_back(tempPoint);
            }
        }
        object_Points.push_back(tempPointSet);
    }

    /* 初始化每幅影象中的角點數,這裡我們假設每幅影象中都可以看到完整的定標板 */
    for (int i=0; i< image_count; i++)
    {
        point_counts.push_back(board_size.width*board_size.height);
    }

    /* 開始定標 */
    calibrateCamera(object_Points, corners_Seq, image_size,  intrinsic_matrix  ,distortion_coeffs, rotation_vectors, translation_vectors);
    std::cout<<"achievement calibaration\n";

    /************************************************************************
               對定標結果進行評價
        *************************************************************************/
    std::cout<<"開始評價定標結果………………"<<endl;
    double total_err = 0.0;                   /* 所有影象的平均誤差的總和 */
    double err = 0.0;                        /* 每幅影象的平均誤差 */
    vector<Point2f>  image_points2;             /****   儲存重新計算得到的投影點    ****/

    std::cout<<"每幅影象的定標誤差:"<<endl;
    fout<<"每幅影象的定標誤差:"<<endl<<endl;
    for (int i=0;  i<image_count;  i++)
    {
        vector<Point3f> tempPointSet = object_Points[i];
        /****    通過得到的攝像機內外引數,對空間的三維點進行重新投影計算,得到新的投影點     ****/
        projectPoints(tempPointSet, rotation_vectors[i], translation_vectors[i], intrinsic_matrix, distortion_coeffs, image_points2);
        /* 計算新的投影點和舊的投影點之間的誤差*/
        vector<Point2f> tempImagePoint = corners_Seq[i];
        Mat tempImagePointMat = Mat(1,tempImagePoint.size(),CV_32FC2);
        Mat image_points2Mat = Mat(1,image_points2.size(), CV_32FC2);
        for (int j = 0 ; j < tempImagePoint.size(); j++)
        {
            image_points2Mat.at<Vec2f>(0,j) = Vec2f(image_points2[j].x, image_points2[j].y);
            tempImagePointMat.at<Vec2f>(0,j) = Vec2f(tempImagePoint[j].x, tempImagePoint[j].y);
        }
        err = norm(image_points2Mat, tempImagePointMat, NORM_L2);
        total_err += err/=  point_counts[i];
        std::cout<<"第"<<i+1<<"幅影象的平均誤差:"<<err<<"畫素"<<endl;
        fout<<"第"<<i+1<<"幅影象的平均誤差:"<<err<<"畫素"<<endl;
    }
    std::cout<<"總體平均誤差:"<<total_err/image_count<<"畫素"<<endl;
    fout<<"總體平均誤差:"<<total_err/image_count<<"畫素"<<endl<<endl;
    std::cout<<"評價完成!"<<endl;

    /************************************************************************
               儲存定標結果
        *************************************************************************/
    std::cout<<"開始儲存定標結果………………"<<endl;
    Mat rotation_matrix = Mat(3,3,CV_32FC1, Scalar::all(0)); /* 儲存每幅影象的旋轉矩陣 */

    fout<<"相機內參數矩陣:"<<endl;
    fout<<intrinsic_matrix<<endl<<endl;
    fout<<"畸變係數:\n";
    fout<<distortion_coeffs<<endl<<endl<<endl;
    for (int i=0; i<image_count; i++)
    {
        fout<<"第"<<i+1<<"幅影象的旋轉向量:"<<endl;
        fout<<rotation_vectors[i]<<endl;

        /* 將旋轉向量轉換為相對應的旋轉矩陣 */
        Rodrigues(rotation_vectors[i],rotation_matrix);
        fout<<"第"<<i+1<<"幅影象的旋轉矩陣:"<<endl;
        fout<<rotation_matrix<<endl;
        fout<<"第"<<i+1<<"幅影象的平移向量:"<<endl;
        fout<<translation_vectors[i]<<endl<<endl;
    }
    std::cout<<"完成儲存"<<endl;
    fout<<endl;

    /************************************************************************
               顯示定標結果
        *************************************************************************/
    Mat mapx = Mat(image_size,CV_32FC1);
    Mat mapy = Mat(image_size,CV_32FC1);
    Mat R = Mat::eye(3,3,CV_32F);
    std::cout<<"儲存矯正影象"<<endl;
    string imageFileName;
    std::stringstream StrStm;
    for (int i = 0 ; i != image_count ; i++)
    {
        std::cout<<"Frame #"<<i+1<<"..."<<endl;
        Mat newCameraMatrix = Mat(3,3,CV_32FC1,Scalar::all(0));
        initUndistortRectifyMap(intrinsic_matrix,distortion_coeffs,R,intrinsic_matrix,image_size,CV_32FC1,mapx,mapy);
        StrStm.clear();
        imageFileName.clear();
        StrStm<<i+1;
        StrStm>>imageFileName;
        imageFileName += ".jpg";
        Mat t = imread(imageFileName);
        Mat newimage = t.clone();
        cv::remap(t,newimage,mapx, mapy, INTER_LINEAR);
        StrStm.clear();
        imageFileName.clear();
        StrStm<<i+1;
        StrStm>>imageFileName;
        imageFileName += "_d.jpg";
        imwrite(imageFileName,newimage);
    }
    std::cout<<"儲存結束"<<endl;

}

MainWindow::~MainWindow()
{

}

程式碼知識點詳解

相機標定步驟

  • 讀取多幅影象,從中提取出角點,然後對角點進行亞畫素精確化
    1)讀取影象可以採用已經存在的影象;或者採用外接的攝像頭進行讀取
    2)提取角點
    3)亞畫素精確化

  • 攝像機定標
    1)初始化定標板上角點的三維座標
    2)初始化每幅影象中的角點數
    3)開始定標—calibrateCamera

  • 對定標結果進行評價
    通過得到的攝像機內外引數,對空間的三維點進行重新投影計算,得到新的投影點
    計算新的投影點和舊的投影點之間的誤差

相關推薦

OpenCV相機標定及距離估計(單目)

相機標定基本知識 對於針孔攝像機模型,一幅檢視是通過透視變換將三維空間中的點投影到影象平面。投影公式如下: 或者 這裡(X, Y, Z)是一個點的世界座標,(u, v)是點投影在影象平面的座標,以畫素為單位。A被稱作攝像機矩陣,或者內參數矩陣。(cx, cy)是基

opencv相機標定的一些函式講解

畸變矯正是上一篇博文的遺留問題,當畸變係數和內外引數矩陣標定完成後,就應該進行畸變的矯正,以達到消除畸變的目的,此其一。 在該系列第一部分的博文中介紹的立體成像原理中提到,要通過兩幅影象估計物點的深度資訊,就必須在兩幅影象中準確的匹配到同一物點,這樣才能根據該物點在兩幅影象中的

opencv---相機標定

參考文章 座標系之間的關係 計算機視覺領域中常見的三個座標系:影象座標系,相機座標系,世界座標系 影象座標系—理想影象座標系和實際影象座標系 上圖中: 實際的影象座標系原點為 二者之間的關係式為(1)(2),(1)(2)也可以用矩陣(3)

opencv-相機標定步驟、評估標定誤差以及標定之後影象座標到世界座標的轉換

前一段時間,研究了下相機標定。關於opencv相機標定,包括標定完後,世界座標到 影象座標的轉換,以評估影象的標定誤差,這些網上有很多資源和原始碼。 可是,相機標定完之後,我們想要的是,知道了影象座標,想要得到它的世界座標,或者我們已知影象上兩個點之間的畫素距離,現在我們想

OpenCV——相機標定

1、四個座標系 世界座標系,相機座標系,影象物理座標系,畫素座標系 2、座標系之間的轉換 2.1、世界座標系——相機座標系 假設世界座標系中點座標為[x1,y1,z1],對應的相機座標系中的點座標為[x,y,z],世界座標系轉換至相機座標系遵循如下推

opencv 相機標定與矯正

由攝像機拍取並進行標定與矯正 步驟: 1.確定基礎設定 //設定1 影象的尺寸 const int nImageW = 2592; const int nImageH

雙目相機標定以及立體測距原理及OpenCV實現

ada eps 左右 flag 並且 length turn iostream 中一 作者:dcrmg 單目相機標定的目標是獲取相機的內參和外參,內參(1/dx,1/dy,Cx,Cy,f)表征了相機的內部結構參數,外參是相機的旋轉矩陣R和平移向量t。內參中dx和d

相機標定與矯正opencv+MATLAB

open space stream 修復 tin net src 標定 不錯 博客轉載自:http://blog.csdn.net/Loser__Wang/article/details/51811347 本文目的在於記錄如何使用MATLAB做攝像機標定,並通過opencv

opencv 單目相機標定 自帶例子程式的使用

<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/

魚眼相機標定以及OpenCV實現

https://blog.csdn.net/u010784534/article/details/50474371 在另一篇文章中我已經寫過有關普通相機模型及其OpenCV標定實現,這篇文章將主要關注魚眼相機模型及其OpenCV標定實現。  先看一張魚眼相機拍攝出來的結果:

【程式碼】python+opencv實現相機標定

詳細流程講解: opencv官方文件翻譯版: 1. 準備標定影象 相機標定是進行視覺測量和定位的基礎工作之一,標定引數準確與否直接關係到整個系統的精度,為此根據自己專案中的經驗及參考相關的商用視覺軟體的做法將相機標定過程中標定圖片的獲取過程中需要注意的問題總結

基於OPENCV相機標定及程式碼

2015年11月17上傳 以下是我實現的相機標定 C++ 類,建構函式如下: CCalibration::CCalibration(CvSize _board_sz, double _board_dt, int _n_boards) { //標定板的資訊 board

相機標定OpenCV&Matlab

Camera Calibration 1.OpenCV Camera Calibration OpenCV提供具體的標定策略和說明文件,可以直接使用,說明文件的位置"D:\opencv\sources\doc\tutorials\calib3d\camera_calibra

相機標定 matlab opencv ROS三種方法標定步驟(1)

 一 、 理解攝像機模型,網上有很多講解的十分詳細,在這裡我只是記錄我的整合出來的資料和我的部分理解         計算機視覺領域中常見的三個座標系:影象座標系,相機座標系,世界座標系,實際上就是要用矩陣來表         示各個座標系下的轉換,首先在影象座標系下與相機座標系的關係            

基於opencv相機標定

利用opencv中帶的相機標定camera_calibration.cpp檔案,整理後進行相機矯正。 在opencv中的目錄:/opencv-3.3.0/samples/cpp/tutorial_code/calib3d/camera_calibration

詳細介紹Opencv實現張正友法相機標定

一.本程式基於以下配置: - Visual Studio 2015 - OpenCV 3.1.0 開發環境配置參考:OpenCV3.1.0+VS2013開發環境配置 二.本程式準備工作: 本程式使用的標定板是10行14列棋盤格圖案,示

OpenCV——單目相機標定

步驟: 1、製作標定板 此處製作邊長2.5cm的棋盤圖,規格大小為8*8,生成程式碼如下所示 //程式設計環境:VS2013, X64,OpenCV3.0.0 #include <iostream> #include <opencv2\

opencv裡的norm範數和影象裡的深度和通道數的理解和意義和相機標定後對內外引數的質量評估

CV_8UC1 是指一個8位無符號整型單通道矩陣, CV_32FC2是指一個32位浮點型雙通道矩陣 CV_8UC1 CV_8SC1 CV_16U C1 CV_16SC1 CV_8UC2 CV_

Halcon學習筆記——機器視覺應用工程開發思路及相機標定

助手 創建模板 建模 visio open 這一 目的 傅裏葉變換 綁定 機器視覺應用工程開發思路 機器視覺應用工程主要可劃分為兩大部分,硬件部分和軟件部分。 1.硬件部分,硬件的選型至關重要,決定了後續工作是否可以正常開展,其中關鍵硬件部

相機標定過程

機器視覺1. 攝像機標定的數學過程如下: 這裏程序的實現是在opencv中,所以就用opencv的程序來說明具體的過程.註意各個版本的opencv之間的程序移植性並不好,以下程序是在opencv2.4.3下編制運行的,註意1.程序運行前需要插上攝像頭,否則程序有可能不能正常運行2.獲取棋盤格圖像張正友論文中建