1. 程式人生 > >立體匹配之動態規劃DP

立體匹配之動態規劃DP

動態規劃通常應用於最優化問題的求解中,Baker、Ohta 等將動態規劃引入立體匹配中來獲取視差圖。動態規劃匹配的過程可以分為兩個階段,建立視差空間和動態規劃優化,將立體匹配問題轉化為視差空間內尋找最優路徑的問題。

       密集匹配通常會充分利用影像間的核線約束條件,對立體像對進行核線糾正,這樣同名像點肯定位於對應的同名核線上,降低了匹配的難度。視差空間影像DSI(Disparity Space Image)是一種反映核線立體像對間同一掃描線視差關係的資料結構,將視差分析轉化為一種類似的譜分析。其數學表達為:

其中w 為影象的寬度, NaN 表示在該視差值為d 時不可能有對應的同名點,L((* ))  是對應點之間的相似性測度函式。在匹配核線影像時,逐行計算畫素的DSI,將每一行的DSI 依次疊加起來構成一個三維空間,稱之為視差空間,視差空間包含了每個畫素所有可能的視差取值。如下圖所示,圖中的x、y 代表影象的橫縱座標,d 表示視差搜尋範圍。

在建立好視差空間後,立體匹配問題就會轉化為在視差空間內尋找最佳路徑的問題,該路徑上的視差累積的能量最小,相似性最大。一般採用從影象左邊到右邊的順序,逐行進行。

實現過程如下:

//////minDeta、maxDeta為最小、大視差,P1、P2為平滑懲罰項
void Dynamic(Mat lImg,Mat rImg,int minDeta,int maxDeta,int P1,int P2)
{
    if (lImg.empty() || rImg.empty() || (lImg.type() != CV_8UC3&&lImg.type() != CV_8UC1) || (rImg.type() != CV_8UC3&&rImg.type() != CV_8UC1)) return;
    Mat lGrayImg = lImg.type == CV_8UC3 ? cvtColor(lImg, lGrayImg, COLOR_BGR2GRAY) : lImg;
    Mat rGrayImg = rImg.type == CV_8UC3 ? cvtColor(rImg, rGrayImg, COLOR_BGR2GRAY) : rImg;
    
    int detaRang=maxDeta-minDeta+1;///視差範圍
    Mat dispMap(lGrayImg.size(),CV_8UC1,Scalar::all(0));//////左視差圖
    for(int r=0;r<lGrayImg.rows;r++)
    {
        printf("動態規劃...%d%%\r",(int)(r*100.0/(lGrayImg.rows)));/////方便檢視進度
        Mat dif(Size(detaRang, lGrayImg.cols),CV_32FC1,Scalar::all(0));////視差空間
        Mat Emat(Size(detaRang, lGrayImg.cols),CV_32FC1,Scalar::all(0));/////能量空間
        Mat Dmat(Size(detaRang, lGrayImg.cols),CV_8UC1,Scalar::all(0));/////路徑走向
        for(int c=0;c<lGrayImg.cols;c++)
        {
            for(int d=0;d<detaRang;d++)
            {
                int rc=c-d-minDeta;///當前視差下左畫素對應對的右畫素座標
                if(rc>=0)
                {
                    dif.ptr<float>(c)[d] = SAD(lGrayImg, rGrayImg,Point2i(c, r),Point2i(c - d, r), 0);//////AD匹配代價
                }
                else
                {
                    dif.ptr<float>(c)[d]=c<minDeta?0:dif.ptr<float>(c)[d-1];/////防止邊界超限處代價對整體路徑的影響
                }
            }
        }
        for(int c=1;c<lGrayImg.cols;c++)
        {
            for(int match=0;match<detaRang;match++)
            {
                float tmpmin=FLT_MAX;//////當前狀態下路徑代價
                int pmin=NULL;////路徑走向
                for(int pre=0;pre<=detaRang;pre++)
                {
                    int Edata=dif.ptr<float>(c)[match];////資料項
                    int dd=abs(match-pre);
                    float Esmooth=dd>1?P2:(dd==0?0:P1);////視差等於1與大於1時候的平滑懲罰不同
                    float E=Edata+Esmooth+Emat.ptr<float>(c-1)[pre];/////路徑能量值
                    if (E<tmpmin)
                    {
                        tmpmin=E;
                        pmin=pre;
                    }
                }
                Emat.ptr<float>(c)[match]=tmpmin;
                Dmat.ptr<uchar>(c)[match]=pmin;
            }
        }
        int minID=0;
        float min=Emat.ptr<float>(lGrayImg.cols-1)[0];
        for(int i=0;i<detaRang;++i)
        {
            if(Emat.ptr<float>(lGrayImg.cols-1)[i]<min)
            {
                minID =i;
                min=Emat.ptr<float>(lGrayImg.cols-1)[i];
            }
        }
        //取得視差
        for(int c= lGrayImg.cols-1;c>=0;--c)
        {
            int d=Dmat.ptr<uchar>(c)[minID];
            minID =d;
            dispMap.ptr<uchar>(r)[c]=d+minDeta;/////
        }
    }    

}

轉:https://blog.csdn.net/u014493244/article/details/72780696