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;
}

1 comment:

  1. Image processing based on FPGA

    系列讲座
    http://blog.csdn.net/column/details/fpga-image.html

    同一个人博客里有很多vison on FPGA 的信息

    ReplyDelete