Home | History | Annotate | Download | only in src
      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 
     68 typedef struct _CvDPCell
     69 {
     70     uchar  step; //local-optimal step
     71     int    sum;  //current sum
     72 }_CvDPCell;
     73 
     74 typedef 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 
     84 void 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*/
    495 CV_IMPL void
    496 cvFindStereoCorrespondence(
    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