To Log Everything I find useful. If you find anything inappropriate, please contact cuijinqiang@gmail.com
Wednesday, February 6, 2013
立体视觉算法--SAD+DP
http://blog.csdn.net/renshengrumenglibing/article/details/8544057
#include <cstdio>
#include <cstring>
#include <iostream>
#include<cv.h>
#include<highgui.h>
#include <cmath>
using namespace std;
const int Width = 512;
const int Height = 512;
int Ddynamic[Width][Width];
int main()
{
//打开文件
FILE* pFile;
if (pFile = fopen("data.txt","a"))
{
//cout <<"File Open Success"<<endl;
}else{
//cout <<"File Open Failed"<<end;
return 0;
}
// IplImage * leftImage = cvLoadImage("l1.png",0);
// IplImage * rightImage = cvLoadImage("r1.png",0);
//IplImage * leftImage = cvLoadImage("l2.jpg",0);
//IplImage * rightImage = cvLoadImage("r2.jpg",0);
IplImage * leftImage = cvLoadImage("left.bmp",0);
IplImage * rightImage = cvLoadImage("right.bmp",0);
int imageWidth = leftImage->width;
int imageHeight =leftImage->height;
IplImage * leftDepth = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * rightDepth = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * leftValid = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * rightValid = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * leftFilter = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * rightFilter = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * depth = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
IplImage * valid = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
unsigned char * pPixel = NULL;
unsigned char pixel;
unsigned char * pPixel2 = NULL;
unsigned char pixel2;
cvZero(leftDepth);
cvZero(rightDepth);
cvZero(leftValid);
cvZero(rightValid);
cvZero(leftFilter);
cvZero(rightFilter);
cvZero(depth);
cvZero(valid);
CvSize SADWindowSize = cvSize(5,5); //(widh,height)
int SW2 = SADWindowSize.width/2;
int SH2 = SADWindowSize.height/2;
cout<<"SH2: "<<SH2<<endl;
cout<<"SW2: "<<SW2<<endl;
int minD = 0;
int maxD = 15;
//假设图像是经过矫正的,那么每次都只是需要搜搜同一行的内容
int max12Diff = 8*SADWindowSize.width*SADWindowSize.height;
for (int i = 0;i < imageWidth;i++)
{
Ddynamic[0][i] = 0;
Ddynamic[i][0] = 0;
}
unsigned char * pLeftPixel = NULL;
unsigned char * pRightPixel = NULL;
unsigned char leftPixel = 0;
unsigned char rightPixel =0;
int m,n,l;
int difPixel = 0;
int t1 = clock();
for (int i = SH2 ; i < imageHeight -SH2;i++)
{
for (int j = SW2; j<imageWidth - SW2;j++)
{
for (int k = j + minD; k <= j + maxD;k++)
{
difPixel = 0;
for (m = -SH2;m <= SH2;m++)
{
for (n = -SW2; n <= SW2;n++)
{
pRightPixel= (unsigned char*)rightImage->imageData+
(i+m)*rightImage->widthStep + j+n;
rightPixel = *pRightPixel;
if (k < SW2 || k >= imageWidth -SW2 )
{
difPixel += rightPixel;
}else {
pLeftPixel = (unsigned char*)leftImage->imageData +
(i+m)*leftImage->widthStep + k+n;
leftPixel = *pLeftPixel;
difPixel += abs(leftPixel - rightPixel);
}
}
}
if (difPixel <= max12Diff)
{
Ddynamic[j + 1][k + 1] = Ddynamic[j][k] +1;
}else if (Ddynamic[j][k+1] > Ddynamic[j+1][k])
{
Ddynamic[j + 1][k + 1] = Ddynamic[j][k+1];
}else{
Ddynamic[j+1][k+1] = Ddynamic[j+1][k];
}
//cout<<Ddynamic[j +1][k+1]<<" ";
}
//cout<<"\n";
}
//逆向搜索,找出最佳路径
m = imageWidth - SW2;
n = imageWidth - SW2;
int m2 = m, n2 = n;
while( m >= 1 && n >= 1)
{
if ((m2 == m + 1 && n2 >= n +1) || ( m2 > m +1 && n2 == n + 1))
{
pPixel = (unsigned char *)rightDepth->imageData + i*rightDepth->widthStep + m;
*pPixel = (n-m)*10;
//标记有效匹配点
pPixel = (unsigned char *)rightValid->imageData + i*rightValid->widthStep + m;
*pPixel = 255;
m2 = m;
n2 = n;
}
if (Ddynamic[m-1][n-1] >= Ddynamic[m][n -1] && Ddynamic[m-1][n -1] >= Ddynamic[m-1][n])
{
m--;
n--;
}else if (Ddynamic[m-1][n] >= Ddynamic[m][n -1] && Ddynamic[m-1][n] >= Ddynamic[m-1][n -1])
{
m--;
}
else
{
n--;
}
}
//cvWaitKey(0);
}
int t2 = clock();
cout<<"dt: "<<t2-t1<<endl;
//统计未能匹配点的个数
int count = 0;
for (int i = 0 ;i< imageHeight;i++)
{
for (int j= 0; j< imageWidth;j++)
{
pPixel = (unsigned char *)rightValid->imageData + i*rightValid->widthStep + j;
pixel = *pPixel;
if (pixel == 0)
{
count++;
}
}
}
cout<<"rightCount: "<<count<<" "<<(double)count/(imageWidth*imageHeight)<<endl;
rightFilter = cvCloneImage(rightDepth);
//7*7中值滤波
int halfMedianWindowSize = 3;
int medianWindowSize = 2*halfMedianWindowSize + 1;
int medianArray[100] = {0};
count = 0;
int temp = 0;
int medianVal = 0;
for (int i = halfMedianWindowSize + 1 ;i< imageHeight - halfMedianWindowSize;i++)
{
for (int j = halfMedianWindowSize; j< imageWidth - halfMedianWindowSize;j++)
{
pPixel = (unsigned char *)rightValid->imageData + i*rightValid->widthStep + j;
pixel = *pPixel;
if (pixel == 0)
{
count = 0;
for (int m = i - halfMedianWindowSize ; m <= i + halfMedianWindowSize ;m++)
{
for (int n = j - halfMedianWindowSize; n <= j + halfMedianWindowSize ;n++)
{
pPixel2 = (unsigned char *)rightDepth->imageData + m*rightDepth->widthStep + n;
pixel2 = *pPixel2;
if (pixel2 != 0)
{
medianArray[count] = pixel2;
count++;
}
}
//排序
for (int k = 0; k< count;k++)
{
for (int l = k + 1; l< count;l++)
{
if (medianArray[l] < medianArray[l-1] )
{
temp = medianArray[l];
medianArray[l] = medianArray[l-1];
medianArray[l-1] = temp;
}
}
}
medianVal = medianArray[count/2];
pPixel = (unsigned char *)rightFilter->imageData + i*rightFilter->widthStep + j;
*pPixel = medianVal;
}
}
}
}
//两次进行DP计算,分别是左对右和右对左,从右想左扫描
for (int j = 0; j<= imageWidth;j++)
{
for (int k = 0;k <= imageWidth;k++)
{
Ddynamic[j][k] = 0;
}
}
minD = -maxD;
maxD = 0;
for (int i = SH2 ; i < imageHeight -SH2;i++)
{
for (int j = imageWidth-SW2-1; j >= SW2;j--)
{
for (int k = j + maxD; k >= j + minD;k--)
{
difPixel = 0;
for (m = -SH2;m <= SH2;m++)
{
for (n = -SW2; n <= SW2;n++)
{
pLeftPixel = (unsigned char*)leftImage->imageData +
(i+m)*leftImage->widthStep + j+n;
leftPixel = *pLeftPixel;
if (k < SW2 || k >= imageWidth -SW2)
{
difPixel += leftPixel;
}else {
pRightPixel= (unsigned char*)rightImage->imageData+
(i+m)*rightImage->widthStep + k+n;
rightPixel = *pRightPixel;
difPixel += abs(leftPixel - rightPixel);
//cout<<Ddynamic[j +1][k+1]<<" ";
}
}
}
if (difPixel <= max12Diff)
{
Ddynamic[j][k] = Ddynamic[j+1][k+1] +1;
}else if (Ddynamic[j+1][k] > Ddynamic[j][k+1])
{
Ddynamic[j][k] = Ddynamic[j+1][k];
}else{
Ddynamic[j][k] = Ddynamic[j][k+1];
}
}
//cout<<"\n";
}
//逆向搜索,找出最佳路径
m = 0;
n = 0;
int m2 = m, n2 = n;
while( m < imageWidth && n < imageWidth)
{
if ((m == m2 + 1 && n >= n2 +1) || ( m > m2 +1 && n == n2 + 1))
{
pPixel = (unsigned char *)leftDepth->imageData + i*leftDepth->widthStep + m;
*pPixel = (m-n)*10;
//标记有效匹配点
pPixel = (unsigned char *)leftValid->imageData + i*leftValid->widthStep + m;
*pPixel = 255;
m2 = m;
n2 = n;
}
if (Ddynamic[m+1][n+1] >= Ddynamic[m][n+1] && Ddynamic[m+1][n+1] >= Ddynamic[m+1][n])
{
m++;
n++;
}else if (Ddynamic[m+1][n] >= Ddynamic[m][n +1] && Ddynamic[m+1][n] >= Ddynamic[m+1][n+1])
{
m++;
}
else
{
n++;
}
}
//cvWaitKey(0);
}
int t3 = clock();
//refine the depth image 7*7中值滤波
//统计未能匹配点的个数
count = 0;
for (int i = 0 ;i< imageHeight;i++)
{
for (int j= 0; j< imageWidth;j++)
{
pPixel = (unsigned char *)leftValid->imageData + i*leftValid->widthStep + j;
pixel = *pPixel;
if (pixel == 0)
{
count++;
}
}
}
cout<<"Left Count: "<<count<<" "<<(double)count/(imageWidth*imageHeight)<<endl;
//将关键信息计入文件
fprintf(pFile,"\nDP:\nClock: %dms",t3-t1);
fprintf(pFile,"\nInvalid Point: %f",(double)count/(imageWidth*imageHeight));
// cvWaitKey(0);
leftFilter = cvCloneImage(leftDepth);
//7*7中值滤波
count = 0;
for (int i = halfMedianWindowSize + 1 ;i< imageHeight - halfMedianWindowSize;i++)
{
for (int j = halfMedianWindowSize; j< imageWidth - halfMedianWindowSize;j++)
{
pPixel = (unsigned char *)leftValid->imageData + i*leftValid->widthStep + j;
pixel = *pPixel;
if (pixel == 0)
{
count = 0;
for (int m = i - halfMedianWindowSize ; m <= i + halfMedianWindowSize ;m++)
{
for (int n = j - halfMedianWindowSize; n <= j + halfMedianWindowSize ;n++)
{
pPixel2 = (unsigned char *)leftDepth->imageData + m*leftDepth->widthStep + n;
pixel2 = *pPixel2;
if (pixel2 != 0)
{
medianArray[count] = pixel2;
count++;
}
}
//排序
for (int k = 0; k< count;k++)
{
for (int l = k + 1; l< count;l++)
{
if (medianArray[l] < medianArray[l-1] )
{
temp = medianArray[l];
medianArray[l] = medianArray[l-1];
medianArray[l-1] = temp;
}
}
}
medianVal = medianArray[count/2];
pPixel = (unsigned char *)leftFilter->imageData + i*leftFilter->widthStep + j;
*pPixel = medianVal;
}
}
}
}
//假如已知左右图片的深度,进行refinement
unsigned char dLeft = 0, dRight = 0;
count = 0;
for (int i = 0; i< imageHeight;i++)
{
for (int j = 0; j< imageWidth;j++)
{
pRightPixel= (unsigned char*)rightDepth->imageData + i*rightDepth->widthStep + j;
dRight = (*pRightPixel)/10;
if (j + dRight < imageWidth)
{
pPixel= (unsigned char*)depth->imageData + i*depth->widthStep + j;
pLeftPixel= (unsigned char*)leftDepth->imageData + i*leftDepth->widthStep + j + dRight;
dLeft = (*pLeftPixel)/10;
if (abs(int(dRight) -(int)dLeft) <= 1)
{
//深度一致
*pPixel = dRight*10;
}else{
//深度不一致,认为是误匹配、错误匹配
*pPixel = 0;
count++;
}
}
}
}
cout<<"depth Count: "<<count<<" "<<(double)count/(imageWidth*imageHeight)<<endl;
cvNamedWindow("leftImage",1);
cvNamedWindow("rightImage",1);
cvNamedWindow("leftDepth",1);
cvNamedWindow("leftValid",1);
cvNamedWindow("rightDepth",1);
cvNamedWindow("rightValid",1);
cvNamedWindow("leftFilter",1);
cvNamedWindow("rightFilter",1);
cvNamedWindow("depth",1);
cvShowImage("leftImage",leftImage);
cvShowImage("rightImage",rightImage);
cvShowImage("leftDepth",leftDepth);
cvShowImage("rightDepth",rightDepth);
cvShowImage("leftValid",leftValid);
cvShowImage("rightValid",rightValid);
cvShowImage("leftFilter",leftFilter);
cvShowImage("rightFilter",rightFilter);
cvShowImage("depth",depth);
cvSaveImage("leftDepth.jpg",leftDepth);
cvSaveImage("rightDepth.jpg",rightDepth);
cvSaveImage("leftValid.jpg",leftValid);
cvSaveImage("rightValid.jpg",rightValid);
cvSaveImage("leftFilter.jpg",leftFilter);
cvSaveImage("rightFilter.jpg",rightFilter);
cvSaveImage("depth.jpg",depth);
fclose(pFile);
cvWaitKey(0);
return 0;
}
Subscribe to:
Post Comments (Atom)
Image processing based on FPGA
ReplyDelete系列讲座
http://blog.csdn.net/column/details/fpga-image.html
同一个人博客里有很多vison on FPGA 的信息