立体匹配—NCC算法代码

来源:互联网 发布:nokia软件下载 编辑:程序博客网 时间:2024/06/07 06:57
              NCC算法是立体匹配较为经典的一个算法,其定义为:

其中Wp为以像素p=(px,py)为中心的匹配窗口。I1为左图匹配窗口内的像素,I2为右图匹配窗口内的像素。


下面是用C++编写的算法:

<pre name="code" class="cpp">/***********************************************  * *   left_sq存放了左图窗口内像素与均值差值的平方 *   right_sq存放了右图窗口内像素与均值差值的平方 *   left_avg存放了左图窗口内像素的均值 *   right_avg存放了右图窗口内像素的均值 * **************************************************/void compute_sq(IplImage* left_img, IplImage* right_img, float *left_sq, float *right_sq, float *left_avg, float *right_avg){//图像的高度和宽度int height = left_img->height;int width = left_img->width;//窗口半径,为奇数int N = 5;//图像匹配的起始行和终止行int line_start = N;int line_end = height-N;//图像需要视差搜索的起始列和终止列int row_start = N;int row_end = width-N;int addr = 0;float temp_l = 0, temp_r = 0, suml = 0, sumr = 0;for (int j = line_start; j < line_end; j++){for (int i = row_start; i < row_end; i++){suml = 0.0, sumr = 0.0;temp_l = 0.0; temp_r = 0.0;for (int m = j - N; m <= j + N; m++){for (int n = i - N; n <= i + N; n++){suml += ((uchar*)(left_img->imageData + m*left_img->widthStep))[n];//cout << "l_px:" << (int)((uchar*)(left_img->imageData + m*left_img->widthStep))[n] << endl;sumr += ((uchar*)(right_img->imageData + m*right_img->widthStep))[n];//cout << "r_px:" << (int)((uchar*)(right_img->imageData + m*right_img->widthStep))[n]<<endl;}}addr = j*width + i;left_avg[addr] = suml / pow((2 * N + 1), 2);right_avg[addr] = sumr / pow((2 * N + 1), 2);//cout << "l_avg:" << (float)left_avg[addr]<<endl;//cout << "r_avg:" << (float)right_avg[addr]<<endl;for (int m = j - N; m <= j + N; m++){for (int n = i - N; n <= i + N; n++){temp_l += pow((((uchar*)(left_img->imageData + m*left_img->widthStep))[n] - left_avg[addr]), 2);temp_r += pow((((uchar*)(right_img->imageData + m*right_img->widthStep))[n] - right_avg[addr]), 2);}}left_sq[addr] = temp_l;right_sq[addr] = temp_r;//cout << "l_sq:" << (float)left_sq[addr] << endl;//cout << "r_sq:" << (float)right_sq[addr] << endl;}}}void compute_DP(IplImage* left_img, IplImage* right_img, IplImage* depth_img, float *left_sq, float *right_sq, float *left_avg, float *right_avg){    //图像的高度和宽度int height = left_img->height;int width = left_img->width;//窗口半径,为奇数int N = 5; //搜索的视差值范围int maxD = 10;int minD = 1;//图像匹配的起始行和终止行int line_start = N;int line_end = height-N;//图像需要视差搜索的起始列和终止列int row_start = N;int row_end = width-N-maxD;int addr;float max_tmp, cov_tmp;//视差int vd = 0;for (int j = line_start; j < line_end; j++){for (int i = row_start; i < row_end; i++){for (int d = minD; d <= maxD; d++){cov_tmp = 0.0;addr = j*width + i;for (int m = j - N; m <= j + N; m++){for (int n = i - N; n <= i + N; n++){//cout << "l_px:" << (int)((uchar*)(left_img->imageData + m*left_img->widthStep))[n] << endl;//cout << "l-avg:" << (float)(((uchar*)(left_img->imageData + m*left_img->widthStep))[n] - left_avg[addr]) << endl;//cout << "r_px:" << (int)((uchar*)(right_img->imageData + m*right_img->widthStep))[n + d] << endl;//cout << "r-avg:" << (float)(((uchar*)(right_img->imageData + m*right_img->widthStep))[n + d] - right_avg[addr+d])<<endl;cov_tmp += (((uchar*)(left_img->imageData + m*left_img->widthStep))[n]-left_avg[addr])*(((uchar*)(right_img->imageData + m*right_img->widthStep))[n + d]-right_avg[addr+d]);}}//cout << "a:" << cov_tmp << endl;cov_tmp = (float)(cov_tmp / sqrt(left_sq[addr] * right_sq[addr+d]));//cout << "cov_tmp:" << cov_tmp << endl;if (d == minD){max_tmp = cov_tmp;vd = d;}else{if (cov_tmp > max_tmp){max_tmp = cov_tmp;vd = d;}}}vd = vd * 20;if (vd > 255){vd = 255;}else if (vd < 0){vd = 0;}//cout << "d:" << vd << endl;((uchar*)(depth_img->imageData + j*depth_img->widthStep))[i] = vd;}}}void NCC_Match(IplImage* left_img, IplImage* right_img, IplImage* depth_img){float *left_sq, *right_sq, *left_avg, *right_avg;int img_size = left_img->height*left_img->width;left_sq = (float *)malloc(img_size * sizeof(float));right_sq = (float *)malloc(img_size * sizeof(float));left_avg = (float *)malloc(img_size * sizeof(float));right_avg = (float *)malloc(img_size * sizeof(float));memset(left_sq, 0, img_size);memset(right_sq, 0, img_size);compute_sq(left_img, right_img, left_sq, right_sq,left_avg,right_avg);compute_DP(left_img, right_img, depth_img, left_sq, right_sq,left_avg,right_avg);free(left_sq);free(right_sq);return;}


      在配置好opencv的VS环境下,输出标准的左右图运行即可,注意标准图是不需要做矫正的图,网上可以下到几张经典的图片。

      运行结果:

   

    效果只能说非常的一般,只适合初学者入门学习。

   转载请注明出处:http://blog.csdn.net/lvlitc/article/details/46431245

0 0
原创粉丝点击