国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

相機的畸變矯正與opencv代碼說明

這篇具有很好參考價值的文章主要介紹了相機的畸變矯正與opencv代碼說明。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

簡介

圖像算法中會經(jīng)常用到攝像機的畸變校正,有必要總結(jié)分析OpenCV中畸變校正方法,其中包括普通針孔相機模型和魚眼相機模型fisheye兩種畸變校正方法。普通相機模型畸變校正函數(shù)針對OpenCV中的cv::initUndistortRectifyMap(),魚眼相機模型畸變校正函數(shù)對應(yīng)OpenCV中的cv::fisheye::initUndistortRectifyMap()。兩種方法算出映射Mapx和Mapy后,統(tǒng)一用cv::Remap()函數(shù)進行插值得到校正后的圖像。

魚眼模型的畸變校正

魚眼鏡頭生產(chǎn)過程中不可能精確地按照投影模型來設(shè)計,所以為了方便魚眼相機的標(biāo)定,Kannala-Brandt提出了一種魚眼相機的一般多項式近似模型。取前5項,給出了足夠的自由度來很好的近似各種投影模型。
opencv 相機校正,opencv,計算機視覺

簡要流程就是:

  • 1.求內(nèi)參矩陣的逆,由于攝像機坐標(biāo)系的三維點到二維圖像平面,需要乘以旋轉(zhuǎn)矩陣R和內(nèi)參矩陣K。那么反向投影回去則是二維圖像坐標(biāo)乘以 K*R的逆矩陣。

  • 2.將目標(biāo)圖像中的每一個像素點坐標(biāo)(j,i),乘以1中求出的逆矩陣iR,轉(zhuǎn)換到攝像機坐標(biāo)系(_x,_y,_w),并歸一化得到z=1平面下的三維坐標(biāo)(x,y,1)。

  • 3.求出平面模型下像素點對應(yīng)魚眼半球模型下的極坐標(biāo)(r, theta)。

  • 4.利用魚眼畸變模型求出擁有畸變時像素點對應(yīng)的theta_d。

  • 5.利用求出的theta_d值將三維坐標(biāo)點重投影到二維圖像平面得到(u,v),(u,v)即為目標(biāo)圖像對應(yīng)的畸變圖像中像素點坐標(biāo)。

  • 6.使用cv::Remap()函數(shù),根據(jù)mapx,mapy取出對應(yīng)坐標(biāo)位置的像素值賦值給目標(biāo)圖像,一般采用雙線性插值法,得到畸變校正后的目標(biāo)圖像。

#include <opencv2\opencv.hpp>

