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// When CV_IMAX3 and CV_IMIN3 are used in the same expression, the evulation 80// order is undefined, and they should not assign to the same temporary variable. 81#define CV_IMAX3(a,b,c) ((max3 = (a) >= (b) ? (a) : (b)),(max3 >= (c) ? max3 : (c))) 82#define CV_IMIN3(a,b,c) ((min3 = (a) <= (b) ? (a) : (b)),(min3 <= (c) ? min3 : (c))) 83 84void icvFindStereoCorrespondenceByBirchfieldDP( uchar* src1, uchar* src2, 85 uchar* disparities, 86 CvSize size, int widthStep, 87 int maxDisparity, 88 float _param1, float _param2, 89 float _param3, float _param4, 90 float _param5 ) 91{ 92 int x, y, i, j, max3, min3; 93 int d, s; 94 int dispH = maxDisparity + 3; 95 uchar *dispdata; 96 int imgW = size.width; 97 int imgH = size.height; 98 uchar val, prevval, prev, curr; 99 int min_val; 100 uchar* dest = disparities; 101 int param1 = cvRound(_param1); 102 int param2 = cvRound(_param2); 103 int param3 = cvRound(_param3); 104 int param4 = cvRound(_param4); 105 int param5 = cvRound(_param5); 106 107 #define CELL(d,x) cells[(d)+(x)*dispH] 108 109 uchar* dsi = (uchar*)cvAlloc(sizeof(uchar)*imgW*dispH); 110 uchar* edges = (uchar*)cvAlloc(sizeof(uchar)*imgW*imgH); 111 _CvDPCell* cells = (_CvDPCell*)cvAlloc(sizeof(_CvDPCell)*imgW*MAX(dispH,(imgH+1)/2)); 112 _CvRightImData* rData = (_CvRightImData*)cvAlloc(sizeof(_CvRightImData)*imgW); 113 int* reliabilities = (int*)cells; 114 115 for( y = 0; y < imgH; y++ ) 116 { 117 uchar* srcdata1 = src1 + widthStep * y; 118 uchar* srcdata2 = src2 + widthStep * y; 119 120 //init rData 121 prevval = prev = srcdata2[0]; 122 for( j = 1; j < imgW; j++ ) 123 { 124 curr = srcdata2[j]; 125 val = (uchar)((curr + prev)>>1); 126 rData[j-1].max_val = (uchar)CV_IMAX3( val, prevval, prev ); 127 rData[j-1].min_val = (uchar)CV_IMIN3( val, prevval, prev ); 128 prevval = val; 129 prev = curr; 130 } 131 rData[j-1] = rData[j-2];//last elem 132 133 // fill dissimularity space image 134 for( i = 1; i <= maxDisparity + 1; i++ ) 135 { 136 dsi += imgW; 137 rData--; 138 for( j = i - 1; j < imgW - 1; j++ ) 139 { 140 int t; 141 if( (t = srcdata1[j] - rData[j+1].max_val) >= 0 ) 142 { 143 dsi[j] = (uchar)t; 144 } 145 else if( (t = rData[j+1].min_val - srcdata1[j]) >= 0 ) 146 { 147 dsi[j] = (uchar)t; 148 } 149 else 150 { 151 dsi[j] = 0; 152 } 153 } 154 } 155 dsi -= (maxDisparity+1)*imgW; 156 rData += maxDisparity+1; 157 158 //intensity gradients image construction 159 //left row 160 edges[y*imgW] = edges[y*imgW+1] = edges[y*imgW+2] = 2; 161 edges[y*imgW+imgW-1] = edges[y*imgW+imgW-2] = edges[y*imgW+imgW-3] = 1; 162 for( j = 3; j < imgW-4; j++ ) 163 { 164 edges[y*imgW+j] = 0; 165 166 if( ( CV_IMAX3( srcdata1[j-3], srcdata1[j-2], srcdata1[j-1] ) - 167 CV_IMIN3( srcdata1[j-3], srcdata1[j-2], srcdata1[j-1] ) ) >= ICV_BIRCH_DIFF_LUM ) 168 { 169 edges[y*imgW+j] |= 1; 170 } 171 if( ( CV_IMAX3( srcdata2[j+3], srcdata2[j+2], srcdata2[j+1] ) - 172 CV_IMIN3( srcdata2[j+3], srcdata2[j+2], srcdata2[j+1] ) ) >= ICV_BIRCH_DIFF_LUM ) 173 { 174 edges[y*imgW+j] |= 2; 175 } 176 } 177 178 //find correspondence using dynamical programming 179 //init DP table 180 for( x = 0; x < imgW; x++ ) 181 { 182 CELL(0,x).sum = CELL(dispH-1,x).sum = ICV_MAX_DP_SUM_VAL; 183 CELL(0,x).step = CELL(dispH-1,x).step = ICV_DP_STEP_LEFT; 184 } 185 for( d = 2; d < dispH; d++ ) 186 { 187 CELL(d,d-2).sum = ICV_MAX_DP_SUM_VAL; 188 CELL(d,d-2).step = ICV_DP_STEP_UP; 189 } 190 CELL(1,0).sum = 0; 191 CELL(1,0).step = ICV_DP_STEP_LEFT; 192 193 for( x = 1; x < imgW; x++ ) 194 { 195 int d = MIN( x + 1, maxDisparity + 1); 196 uchar* _edges = edges + y*imgW + x; 197 int e0 = _edges[0] & 1; 198 _CvDPCell* _cell = cells + x*dispH; 199 200 do 201 { 202 int s = dsi[d*imgW+x]; 203 int sum[3]; 204 205 //check left step 206 sum[0] = _cell[d-dispH].sum - param2; 207 208 //check up step 209 if( _cell[d+1].step != ICV_DP_STEP_DIAG && e0 ) 210 { 211 sum[1] = _cell[d+1].sum + param1; 212 213 if( _cell[d-1-dispH].step != ICV_DP_STEP_UP && (_edges[1-d] & 2) ) 214 { 215 int t; 216 217 sum[2] = _cell[d-1-dispH].sum + param1; 218 219 t = sum[1] < sum[0]; 220 221 //choose local-optimal pass 222 if( sum[t] <= sum[2] ) 223 { 224 _cell[d].step = (uchar)t; 225 _cell[d].sum = sum[t] + s; 226 } 227 else 228 { 229 _cell[d].step = ICV_DP_STEP_DIAG; 230 _cell[d].sum = sum[2] + s; 231 } 232 } 233 else 234 { 235 if( sum[0] <= sum[1] ) 236 { 237 _cell[d].step = ICV_DP_STEP_LEFT; 238 _cell[d].sum = sum[0] + s; 239 } 240 else 241 { 242 _cell[d].step = ICV_DP_STEP_UP; 243 _cell[d].sum = sum[1] + s; 244 } 245 } 246 } 247 else if( _cell[d-1-dispH].step != ICV_DP_STEP_UP && (_edges[1-d] & 2) ) 248 { 249 sum[2] = _cell[d-1-dispH].sum + param1; 250 if( sum[0] <= sum[2] ) 251 { 252 _cell[d].step = ICV_DP_STEP_LEFT; 253 _cell[d].sum = sum[0] + s; 254 } 255 else 256 { 257 _cell[d].step = ICV_DP_STEP_DIAG; 258 _cell[d].sum = sum[2] + s; 259 } 260 } 261 else 262 { 263 _cell[d].step = ICV_DP_STEP_LEFT; 264 _cell[d].sum = sum[0] + s; 265 } 266 } 267 while( --d ); 268 }// for x 269 270 //extract optimal way and fill disparity image 271 dispdata = dest + widthStep * y; 272 273 //find min_val 274 min_val = ICV_MAX_DP_SUM_VAL; 275 for( i = 1; i <= maxDisparity + 1; i++ ) 276 { 277 if( min_val > CELL(i,imgW-1).sum ) 278 { 279 d = i; 280 min_val = CELL(i,imgW-1).sum; 281 } 282 } 283 284 //track optimal pass 285 for( x = imgW - 1; x > 0; x-- ) 286 { 287 dispdata[x] = (uchar)(d - 1); 288 while( CELL(d,x).step == ICV_DP_STEP_UP ) d++; 289 if ( CELL(d,x).step == ICV_DP_STEP_DIAG ) 290 { 291 s = x; 292 while( CELL(d,x).step == ICV_DP_STEP_DIAG ) 293 { 294 d--; 295 x--; 296 } 297 for( i = x; i < s; i++ ) 298 { 299 dispdata[i] = (uchar)(d-1); 300 } 301 } 302 }//for x 303 }// for y 304 305 //Postprocessing the Disparity Map 306 307 //remove obvious errors in the disparity map 308 for( x = 0; x < imgW; x++ ) 309 { 310 for( y = 1; y < imgH - 1; y++ ) 311 { 312 if( dest[(y-1)*widthStep+x] == dest[(y+1)*widthStep+x] ) 313 { 314 dest[y*widthStep+x] = dest[(y-1)*widthStep+x]; 315 } 316 } 317 } 318 319 //compute intensity Y-gradients 320 for( x = 0; x < imgW; x++ ) 321 { 322 for( y = 1; y < imgH - 1; y++ ) 323 { 324 if( ( CV_IMAX3( src1[(y-1)*widthStep+x], src1[y*widthStep+x], 325 src1[(y+1)*widthStep+x] ) - 326 CV_IMIN3( src1[(y-1)*widthStep+x], src1[y*widthStep+x], 327 src1[(y+1)*widthStep+x] ) ) >= ICV_BIRCH_DIFF_LUM ) 328 { 329 edges[y*imgW+x] |= 4; 330 edges[(y+1)*imgW+x] |= 4; 331 edges[(y-1)*imgW+x] |= 4; 332 y++; 333 } 334 } 335 } 336 337 //remove along any particular row, every gradient 338 //for which two adjacent columns do not agree. 339 for( y = 0; y < imgH; y++ ) 340 { 341 prev = edges[y*imgW]; 342 for( x = 1; x < imgW - 1; x++ ) 343 { 344 curr = edges[y*imgW+x]; 345 if( (curr & 4) && 346 ( !( prev & 4 ) || 347 !( edges[y*imgW+x+1] & 4 ) ) ) 348 { 349 edges[y*imgW+x] -= 4; 350 } 351 prev = curr; 352 } 353 } 354 355 // define reliability 356 for( x = 0; x < imgW; x++ ) 357 { 358 for( y = 1; y < imgH; y++ ) 359 { 360 i = y - 1; 361 for( ; y < imgH && dest[y*widthStep+x] == dest[(y-1)*widthStep+x]; y++ ) 362 ; 363 s = y - i; 364 for( ; i < y; i++ ) 365 { 366 reliabilities[i*imgW+x] = s; 367 } 368 } 369 } 370 371 //Y - propagate reliable regions 372 for( x = 0; x < imgW; x++ ) 373 { 374 for( y = 0; y < imgH; y++ ) 375 { 376 d = dest[y*widthStep+x]; 377 if( reliabilities[y*imgW+x] >= param4 && !(edges[y*imgW+x] & 4) && 378 d > 0 )//highly || moderately 379 { 380 disparities[y*widthStep+x] = (uchar)d; 381 //up propagation 382 for( i = y - 1; i >= 0; i-- ) 383 { 384 if( ( edges[i*imgW+x] & 4 ) || 385 ( dest[i*widthStep+x] < d && 386 reliabilities[i*imgW+x] >= param3 ) || 387 ( reliabilities[y*imgW+x] < param5 && 388 dest[i*widthStep+x] - 1 == d ) ) break; 389 390 disparities[i*widthStep+x] = (uchar)d; 391 } 392 393 //down propagation 394 for( i = y + 1; i < imgH; i++ ) 395 { 396 if( ( edges[i*imgW+x] & 4 ) || 397 ( dest[i*widthStep+x] < d && 398 reliabilities[i*imgW+x] >= param3 ) || 399 ( reliabilities[y*imgW+x] < param5 && 400 dest[i*widthStep+x] - 1 == d ) ) break; 401 402 disparities[i*widthStep+x] = (uchar)d; 403 } 404 y = i - 1; 405 } 406 else 407 { 408 disparities[y*widthStep+x] = (uchar)d; 409 } 410 } 411 } 412 413 // define reliability along X 414 for( y = 0; y < imgH; y++ ) 415 { 416 for( x = 1; x < imgW; x++ ) 417 { 418 i = x - 1; 419 for( ; x < imgW && dest[y*widthStep+x] == dest[y*widthStep+x-1]; x++ ); 420 s = x - i; 421 for( ; i < x; i++ ) 422 { 423 reliabilities[y*imgW+i] = s; 424 } 425 } 426 } 427 428 //X - propagate reliable regions 429 for( y = 0; y < imgH; y++ ) 430 { 431 for( x = 0; x < imgW; x++ ) 432 { 433 d = dest[y*widthStep+x]; 434 if( reliabilities[y*imgW+x] >= param4 && !(edges[y*imgW+x] & 1) && 435 d > 0 )//highly || moderately 436 { 437 disparities[y*widthStep+x] = (uchar)d; 438 //up propagation 439 for( i = x - 1; i >= 0; i-- ) 440 { 441 if( (edges[y*imgW+i] & 1) || 442 ( dest[y*widthStep+i] < d && 443 reliabilities[y*imgW+i] >= param3 ) || 444 ( reliabilities[y*imgW+x] < param5 && 445 dest[y*widthStep+i] - 1 == d ) ) break; 446 447 disparities[y*widthStep+i] = (uchar)d; 448 } 449 450 //down propagation 451 for( i = x + 1; i < imgW; i++ ) 452 { 453 if( (edges[y*imgW+i] & 1) || 454 ( dest[y*widthStep+i] < d && 455 reliabilities[y*imgW+i] >= param3 ) || 456 ( reliabilities[y*imgW+x] < param5 && 457 dest[y*widthStep+i] - 1 == d ) ) break; 458 459 disparities[y*widthStep+i] = (uchar)d; 460 } 461 x = i - 1; 462 } 463 else 464 { 465 disparities[y*widthStep+x] = (uchar)d; 466 } 467 } 468 } 469 470 //release resources 471 cvFree( &dsi ); 472 cvFree( &edges ); 473 cvFree( &cells ); 474 cvFree( &rData ); 475} 476 477 478/*F/////////////////////////////////////////////////////////////////////////// 479// 480// Name: cvFindStereoCorrespondence 481// Purpose: find stereo correspondence on stereo-pair 482// Context: 483// Parameters: 484// leftImage - left image of stereo-pair (format 8uC1). 485// rightImage - right image of stereo-pair (format 8uC1). 486// mode -mode of correspondance retrieval (now CV_RETR_DP_BIRCHFIELD only) 487// dispImage - destination disparity image 488// maxDisparity - maximal disparity 489// param1, param2, param3, param4, param5 - parameters of algorithm 490// Returns: 491// Notes: 492// Images must be rectified. 493// All images must have format 8uC1. 494//F*/ 495CV_IMPL void 496cvFindStereoCorrespondence( 497 const CvArr* leftImage, const CvArr* rightImage, 498 int mode, 499 CvArr* depthImage, 500 int maxDisparity, 501 double param1, double param2, double param3, 502 double param4, double param5 ) 503{ 504 CV_FUNCNAME( "cvFindStereoCorrespondence" ); 505 506 __BEGIN__; 507 508 CvMat *src1, *src2; 509 CvMat *dst; 510 CvMat src1_stub, src2_stub, dst_stub; 511 int coi; 512 513 CV_CALL( src1 = cvGetMat( leftImage, &src1_stub, &coi )); 514 if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); 515 CV_CALL( src2 = cvGetMat( rightImage, &src2_stub, &coi )); 516 if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); 517 CV_CALL( dst = cvGetMat( depthImage, &dst_stub, &coi )); 518 if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); 519 520 // check args 521 if( CV_MAT_TYPE( src1->type ) != CV_8UC1 || 522 CV_MAT_TYPE( src2->type ) != CV_8UC1 || 523 CV_MAT_TYPE( dst->type ) != CV_8UC1) CV_ERROR(CV_StsUnsupportedFormat, 524 "All images must be single-channel and have 8u" ); 525 526 if( !CV_ARE_SIZES_EQ( src1, src2 ) || !CV_ARE_SIZES_EQ( src1, dst ) ) 527 CV_ERROR( CV_StsUnmatchedSizes, "" ); 528 529 if( maxDisparity <= 0 || maxDisparity >= src1->width || maxDisparity > 255 ) 530 CV_ERROR(CV_StsOutOfRange, 531 "parameter /maxDisparity/ is out of range"); 532 533 if( mode == CV_DISPARITY_BIRCHFIELD ) 534 { 535 if( param1 == CV_UNDEF_SC_PARAM ) param1 = CV_IDP_BIRCHFIELD_PARAM1; 536 if( param2 == CV_UNDEF_SC_PARAM ) param2 = CV_IDP_BIRCHFIELD_PARAM2; 537 if( param3 == CV_UNDEF_SC_PARAM ) param3 = CV_IDP_BIRCHFIELD_PARAM3; 538 if( param4 == CV_UNDEF_SC_PARAM ) param4 = CV_IDP_BIRCHFIELD_PARAM4; 539 if( param5 == CV_UNDEF_SC_PARAM ) param5 = CV_IDP_BIRCHFIELD_PARAM5; 540 541 CV_CALL( icvFindStereoCorrespondenceByBirchfieldDP( src1->data.ptr, 542 src2->data.ptr, dst->data.ptr, 543 cvGetMatSize( src1 ), src1->step, 544 maxDisparity, (float)param1, (float)param2, (float)param3, 545 (float)param4, (float)param5 ) ); 546 } 547 else 548 { 549 CV_ERROR( CV_StsBadArg, "Unsupported mode of function" ); 550 } 551 552 __END__; 553} 554 555/* End of file. */ 556 557