關於雙目立體視覺的一些總結(二)
上一篇只是對於雙目立體視覺做了一個簡單的介紹,這裡就我在做這個的時候碰到的一些問題做一個梳理。1.首先要糾正一下之前一個錯誤:cvRemap函式只接受灰度圖。其實這個函式要求src與dst大小格式通道必須一致就行,並不需要一定為灰度資料。當時下這個結論主要是因為被OpenCV的影象矩陣資料格式搞得很暈,為了先出個結果。後來有了要輸出三通道資料的需要,倒是研究了一下OpenCV影象的資料格式。 矩陣元素型別包括了兩部分資訊,首先是元素資料的型別,還有就是該元素包含的通道個數。/*Mat_<uchar>對應的是CV_8U,Mat_<uchar>對應的是CV_8U,Mat_<char>對應的是CV_8S,Mat_<int>對應的是CV_32S,Mat_<float>對應的是CV_32F,Mat_<double>對應的是CV_64F*/#define CV_8U 0#define CV_8S 1 #define CV_16U 2#define CV_16S 3#define CV_32S 4#define CV_32F 5#define CV_64F 6123456789灰度圖就用CV_8U,三通道圖就用CV_8UC3,像我得出的視差圖資料就用CV_16S來儲存,三維座標資訊的資料就用CV_32FC3的型別,總之按需求定。2.通過雙目獲取物體的三維資訊之後,我的目標是把這個三維資訊投影到地面平面上進行分析,所以需要建立空間座標系與地面平面座標系之間的轉化關係。 由於我只需要一個投影面,並不需要關注這個面是不是就是地面,只需要與地面平行即可,所以並不需要事先測定地面,這樣的話建立轉化就簡單了很多。從左片中取一些地面上的畫素點,計算出它們在空間座標系中的三維座標,用最小二乘擬合出這些點所在的平面Ax+By+Cz = D;空間座標系是以左相機光心為原點,視軸為Z軸,基線為X軸(方向指向右相機)的右手系。由於我只要求一個投影平面,座標系可以任意,不妨取上述擬合平面Ax+By+Cz = D與Z軸的交點為地面平面座標系的原點o,與X軸的交點作為x軸正半軸上的點,由此可建立一個地面投影面的座標系。幾個座標點:o(0,0,D);x(DADA,0,0);Y(-DA,D+DA2BD+DA2B,0)。可得到幾個座標向量:ox = (DADA,0,-D);oy = (-DA,D+DA2BD+DA2B,-D);oz = (A,B,C);假設空間中有一個點S(Xs,Ys,Zs);向量oS = (Xs,Ys,Zs - D);現在要求S在xoy平面上的投影,記作p。oS在oz上的投影為h = os⋅oz|oz|⋅ozos·oz|oz|·oz;所以op = oS - h,得到op之後求它在ox和oy上的投影即可得到投影面上的二維座標。這樣三維資訊就投影到了地面上,可以進行分析了。3.我需要把相機拍攝的運動物體(行人)提取出來,目前用的最多的有兩種方法: (1)基於背景建模: 利用背景建模方法,提取出前景運動的目標,在目標區域內進行特徵提取,然後利用分類器進行分類,判斷是否包含行人;(2)基於統計學習的方法: 目前行人檢測最常用的方法,根據大量的樣本構建行人檢測分類器。提取的特徵主要有目標的灰度、邊緣、紋理、顏色、梯度直方圖等資訊。由於當前時間較緊,現階段只有背景建模提取前景的方法,後續會嘗試將兩者結合使用。 我用的是最簡單的方法,即幀差法,有兩種普遍的方法,一種是前後幀相減,一種是三幀法,簡要程式碼如下:/*前後幀相減*/VideoCapture video("../camera.avi");Mat img1, img2, gray1, gray2, grayDiff;int diff_threshold = 20; //幀差閾值while(1){ video.read(img1); objectDetector(img1); cvtColor(img1,gray1,CV_BGR2GRAY); video.read(img2); cvtColor(img2,gray2,CV_BGR2GRAY); subtract(gray1,gray2,grayDiff); for(int i = 0; i < grayDiff.rows; ++i) { for(int j = 0; j < grayDiff.cols; ++j) { if( abs(grayDiff.at<uchar>(i,j)) >= diff_threshold ) { grayDiff.at<uchar>(i,j) = 255; } else { grayDiff.at<uchar>(i,j) = 0; } } } imshow("background",gray1); imshow("zhencha",grayDiff); char c = cvWaitKey(33); if(c == 27) break;}123456789101112131415161718192021222324252627282930313233343536/*三幀法*/VideoCapture video("../camera.avi");Mat img1, img2, gray1, gray2;Mat img3, gray3, grayDiff1, grayDiff2;int diff_threshold = 20; //幀差閾值while(1){ video.read(img1); video.read(img2); video.read(img3); cvtColor(img1,gray1,CV_BGR2GRAY); cvtColor(img2,gray2,CV_BGR2GRAY); cvtColor(img3,gray3,CV_BGR2GRAY); subtract(gray1,gray2,grayDiff1); subtract(gray2,gray3,grayDiff2); for(int i = 0; i < grayDiff1.rows; ++i) { for(int j = 0; j < grayDiff2.cols; ++j) { if( abs(grayDiff1.at<uchar>(i,j)) >= diff_threshold ) { grayDiff1.at<uchar>(i,j) = 255; } else { grayDiff1.at<uchar>(i,j) = 0; } if( abs(grayDiff2.at<uchar>(i,j)) >= diff_threshold ) { grayDiff2.at<uchar>(i,j) = 255; } else { grayDiff2.at<uchar>(i,j) = 0; } } } bitwise_and(grayDiff1,grayDiff2,grayDiff);//和運算 imshow("background",img2); imshow("zhencha",grayDiff); char c = cvWaitKey(33); if(c == 27) break;}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748得到前景之後就可以利用之前建立的座標系轉換得到人在地面上的投影,即我需要使用的深度資訊。 --------------------- 作者:Array03 來源:CSDN 原文:https://blog.csdn.net/u014629875/article/details/51340144