void cv::fisheye::initUndistortRectifyMap( InputArray K, InputArray D, InputArray R, InputArray P,
    const cv::Size& size, int m1type, OutputArray map1, OutputArray map2 )
{
    CV_Assert( m1type == CV_16SC2 || m1type == CV_32F || m1type <=0 );
    map1.create( size, m1type <= 0 ? CV_16SC2 : m1type );
    map2.create( size, map1.type() == CV_16SC2 ? CV_16UC1 : CV_32F );

    CV_Assert((K.depth() == CV_32F || K.depth() == CV_64F) && (D.depth() == CV_32F || D.depth() == CV_64F));
    CV_Assert((P.empty() || P.depth() == CV_32F || P.depth() == CV_64F) && (R.empty() || R.depth() == CV_32F || R.depth() == CV_64F));
    CV_Assert(K.size() == Size(3, 3) && (D.empty() || D.total() == 4));
    CV_Assert(R.empty() || R.size() == Size(3, 3) || R.total() * R.channels() == 3);
    CV_Assert(P.empty() || P.size() == Size(3, 3) || P.size() == Size(4, 3));

    //從內(nèi)參矩陣K中取出歸一化焦距fx,fy; cx,cy
    cv::Vec2d f, c;
    if (K.depth() == CV_32F)
    {
        Matx33f camMat = K.getMat();
        f = Vec2f(camMat(0, 0), camMat(1, 1));
        c = Vec2f(camMat(0, 2), camMat(1, 2));
    }
    else
    {
        Matx33d camMat = K.getMat();
        f = Vec2d(camMat(0, 0), camMat(1, 1));
        c = Vec2d(camMat(0, 2), camMat(1, 2));
    }
    //從畸變系數(shù)矩陣D中取出畸變系數(shù)k1,k2,k3,k4
    Vec4d k = Vec4d::all(0);
    if (!D.empty())
        k = D.depth() == CV_32F ? (Vec4d)*D.getMat().ptr<Vec4f>(): *D.getMat().ptr<Vec4d>();

    //旋轉(zhuǎn)矩陣RR轉(zhuǎn)換數(shù)據(jù)類型為CV_64F,如果不需要旋轉(zhuǎn),則RR為單位陣
    cv::Matx33d RR  = cv::Matx33d::eye();
    if (!R.empty() && R.total() * R.channels() == 3)
    {
        cv::Vec3d rvec;
        R.getMat().convertTo(rvec, CV_64F);
        RR = Affine3d(rvec).rotation();
    }
    else if (!R.empty() && R.size() == Size(3, 3))
        R.getMat().convertTo(RR, CV_64F);
    
    //新的內(nèi)參矩陣PP轉(zhuǎn)換數(shù)據(jù)類型為CV_64F
    cv::Matx33d PP = cv::Matx33d::eye();
    if (!P.empty())
        P.getMat().colRange(0, 3).convertTo(PP, CV_64F);

    //關(guān)鍵一步:新的內(nèi)參矩陣*旋轉(zhuǎn)矩陣,然后利用SVD分解求出逆矩陣iR,后面用到
    cv::Matx33d iR = (PP * RR).inv(cv::DECOMP_SVD);

    //反向映射,遍歷目標(biāo)圖像所有像素位置,找到畸變圖像中對應(yīng)位置坐標(biāo)(u,v),并分別保存坐標(biāo)(u,v)到mapx和mapy中
    for( int i = 0; i < size.height; ++i)
    {
        float* m1f = map1.getMat().ptr<float>(i);
        float* m2f = map2.getMat().ptr<float>(i);
        short*  m1 = (short*)m1f;
        ushort* m2 = (ushort*)m2f;

        //二維圖像平面坐標(biāo)系->攝像機坐標(biāo)系
        double _x = i*iR(0, 1) + iR(0, 2),
               _y = i*iR(1, 1) + iR(1, 2),
               _w = i*iR(2, 1) + iR(2, 2);

        for( int j = 0; j < size.width; ++j)
        {
            //歸一化攝像機坐標(biāo)系,相當(dāng)于假定在Z=1平面上
            double x = _x/_w, y = _y/_w;

            //求魚眼半球體截面半徑r
            double r = sqrt(x*x + y*y);
            //求魚眼半球面上一點與光心的連線和光軸的夾角Theta
            double theta = atan(r);
            //畸變模型求出theta_d,相當(dāng)于有畸變的角度值
            double theta2 = theta*theta, theta4 = theta2*theta2, theta6 = theta4*theta2, theta8 = theta4*theta4;
            double theta_d = theta * (1 + k[0]*theta2 + k[1]*theta4 + k[2]*theta6 + k[3]*theta8);
            //利用有畸變的Theta值,將攝像機坐標(biāo)系下的歸一化三維坐標(biāo),重投影到二維圖像平面,得到(j,i)對應(yīng)畸變圖像中的(u,v)
            double scale = (r == 0) ? 1.0 : theta_d / r;
            double u = f[0]*x*scale + c[0];
            double v = f[1]*y*scale + c[1];

            //保存(u,v)坐標(biāo)到mapx,mapy
            if( m1type == CV_16SC2 )
            {
                int iu = cv::saturate_cast<int>(u*cv::INTER_TAB_SIZE);
                int iv = cv::saturate_cast<int>(v*cv::INTER_TAB_SIZE);
                m1[j*2+0] = (short)(iu >> cv::INTER_BITS);
                m1[j*2+1] = (short)(iv >> cv::INTER_BITS);
                m2[j] = (ushort)((iv & (cv::INTER_TAB_SIZE-1))*cv::INTER_TAB_SIZE + (iu & (cv::INTER_TAB_SIZE-1)));
            }
            else if( m1type == CV_32FC1 )
            {
                m1f[j] = (float)u;
                m2f[j] = (float)v;
            }

            //這三條語句是上面 ”//二維圖像平面坐標(biāo)系->攝像機坐標(biāo)系“的一部分,是矩陣iR的第一列,這樣寫能夠簡化計算
            _x += iR(0, 0);
            _y += iR(1, 0);
            _w += iR(2, 0);
        }
    }
}

