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 
icvFindStereoCorrespondenceByBirchfieldDP(uchar * src1,uchar * src2,uchar * disparities,CvSize size,int widthStep,int maxDisparity,float _param1,float _param2,float _param3,float _param4,float _param5)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
cvFindStereoCorrespondence(const CvArr * leftImage,const CvArr * rightImage,int mode,CvArr * depthImage,int maxDisparity,double param1,double param2,double param3,double param4,double param5)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