1/*M/////////////////////////////////////////////////////////////////////////////////////// 2// 3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4// 5// By downloading, copying, installing or using the software you agree to this license. 6// If you do not agree to this license, do not download, install, 7// copy or use the software. 8// 9// 10// Intel License Agreement 11// For Open Source Computer Vision Library 12// 13// Copyright (C) 2000, Intel Corporation, all rights reserved. 14// Third party copyrights are property of their respective owners. 15// 16// Redistribution and use in source and binary forms, with or without modification, 17// are permitted provided that the following conditions are met: 18// 19// * Redistribution's of source code must retain the above copyright notice, 20// this list of conditions and the following disclaimer. 21// 22// * Redistribution's in binary form must reproduce the above copyright notice, 23// this list of conditions and the following disclaimer in the documentation 24// and/or other materials provided with the distribution. 25// 26// * The name of Intel Corporation may not be used to endorse or promote products 27// derived from this software without specific prior written permission. 28// 29// This software is provided by the copyright holders and contributors "as is" and 30// any express or implied warranties, including, but not limited to, the implied 31// warranties of merchantability and fitness for a particular purpose are disclaimed. 32// In no event shall the Intel Corporation or contributors be liable for any direct, 33// indirect, incidental, special, exemplary, or consequential damages 34// (including, but not limited to, procurement of substitute goods or services; 35// loss of use, data, or profits; or business interruption) however caused 36// and on any theory of liability, whether in contract, strict liability, 37// or tort (including negligence or otherwise) arising in any way out of 38// the use of this software, even if advised of the possibility of such damage. 39// 40//M*/ 41 42#include "_cvaux.h" 43 44/****************************************************************************************\ 45 The code below is some modification of Stan Birchfield's algorithm described in: 46 47 Depth Discontinuities by Pixel-to-Pixel Stereo 48 Stan Birchfield and Carlo Tomasi 49 International Journal of Computer Vision, 50 35(3): 269-293, December 1999. 51 52 This implementation uses different cost function that results in 53 O(pixPerRow*maxDisparity) complexity of dynamic programming stage versus 54 O(pixPerRow*log(pixPerRow)*maxDisparity) in the above paper. 55\****************************************************************************************/ 56 57/****************************************************************************************\ 58* Find stereo correspondence by dynamic programming algorithm * 59\****************************************************************************************/ 60#define ICV_DP_STEP_LEFT 0 61#define ICV_DP_STEP_UP 1 62#define ICV_DP_STEP_DIAG 2 63 64#define ICV_BIRCH_DIFF_LUM 5 65 66#define ICV_MAX_DP_SUM_VAL (INT_MAX/4) 67 68typedef struct _CvDPCell 69{ 70 uchar step; //local-optimal step 71 int sum; //current sum 72}_CvDPCell; 73 74typedef struct _CvRightImData 75{ 76 uchar min_val, max_val; 77} _CvRightImData; 78 79#define CV_IMAX3(a,b,c) ((temp3 = (a) >= (b) ? (a) : (b)),(temp3 >= (c) ? temp3 : (c))) 80#define CV_IMIN3(a,b,c) ((temp3 = (a) <= (b) ? (a) : (b)),(temp3 <= (c) ? temp3 : (c))) 81 82void icvFindStereoCorrespondenceByBirchfieldDP( uchar* src1, uchar* src2, 83 uchar* disparities, 84 CvSize size, int widthStep, 85 int maxDisparity, 86 float _param1, float _param2, 87 float _param3, float _param4, 88 float _param5 ) 89{ 90 int x, y, i, j, temp3; 91 int d, s; 92 int dispH = maxDisparity + 3; 93 uchar *dispdata; 94 int imgW = size.width; 95 int imgH = size.height; 96 uchar val, prevval, prev, curr; 97 int min_val; 98 uchar* dest = disparities; 99 int param1 = cvRound(_param1); 100 int param2 = cvRound(_param2); 101 int param3 = cvRound(_param3); 102 int param4 = cvRound(_param4); 103 int param5 = cvRound(_param5); 104 105 #define CELL(d,x) cells[(d)+(x)*dispH] 106 107 uchar* dsi = (uchar*)cvAlloc(sizeof(uchar)*imgW*dispH); 108 uchar* edges = (uchar*)cvAlloc(sizeof(uchar)*imgW*imgH); 109 _CvDPCell* cells = (_CvDPCell*)cvAlloc(sizeof(_CvDPCell)*imgW*MAX(dispH,(imgH+1)/2)); 110 _CvRightImData* rData = (_CvRightImData*)cvAlloc(sizeof(_CvRightImData)*imgW); 111 int* reliabilities = (int*)cells; 112 113 for( y = 0; y < imgH; y++ ) 114 { 115 uchar* srcdata1 = src1 + widthStep * y; 116 uchar* srcdata2 = src2 + widthStep * y; 117 118 //init rData 119 prevval = prev = srcdata2[0]; 120 for( j = 1; j < imgW; j++ ) 121 { 122 curr = srcdata2[j]; 123 val = (uchar)((curr + prev)>>1); 124 rData[j-1].max_val = (uchar)CV_IMAX3( val, prevval, prev ); 125 rData[j-1].min_val = (uchar)CV_IMIN3( val, prevval, prev ); 126 prevval = val; 127 prev = curr; 128 } 129 rData[j-1] = rData[j-2];//last elem 130 131 // fill dissimularity space image 132 for( i = 1; i <= maxDisparity + 1; i++ ) 133 { 134 dsi += imgW; 135 rData--; 136 for( j = i - 1; j < imgW - 1; j++ ) 137 { 138 int t; 139 if( (t = srcdata1[j] - rData[j+1].max_val) >= 0 ) 140 { 141 dsi[j] = (uchar)t; 142 } 143 else if( (t = rData[j+1].min_val - srcdata1[j]) >= 0 ) 144 { 145 dsi[j] = (uchar)t; 146 } 147 else 148 { 149 dsi[j] = 0; 150 } 151 } 152 } 153 dsi -= (maxDisparity+1)*imgW; 154 rData += maxDisparity+1; 155 156 //intensity gradients image construction 157 //left row 158 edges[y*imgW] = edges[y*imgW+1] = edges[y*imgW+2] = 2; 159 edges[y*imgW+imgW-1] = edges[y*imgW+imgW-2] = edges[y*imgW+imgW-3] = 1; 160 for( j = 3; j < imgW-4; j++ ) 161 { 162 edges[y*imgW+j] = 0; 163 164 if( ( CV_IMAX3( srcdata1[j-3], srcdata1[j-2], srcdata1[j-1] ) - 165 CV_IMIN3( srcdata1[j-3], srcdata1[j-2], srcdata1[j-1] ) ) >= ICV_BIRCH_DIFF_LUM ) 166 { 167 edges[y*imgW+j] |= 1; 168 } 169 if( ( CV_IMAX3( srcdata2[j+3], srcdata2[j+2], srcdata2[j+1] ) - 170 CV_IMIN3( srcdata2[j+3], srcdata2[j+2], srcdata2[j+1] ) ) >= ICV_BIRCH_DIFF_LUM ) 171 { 172 edges[y*imgW+j] |= 2; 173 } 174 } 175 176 //find correspondence using dynamical programming 177 //init DP table 178 for( x = 0; x < imgW; x++ ) 179 { 180 CELL(0,x).sum = CELL(dispH-1,x).sum = ICV_MAX_DP_SUM_VAL; 181 CELL(0,x).step = CELL(dispH-1,x).step = ICV_DP_STEP_LEFT; 182 } 183 for( d = 2; d < dispH; d++ ) 184 { 185 CELL(d,d-2).sum = ICV_MAX_DP_SUM_VAL; 186 CELL(d,d-2).step = ICV_DP_STEP_UP; 187 } 188 CELL(1,0).sum = 0; 189 CELL(1,0).step = ICV_DP_STEP_LEFT; 190 191 for( x = 1; x < imgW; x++ ) 192 { 193 int d = MIN( x + 1, maxDisparity + 1); 194 uchar* _edges = edges + y*imgW + x; 195 int e0 = _edges[0] & 1; 196 _CvDPCell* _cell = cells + x*dispH; 197 198 do 199 { 200 int s = dsi[d*imgW+x]; 201 int sum[3]; 202 203 //check left step 204 sum[0] = _cell[d-dispH].sum - param2; 205 206 //check up step 207 if( _cell[d+1].step != ICV_DP_STEP_DIAG && e0 ) 208 { 209 sum[1] = _cell[d+1].sum + param1; 210 211 if( _cell[d-1-dispH].step != ICV_DP_STEP_UP && (_edges[1-d] & 2) ) 212 { 213 int t; 214 215 sum[2] = _cell[d-1-dispH].sum + param1; 216 217 t = sum[1] < sum[0]; 218 219 //choose local-optimal pass 220 if( sum[t] <= sum[2] ) 221 { 222 _cell[d].step = (uchar)t; 223 _cell[d].sum = sum[t] + s; 224 } 225 else 226 { 227 _cell[d].step = ICV_DP_STEP_DIAG; 228 _cell[d].sum = sum[2] + s; 229 } 230 } 231 else 232 { 233 if( sum[0] <= sum[1] ) 234 { 235 _cell[d].step = ICV_DP_STEP_LEFT; 236 _cell[d].sum = sum[0] + s; 237 } 238 else 239 { 240 _cell[d].step = ICV_DP_STEP_UP; 241 _cell[d].sum = sum[1] + s; 242 } 243 } 244 } 245 else if( _cell[d-1-dispH].step != ICV_DP_STEP_UP && (_edges[1-d] & 2) ) 246 { 247 sum[2] = _cell[d-1-dispH].sum + param1; 248 if( sum[0] <= sum[2] ) 249 { 250 _cell[d].step = ICV_DP_STEP_LEFT; 251 _cell[d].sum = sum[0] + s; 252 } 253 else 254 { 255 _cell[d].step = ICV_DP_STEP_DIAG; 256 _cell[d].sum = sum[2] + s; 257 } 258 } 259 else 260 { 261 _cell[d].step = ICV_DP_STEP_LEFT; 262 _cell[d].sum = sum[0] + s; 263 } 264 } 265 while( --d ); 266 }// for x 267 268 //extract optimal way and fill disparity image 269 dispdata = dest + widthStep * y; 270 271 //find min_val 272 min_val = ICV_MAX_DP_SUM_VAL; 273 for( i = 1; i <= maxDisparity + 1; i++ ) 274 { 275 if( min_val > CELL(i,imgW-1).sum ) 276 { 277 d = i; 278 min_val = CELL(i,imgW-1).sum; 279 } 280 } 281 282 //track optimal pass 283 for( x = imgW - 1; x > 0; x-- ) 284 { 285 dispdata[x] = (uchar)(d - 1); 286 while( CELL(d,x).step == ICV_DP_STEP_UP ) d++; 287 if ( CELL(d,x).step == ICV_DP_STEP_DIAG ) 288 { 289 s = x; 290 while( CELL(d,x).step == ICV_DP_STEP_DIAG ) 291 { 292 d--; 293 x--; 294 } 295 for( i = x; i < s; i++ ) 296 { 297 dispdata[i] = (uchar)(d-1); 298 } 299 } 300 }//for x 301 }// for y 302 303 //Postprocessing the Disparity Map 304 305 //remove obvious errors in the disparity map 306 for( x = 0; x < imgW; x++ ) 307 { 308 for( y = 1; y < imgH - 1; y++ ) 309 { 310 if( dest[(y-1)*widthStep+x] == dest[(y+1)*widthStep+x] ) 311 { 312 dest[y*widthStep+x] = dest[(y-1)*widthStep+x]; 313 } 314 } 315 } 316 317 //compute intensity Y-gradients 318 for( x = 0; x < imgW; x++ ) 319 { 320 for( y = 1; y < imgH - 1; y++ ) 321 { 322 if( ( CV_IMAX3( src1[(y-1)*widthStep+x], src1[y*widthStep+x], 323 src1[(y+1)*widthStep+x] ) - 324 CV_IMIN3( src1[(y-1)*widthStep+x], src1[y*widthStep+x], 325 src1[(y+1)*widthStep+x] ) ) >= ICV_BIRCH_DIFF_LUM ) 326 { 327 edges[y*imgW+x] |= 4; 328 edges[(y+1)*imgW+x] |= 4; 329 edges[(y-1)*imgW+x] |= 4; 330 y++; 331 } 332 } 333 } 334 335 //remove along any particular row, every gradient 336 //for which two adjacent columns do not agree. 337 for( y = 0; y < imgH; y++ ) 338 { 339 prev = edges[y*imgW]; 340 for( x = 1; x < imgW - 1; x++ ) 341 { 342 curr = edges[y*imgW+x]; 343 if( (curr & 4) && 344 ( !( prev & 4 ) || 345 !( edges[y*imgW+x+1] & 4 ) ) ) 346 { 347 edges[y*imgW+x] -= 4; 348 } 349 prev = curr; 350 } 351 } 352 353 // define reliability 354 for( x = 0; x < imgW; x++ ) 355 { 356 for( y = 1; y < imgH; y++ ) 357 { 358 i = y - 1; 359 for( ; y < imgH && dest[y*widthStep+x] == dest[(y-1)*widthStep+x]; y++ ) 360 ; 361 s = y - i; 362 for( ; i < y; i++ ) 363 { 364 reliabilities[i*imgW+x] = s; 365 } 366 } 367 } 368 369 //Y - propagate reliable regions 370 for( x = 0; x < imgW; x++ ) 371 { 372 for( y = 0; y < imgH; y++ ) 373 { 374 d = dest[y*widthStep+x]; 375 if( reliabilities[y*imgW+x] >= param4 && !(edges[y*imgW+x] & 4) && 376 d > 0 )//highly || moderately 377 { 378 disparities[y*widthStep+x] = (uchar)d; 379 //up propagation 380 for( i = y - 1; i >= 0; i-- ) 381 { 382 if( ( edges[i*imgW+x] & 4 ) || 383 ( dest[i*widthStep+x] < d && 384 reliabilities[i*imgW+x] >= param3 ) || 385 ( reliabilities[y*imgW+x] < param5 && 386 dest[i*widthStep+x] - 1 == d ) ) break; 387 388 disparities[i*widthStep+x] = (uchar)d; 389 } 390 391 //down propagation 392 for( i = y + 1; i < imgH; i++ ) 393 { 394 if( ( edges[i*imgW+x] & 4 ) || 395 ( dest[i*widthStep+x] < d && 396 reliabilities[i*imgW+x] >= param3 ) || 397 ( reliabilities[y*imgW+x] < param5 && 398 dest[i*widthStep+x] - 1 == d ) ) break; 399 400 disparities[i*widthStep+x] = (uchar)d; 401 } 402 y = i - 1; 403 } 404 else 405 { 406 disparities[y*widthStep+x] = (uchar)d; 407 } 408 } 409 } 410 411 // define reliability along X 412 for( y = 0; y < imgH; y++ ) 413 { 414 for( x = 1; x < imgW; x++ ) 415 { 416 i = x - 1; 417 for( ; x < imgW && dest[y*widthStep+x] == dest[y*widthStep+x-1]; x++ ); 418 s = x - i; 419 for( ; i < x; i++ ) 420 { 421 reliabilities[y*imgW+i] = s; 422 } 423 } 424 } 425 426 //X - propagate reliable regions 427 for( y = 0; y < imgH; y++ ) 428 { 429 for( x = 0; x < imgW; x++ ) 430 { 431 d = dest[y*widthStep+x]; 432 if( reliabilities[y*imgW+x] >= param4 && !(edges[y*imgW+x] & 1) && 433 d > 0 )//highly || moderately 434 { 435 disparities[y*widthStep+x] = (uchar)d; 436 //up propagation 437 for( i = x - 1; i >= 0; i-- ) 438 { 439 if( (edges[y*imgW+i] & 1) || 440 ( dest[y*widthStep+i] < d && 441 reliabilities[y*imgW+i] >= param3 ) || 442 ( reliabilities[y*imgW+x] < param5 && 443 dest[y*widthStep+i] - 1 == d ) ) break; 444 445 disparities[y*widthStep+i] = (uchar)d; 446 } 447 448 //down propagation 449 for( i = x + 1; i < imgW; i++ ) 450 { 451 if( (edges[y*imgW+i] & 1) || 452 ( dest[y*widthStep+i] < d && 453 reliabilities[y*imgW+i] >= param3 ) || 454 ( reliabilities[y*imgW+x] < param5 && 455 dest[y*widthStep+i] - 1 == d ) ) break; 456 457 disparities[y*widthStep+i] = (uchar)d; 458 } 459 x = i - 1; 460 } 461 else 462 { 463 disparities[y*widthStep+x] = (uchar)d; 464 } 465 } 466 } 467 468 //release resources 469 cvFree( &dsi ); 470 cvFree( &edges ); 471 cvFree( &cells ); 472 cvFree( &rData ); 473} 474 475 476/*F/////////////////////////////////////////////////////////////////////////// 477// 478// Name: cvFindStereoCorrespondence 479// Purpose: find stereo correspondence on stereo-pair 480// Context: 481// Parameters: 482// leftImage - left image of stereo-pair (format 8uC1). 483// rightImage - right image of stereo-pair (format 8uC1). 484// mode -mode of correspondance retrieval (now CV_RETR_DP_BIRCHFIELD only) 485// dispImage - destination disparity image 486// maxDisparity - maximal disparity 487// param1, param2, param3, param4, param5 - parameters of algorithm 488// Returns: 489// Notes: 490// Images must be rectified. 491// All images must have format 8uC1. 492//F*/ 493CV_IMPL void 494cvFindStereoCorrespondence( 495 const CvArr* leftImage, const CvArr* rightImage, 496 int mode, 497 CvArr* depthImage, 498 int maxDisparity, 499 double param1, double param2, double param3, 500 double param4, double param5 ) 501{ 502 CV_FUNCNAME( "cvFindStereoCorrespondence" ); 503 504 __BEGIN__; 505 506 CvMat *src1, *src2; 507 CvMat *dst; 508 CvMat src1_stub, src2_stub, dst_stub; 509 int coi; 510 511 CV_CALL( src1 = cvGetMat( leftImage, &src1_stub, &coi )); 512 if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); 513 CV_CALL( src2 = cvGetMat( rightImage, &src2_stub, &coi )); 514 if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); 515 CV_CALL( dst = cvGetMat( depthImage, &dst_stub, &coi )); 516 if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); 517 518 // check args 519 if( CV_MAT_TYPE( src1->type ) != CV_8UC1 || 520 CV_MAT_TYPE( src2->type ) != CV_8UC1 || 521 CV_MAT_TYPE( dst->type ) != CV_8UC1) CV_ERROR(CV_StsUnsupportedFormat, 522 "All images must be single-channel and have 8u" ); 523 524 if( !CV_ARE_SIZES_EQ( src1, src2 ) || !CV_ARE_SIZES_EQ( src1, dst ) ) 525 CV_ERROR( CV_StsUnmatchedSizes, "" ); 526 527 if( maxDisparity <= 0 || maxDisparity >= src1->width || maxDisparity > 255 ) 528 CV_ERROR(CV_StsOutOfRange, 529 "parameter /maxDisparity/ is out of range"); 530 531 if( mode == CV_DISPARITY_BIRCHFIELD ) 532 { 533 if( param1 == CV_UNDEF_SC_PARAM ) param1 = CV_IDP_BIRCHFIELD_PARAM1; 534 if( param2 == CV_UNDEF_SC_PARAM ) param2 = CV_IDP_BIRCHFIELD_PARAM2; 535 if( param3 == CV_UNDEF_SC_PARAM ) param3 = CV_IDP_BIRCHFIELD_PARAM3; 536 if( param4 == CV_UNDEF_SC_PARAM ) param4 = CV_IDP_BIRCHFIELD_PARAM4; 537 if( param5 == CV_UNDEF_SC_PARAM ) param5 = CV_IDP_BIRCHFIELD_PARAM5; 538 539 CV_CALL( icvFindStereoCorrespondenceByBirchfieldDP( src1->data.ptr, 540 src2->data.ptr, dst->data.ptr, 541 cvGetMatSize( src1 ), src1->step, 542 maxDisparity, (float)param1, (float)param2, (float)param3, 543 (float)param4, (float)param5 ) ); 544 } 545 else 546 { 547 CV_ERROR( CV_StsBadArg, "Unsupported mode of function" ); 548 } 549 550 __END__; 551} 552 553/* End of file. */ 554 555