針孔模型的畸變校正

主要流程和上面Fisheye模型差不多,只有第4部分的畸變模型不一樣,普通相機的畸變模型如下,k1,k2,k3為徑向畸變,p1,p2為切向畸變:
opencv 相機校正,opencv,計算機視覺
其中 r 2 = x 2 + y 2 r^2=x^2 + y^2 r2=x2+y2
將畸變后的點通過內(nèi)參數(shù)矩陣投影到像素平面,得到該點在圖像上的正確位置
opencv 相機校正,opencv,計算機視覺文章來源地址http://www.zghlxwxcb.cn/news/detail-629224.html

#include <opencv2\opencv.hpp>

void cv::initUndistortRectifyMap( InputArray _cameraMatrix, InputArray _distCoeffs,
                              InputArray _matR, InputArray _newCameraMatrix,
                              Size size, int m1type, OutputArray _map1, OutputArray _map2 )
{
    Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat();
    Mat matR = _matR.getMat(), newCameraMatrix = _newCameraMatrix.getMat();

    if( m1type <= 0 )
        m1type = CV_16SC2;
    CV_Assert( m1type == CV_16SC2 || m1type == CV_32FC1 || m1type == CV_32FC2 );
    _map1.create( size, m1type );
    Mat map1 = _map1.getMat(), map2;
    if( m1type != CV_32FC2 )
    {
        _map2.create( size, m1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 );
        map2 = _map2.getMat();
    }
    else
        _map2.release();

    Mat_<double> R = Mat_<double>::eye(3, 3);
    Mat_<double> A = Mat_<double>(cameraMatrix), Ar;

    if( !newCameraMatrix.empty() )
        Ar = Mat_<double>(newCameraMatrix);
    else
        Ar = getDefaultNewCameraMatrix( A, size, true );

    if( !matR.empty() )
        R = Mat_<double>(matR);

    if( !distCoeffs.empty() )
        distCoeffs = Mat_<double>(distCoeffs);
    else
    {
        distCoeffs.create(14, 1, CV_64F);
        distCoeffs = 0.;
    }

    CV_Assert( A.size() == Size(3,3) && A.size() == R.size() );
    CV_Assert( Ar.size() == Size(3,3) || Ar.size() == Size(4, 3));

    //LU分解求新的內(nèi)參矩陣Ar與旋轉(zhuǎn)矩陣R乘積的逆矩陣iR
    Mat_<double> iR = (Ar.colRange(0,3)*R).inv(DECOMP_LU);
    const double* ir = &iR(0,0);

    //從舊的內(nèi)參矩陣中取出光心位置u0,v0,和歸一化焦距fx,fy
    double u0 = A(0, 2),  v0 = A(1, 2);
    double fx = A(0, 0),  fy = A(1, 1);

    //尼瑪14個畸變系數(shù),不過大多用到的只有(k1,k2,p1,p2),最多加一個k3,用不到的置為0
    CV_Assert( distCoeffs.size() == Size(1, 4) || distCoeffs.size() == Size(4, 1) ||
               distCoeffs.size() == Size(1, 5) || distCoeffs.size() == Size(5, 1) ||
               distCoeffs.size() == Size(1, 8) || distCoeffs.size() == Size(8, 1) ||
               distCoeffs.size() == Size(1, 12) || distCoeffs.size() == Size(12, 1) ||
               distCoeffs.size() == Size(1, 14) || distCoeffs.size() == Size(14, 1));

    if( distCoeffs.rows != 1 && !distCoeffs.isContinuous() )
        distCoeffs = distCoeffs.t();

    const double* const distPtr = distCoeffs.ptr<double>();
    double k1 = distPtr[0];
    double k2 = distPtr[1];
    double p1 = distPtr[2];
    double p2 = distPtr[3];
    double k3 = distCoeffs.cols + distCoeffs.rows - 1 >= 5 ? distPtr[4] : 0.;
    double k4 = distCoeffs.cols + distCoeffs.rows - 1 >= 8 ? distPtr[5] : 0.;
    double k5 = distCoeffs.cols + distCoeffs.rows - 1 >= 8 ? distPtr[6] : 0.;
    double k6 = distCoeffs.cols + distCoeffs.rows - 1 >= 8 ? distPtr[7] : 0.;
    double s1 = distCoeffs.cols + distCoeffs.rows - 1 >= 12 ? distPtr[8] : 0.;
    double s2 = distCoeffs.cols + distCoeffs.rows - 1 >= 12 ? distPtr[9] : 0.;
    double s3 = distCoeffs.cols + distCoeffs.rows - 1 >= 12 ? distPtr[10] : 0.;
    double s4 = distCoeffs.cols + distCoeffs.rows - 1 >= 12 ? distPtr[11] : 0.;
    double tauX = distCoeffs.cols + distCoeffs.rows - 1 >= 14 ? distPtr[12] : 0.;
    double tauY = distCoeffs.cols + distCoeffs.rows - 1 >= 14 ? distPtr[13] : 0.;

    //tauX,tauY這個是什么梯形畸變,用不到的話matTilt為單位陣
    // Matrix for trapezoidal distortion of tilted image sensor
    cv::Matx33d matTilt = cv::Matx33d::eye();
    cv::detail::computeTiltProjectionMatrix(tauX, tauY, &matTilt);

    for( int i = 0; i < size.height; i++ )
    {
        float* m1f = map1.ptr<float>(i);
        float* m2f = map2.empty() ? 0 : map2.ptr<float>(i);
        short* m1 = (short*)m1f;
        ushort* m2 = (ushort*)m2f;

        //利用逆矩陣iR將二維圖像坐標(biāo)(j,i)轉(zhuǎn)換到攝像機坐標(biāo)系(_x,_y,_w)
        double _x = i*ir[1] + ir[2], _y = i*ir[4] + ir[5], _w = i*ir[7] + ir[8];

        for( int j = 0; j < size.width; j++, _x += ir[0], _y += ir[3], _w += ir[6] )
        {
            //攝像機坐標(biāo)系歸一化,令Z=1平面
            double w = 1./_w, x = _x*w, y = _y*w;
             //這一部分請看OpenCV官方文檔,畸變模型部分
            double x2 = x*x, y2 = y*y;
            double r2 = x2 + y2, _2xy = 2*x*y;
            double kr = (1 + ((k3*r2 + k2)*r2 + k1)*r2)/(1 + ((k6*r2 + k5)*r2 + k4)*r2);
            double xd = (x*kr + p1*_2xy + p2*(r2 + 2*x2) + s1*r2+s2*r2*r2);
            double yd = (y*kr + p1*(r2 + 2*y2) + p2*_2xy + s3*r2+s4*r2*r2);
           //根據(jù)求取的xd,yd將三維坐標(biāo)重投影到二維畸變圖像坐標(biāo)(u,v)
            cv::Vec3d vecTilt = matTilt*cv::Vec3d(xd, yd, 1);
            double invProj = vecTilt(2) ? 1./vecTilt(2) : 1;
            double u = fx*invProj*vecTilt(0) + u0;
            double v = fy*invProj*vecTilt(1) + v0;
            //保存u,v的值到Mapx,Mapy中
            if( m1type == CV_16SC2 )
            {
                int iu = saturate_cast<int>(u*INTER_TAB_SIZE);
                int iv = saturate_cast<int>(v*INTER_TAB_SIZE);
                m1[j*2] = (short)(iu >> INTER_BITS);
                m1[j*2+1] = (short)(iv >> INTER_BITS);
                m2[j] = (ushort)((iv & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE + (iu & (INTER_TAB_SIZE-1)));
            }
            else if( m1type == CV_32FC1 )
            {
                m1f[j] = (float)u;
                m2f[j] = (float)v;
            }
            else
            {
                m1f[j*2] = (float)u;
                m1f[j*2+1] = (float)v;
            }
        }
    }
}

到了這里,關(guān)于相機的畸變矯正與opencv代碼說明的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • opencv對相機進行畸變矯正,及從矯正后的圖像坐標(biāo)反求原來的對應(yīng)坐標(biāo)

    opencv對相機進行畸變矯正,及從矯正后的圖像坐標(biāo)反求原來的對應(yīng)坐標(biāo)

    目前有個項目,需要用到熱成像相機。但是這個熱成像相機它的畸變比較厲害,因此需要用標(biāo)定板進行標(biāo)定,從而消除鏡頭畸變。 同時需要實現(xiàn)用戶用鼠標(biāo)點擊校正后的畫面后,顯示用戶點擊位置的像素所代表的溫度。 另外熱成像sdk中還有個功能:選定一個rect,可以返回這

    2024年02月16日
    瀏覽(32)
  • 相機的內(nèi)外參數(shù)標(biāo)定和畸變矯正原理和代碼

    相機的內(nèi)外參數(shù)標(biāo)定和畸變矯正原理和代碼

    相機的成像過程實質(zhì)上是坐標(biāo)系轉(zhuǎn)換。首先空間中的點坐標(biāo)由世界坐標(biāo)系轉(zhuǎn)換到相機坐標(biāo)系,然后將其投影到成像平面(圖像物理坐標(biāo)系),最后再將成像平面上的數(shù)據(jù)轉(zhuǎn)換到圖像像素坐標(biāo)系。但是由于透鏡制造精度及組裝工藝的差別會引入畸變,導(dǎo)致原始圖像的失真。鏡頭

    2024年04月16日
    瀏覽(23)
  • 計算機視覺(相機標(biāo)定;內(nèi)參;外參;畸變系數(shù))

    計算機視覺(相機標(biāo)定;內(nèi)參;外參;畸變系數(shù))

    目錄 一、預(yù)備知識 1、坐標(biāo)系變換過程(相機成像過程) (1)相機坐標(biāo)系轉(zhuǎn)換為圖像坐標(biāo)系(透視投影變換遵循的是針孔成像原理) (2)齊次坐標(biāo)的引入原因:(為什么引入齊次坐標(biāo)???) 2、內(nèi)參與外參矩陣的構(gòu)成 3、畸變參數(shù) 二、相機標(biāo)定 1、張正友標(biāo)定法(光學(xué)標(biāo)

    2024年02月07日
    瀏覽(23)
  • 無人機紅外相機的畸變矯正

    無人機紅外相機的畸變矯正

    在項目開展過程中,發(fā)現(xiàn)大疆M30T的紅外相機存在比較明顯的畸變問題,因此需要對紅外圖像進行畸變矯正。在資料檢索過程中,發(fā)現(xiàn)對紅外無人機影像矯正的資料較少,對此,我從相機的成像原理角度出發(fā),探索出一種效果尚可的解決思路,遂以本文記錄如下。 目前采用的

    2024年02月04日
    瀏覽(16)
  • opencv圖像畸變矯正:源碼學(xué)習(xí)

    opencv圖像畸變矯正:源碼學(xué)習(xí)

    參考資料:相機標(biāo)定(4) 矯正畸變 undistort()和initUndistortRectifyMap() 背景: opencv提供了直接進行畸變矯正的代碼,因在項目中需要使用畸變矯正,因此研究一下opencv中畸變矯正的相關(guān)接口與代碼,便于學(xué)習(xí)提升與二次開發(fā)。 opencv在文檔中對相機標(biāo)定與畸變矯正的原理做了簡單

    2024年02月10日
    瀏覽(42)
  • 【相機標(biāo)定】opencv python 標(biāo)定相機內(nèi)參時不計算 k3 畸變參數(shù)

    畸變參數(shù) k3 通常用于描述徑向畸變的更高階效應(yīng),即在需要高精度的應(yīng)用中可以用到,一般的應(yīng)用中 k1, k2 足矣。 常見的應(yīng)用中, orbslam3 中是否傳入 k3 是可選的,而 kalibr 標(biāo)定中則只需要傳入 k1, k2 。但計算 k3 時的 k1, k2 不等于不計算 k3 時的 k1, k2 ,因此需要學(xué)會兩種場景下

    2024年02月09日
    瀏覽(32)
  • python opencv多路視頻畸變矯正與顯示

    python opencv多路視頻畸變矯正與顯示

    用于測試的計算機配置如下: 計算機為八核Intel(R) Xeon(R) CPU E3-1230 V2 @ 3.30GHz 注意:文中所說的cpu使用率是指該算法占用的cpu使用率 測試用的視頻規(guī)格為1920*1080 做一路視頻的去除畸變 cpu的使用率為126.9% 多路視頻去除畸變顯示 三路視頻去除畸變顯示代碼如下: import cv2 import numpy

    2023年04月09日
    瀏覽(24)
  • 傾斜矯正:用Python和OpenCV實現(xiàn)圖像傾斜校正

    圖像傾斜是在圖像獲取或掃描過程中常見的問題,它可能會導(dǎo)致圖像失真、文字難以識別或其他應(yīng)用中的問題。在本文中,我們將使用Python編程語言和OpenCV庫來實現(xiàn)圖像傾斜校正。 首先,我們需要安裝OpenCV庫。可以使用以下命令在Python環(huán)境中安裝它: 安裝完成后,我們可以

    2024年02月03日
    瀏覽(22)
  • OpenCvSharp (C# OpenCV) 二維碼畸變矯正--基于透視變換(附源碼)

    ? ? 本文主要介紹如何使用OpenCvSharp中的透視變換來實現(xiàn)二維碼的畸變矯正。 ? ? 由于CSDN文章中貼二維碼會導(dǎo)致顯示失敗,大家可以直接點下面鏈接查看圖片: ? ??C# OpenCV實現(xiàn)二維碼畸變矯正--基于透視變換 (詳細(xì)步驟 + 代碼) ? ? ?講解實現(xiàn)步驟之前先看下效果(左邊是原圖

    2024年02月15日
    瀏覽(31)
  • python利用opencv進行相機標(biāo)定獲取參數(shù),并根據(jù)畸變參數(shù)修正圖像附有全部代碼(流暢無痛版)

    python利用opencv進行相機標(biāo)定獲取參數(shù),并根據(jù)畸變參數(shù)修正圖像附有全部代碼(流暢無痛版)

    今天的低價單孔攝像機(照相機)會給圖像帶來很多畸變?;冎饕袃?種:徑向畸變和切想畸變。如下圖所示,用紅色直線將棋盤的兩個邊標(biāo)注出來, 但是你會發(fā)現(xiàn)棋盤的邊界并不和紅線重合。所有我們認(rèn)為應(yīng)該是直線的也都凸 出來了。 在 3D 相關(guān)應(yīng)用中,必須要先校正這些畸變

    2024年02月06日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包