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 "_cv.h"
43
44#undef INFINITY
45#define INFINITY 10000
46#define OCCLUSION_PENALTY 10000
47#define OCCLUSION_PENALTY2 1000
48#define DENOMINATOR 16
49#undef OCCLUDED
50#define OCCLUDED CV_STEREO_GC_OCCLUDED
51#define CUTOFF 1000
52#define IS_BLOCKED(d1, d2) ((d1) > (d2))
53
54typedef struct GCVtx
55{
56    GCVtx *next;
57    int parent;
58    int first;
59    int ts;
60    int dist;
61    short weight;
62    uchar t;
63}
64GCVtx;
65
66typedef struct GCEdge
67{
68    GCVtx* dst;
69    int next;
70    int weight;
71}
72GCEdge;
73
74typedef struct CvStereoGCState2
75{
76    int Ithreshold, interactionRadius;
77    int lambda, lambda1, lambda2, K;
78    int dataCostFuncTab[CUTOFF+1];
79    int smoothnessR[CUTOFF*2+1];
80    int smoothnessGrayDiff[512];
81    GCVtx** orphans;
82    int maxOrphans;
83}
84CvStereoGCState2;
85
86// truncTab[x+255] = MAX(x-255,0)
87static uchar icvTruncTab[512];
88// cutoffSqrTab[x] = MIN(x*x, CUTOFF)
89static int icvCutoffSqrTab[256];
90
91static void icvInitStereoConstTabs()
92{
93    static volatile int initialized = 0;
94    if( !initialized )
95    {
96        int i;
97        for( i = 0; i < 512; i++ )
98            icvTruncTab[i] = (uchar)MIN(MAX(i-255,0),255);
99        for( i = 0; i < 256; i++ )
100            icvCutoffSqrTab[i] = MIN(i*i, CUTOFF);
101        initialized = 1;
102    }
103}
104
105static void icvInitStereoTabs( CvStereoGCState2* state2 )
106{
107    int i, K = state2->K;
108
109    for( i = 0; i <= CUTOFF; i++ )
110        state2->dataCostFuncTab[i] = MIN(i*DENOMINATOR - K, 0);
111
112    for( i = 0; i < CUTOFF*2 + 1; i++ )
113        state2->smoothnessR[i] = MIN(abs(i-CUTOFF), state2->interactionRadius);
114
115    for( i = 0; i < 512; i++ )
116    {
117        int diff = abs(i - 255);
118        state2->smoothnessGrayDiff[i] = diff < state2->Ithreshold ? state2->lambda1 : state2->lambda2;
119    }
120}
121
122
123static int icvGCResizeOrphansBuf( GCVtx**& orphans, int norphans )
124{
125    int i, newNOrphans = MAX(norphans*3/2, 256);
126    GCVtx** newOrphans = (GCVtx**)cvAlloc( newNOrphans*sizeof(orphans[0]) );
127    for( i = 0; i < norphans; i++ )
128        newOrphans[i] = orphans[i];
129    cvFree( &orphans );
130    orphans = newOrphans;
131    return newNOrphans;
132}
133
134static int64 icvGCMaxFlow( GCVtx* vtx, int nvtx, GCEdge* edges, GCVtx**& _orphans, int& _maxOrphans )
135{
136    const int TERMINAL = -1, ORPHAN = -2;
137    GCVtx stub, *nil = &stub, *first = nil, *last = nil;
138    int i, k;
139    int curr_ts = 0;
140    int64 flow = 0;
141    int norphans = 0, maxOrphans = _maxOrphans;
142    GCVtx** orphans = _orphans;
143    stub.next = nil;
144
145    // initialize the active queue and the graph vertices
146    for( i = 0; i < nvtx; i++ )
147    {
148        GCVtx* v = vtx + i;
149        v->ts = 0;
150        if( v->weight != 0 )
151        {
152            last = last->next = v;
153            v->dist = 1;
154            v->parent = TERMINAL;
155            v->t = v->weight < 0;
156        }
157        else
158            v->parent = 0;
159    }
160
161    first = first->next;
162    last->next = nil;
163    nil->next = 0;
164
165    // run the search-path -> augment-graph -> restore-trees loop
166    for(;;)
167    {
168        GCVtx* v, *u;
169        int e0 = -1, ei = 0, ej = 0, min_weight, weight;
170        uchar vt;
171
172        // grow S & T search trees, find an edge connecting them
173        while( first != nil )
174        {
175            v = first;
176            if( v->parent )
177            {
178                vt = v->t;
179                for( ei = v->first; ei != 0; ei = edges[ei].next )
180                {
181                    if( edges[ei^vt].weight == 0 )
182                        continue;
183                    u = edges[ei].dst;
184                    if( !u->parent )
185                    {
186                        u->t = vt;
187                        u->parent = ei ^ 1;
188                        u->ts = v->ts;
189                        u->dist = v->dist + 1;
190                        if( !u->next )
191                        {
192                            u->next = nil;
193                            last = last->next = u;
194                        }
195                        continue;
196                    }
197
198                    if( u->t != vt )
199                    {
200                        e0 = ei ^ vt;
201                        break;
202                    }
203
204                    if( u->dist > v->dist+1 && u->ts <= v->ts )
205                    {
206                        // reassign the parent
207                        u->parent = ei ^ 1;
208                        u->ts = v->ts;
209                        u->dist = v->dist + 1;
210                    }
211                }
212                if( e0 > 0 )
213                    break;
214            }
215            // exclude the vertex from the active list
216            first = first->next;
217            v->next = 0;
218        }
219
220        if( e0 <= 0 )
221            break;
222
223        // find the minimum edge weight along the path
224        min_weight = edges[e0].weight;
225        assert( min_weight > 0 );
226        // k = 1: source tree, k = 0: destination tree
227        for( k = 1; k >= 0; k-- )
228        {
229            for( v = edges[e0^k].dst;; v = edges[ei].dst )
230            {
231                if( (ei = v->parent) < 0 )
232                    break;
233                weight = edges[ei^k].weight;
234                min_weight = MIN(min_weight, weight);
235                assert( min_weight > 0 );
236            }
237            weight = abs(v->weight);
238            min_weight = MIN(min_weight, weight);
239            assert( min_weight > 0 );
240        }
241
242        // modify weights of the edges along the path and collect orphans
243        edges[e0].weight -= min_weight;
244        edges[e0^1].weight += min_weight;
245        flow += min_weight;
246
247        // k = 1: source tree, k = 0: destination tree
248        for( k = 1; k >= 0; k-- )
249        {
250            for( v = edges[e0^k].dst;; v = edges[ei].dst )
251            {
252                if( (ei = v->parent) < 0 )
253                    break;
254                edges[ei^(k^1)].weight += min_weight;
255                if( (edges[ei^k].weight -= min_weight) == 0 )
256                {
257                    if( norphans >= maxOrphans )
258                        maxOrphans = icvGCResizeOrphansBuf( orphans, norphans );
259                    orphans[norphans++] = v;
260                    v->parent = ORPHAN;
261                }
262            }
263
264            v->weight = (short)(v->weight + min_weight*(1-k*2));
265            if( v->weight == 0 )
266            {
267                if( norphans >= maxOrphans )
268                    maxOrphans = icvGCResizeOrphansBuf( orphans, norphans );
269                orphans[norphans++] = v;
270                v->parent = ORPHAN;
271            }
272        }
273
274        // restore the search trees by finding new parents for the orphans
275        curr_ts++;
276        while( norphans > 0 )
277        {
278            GCVtx* v = orphans[--norphans];
279            int d, min_dist = INT_MAX;
280            e0 = 0;
281            vt = v->t;
282
283            for( ei = v->first; ei != 0; ei = edges[ei].next )
284            {
285                if( edges[ei^(vt^1)].weight == 0 )
286                    continue;
287                u = edges[ei].dst;
288                if( u->t != vt || u->parent == 0 )
289                    continue;
290                // compute the distance to the tree root
291                for( d = 0;; )
292                {
293                    if( u->ts == curr_ts )
294                    {
295                        d += u->dist;
296                        break;
297                    }
298                    ej = u->parent;
299                    d++;
300                    if( ej < 0 )
301                    {
302                        if( ej == ORPHAN )
303                            d = INT_MAX-1;
304                        else
305                        {
306                            u->ts = curr_ts;
307                            u->dist = 1;
308                        }
309                        break;
310                    }
311                    u = edges[ej].dst;
312                }
313
314                // update the distance
315                if( ++d < INT_MAX )
316                {
317                    if( d < min_dist )
318                    {
319                        min_dist = d;
320                        e0 = ei;
321                    }
322                    for( u = edges[ei].dst; u->ts != curr_ts; u = edges[u->parent].dst )
323                    {
324                        u->ts = curr_ts;
325                        u->dist = --d;
326                    }
327                }
328            }
329
330            if( (v->parent = e0) > 0 )
331            {
332                v->ts = curr_ts;
333                v->dist = min_dist;
334                continue;
335            }
336
337            /* no parent is found */
338            v->ts = 0;
339            for( ei = v->first; ei != 0; ei = edges[ei].next )
340            {
341                u = edges[ei].dst;
342                ej = u->parent;
343                if( u->t != vt || !ej )
344                    continue;
345                if( edges[ei^(vt^1)].weight && !u->next )
346                {
347                    u->next = nil;
348                    last = last->next = u;
349                }
350                if( ej > 0 && edges[ej].dst == v )
351                {
352                    if( norphans >= maxOrphans )
353                        maxOrphans = icvGCResizeOrphansBuf( orphans, norphans );
354                    orphans[norphans++] = u;
355                    u->parent = ORPHAN;
356                }
357            }
358        }
359    }
360
361    _orphans = orphans;
362    _maxOrphans = maxOrphans;
363
364    return flow;
365}
366
367
368CvStereoGCState* cvCreateStereoGCState( int numberOfDisparities, int maxIters )
369{
370    CvStereoGCState* state = 0;
371
372    //CV_FUNCNAME("cvCreateStereoGCState");
373
374    __BEGIN__;
375
376    state = (CvStereoGCState*)cvAlloc( sizeof(*state) );
377    memset( state, 0, sizeof(*state) );
378    state->minDisparity = 0;
379    state->numberOfDisparities = numberOfDisparities;
380    state->maxIters = maxIters <= 0 ? 3 : maxIters;
381    state->Ithreshold = 5;
382    state->interactionRadius = 1;
383    state->K = state->lambda = state->lambda1 = state->lambda2 = -1.f;
384    state->occlusionCost = OCCLUSION_PENALTY;
385
386    __END__;
387
388    return state;
389}
390
391void cvReleaseStereoGCState( CvStereoGCState** _state )
392{
393    CvStereoGCState* state;
394
395    if( !_state && !*_state )
396        return;
397
398    state = *_state;
399    cvReleaseMat( &state->left );
400    cvReleaseMat( &state->right );
401    cvReleaseMat( &state->ptrLeft );
402    cvReleaseMat( &state->ptrRight );
403    cvReleaseMat( &state->vtxBuf );
404    cvReleaseMat( &state->edgeBuf );
405    cvFree( _state );
406}
407
408// ||I(x) - J(x')|| =
409// min(CUTOFF,
410//   min(
411//     max(
412//       max(minJ(x') - I(x), 0),
413//       max(I(x) - maxJ(x'), 0)),
414//     max(
415//       max(minI(x) - J(x'), 0),
416//       max(J(x') - maxI(x), 0)))**2) ==
417// min(CUTOFF,
418//   min(
419//       max(minJ(x') - I(x), 0) +
420//       max(I(x) - maxJ(x'), 0),
421//
422//       max(minI(x) - J(x'), 0) +
423//       max(J(x') - maxI(x), 0)))**2)
424// where (I, minI, maxI) and
425//       (J, minJ, maxJ) are stored as interleaved 3-channel images.
426// minI, maxI are computed from I,
427// minJ, maxJ are computed from J - see icvInitGraySubPix.
428static inline int icvDataCostFuncGraySubpix( const uchar* a, const uchar* b )
429{
430    int va = a[0], vb = b[0];
431    int da = icvTruncTab[b[1] - va + 255] + icvTruncTab[va - b[2] + 255];
432    int db = icvTruncTab[a[1] - vb + 255] + icvTruncTab[vb - a[2] + 255];
433    return icvCutoffSqrTab[MIN(da,db)];
434}
435
436static inline int icvSmoothnessCostFunc( int da, int db, int maxR, const int* stabR, int scale )
437{
438    return da == db ? 0 : (da == OCCLUDED || db == OCCLUDED ? maxR : stabR[da - db])*scale;
439}
440
441static void icvInitGraySubpix( const CvMat* left, const CvMat* right,
442                               CvMat* left3, CvMat* right3 )
443{
444    int k, x, y, rows = left->rows, cols = left->cols;
445
446    for( k = 0; k < 2; k++ )
447    {
448        const CvMat* src = k == 0 ? left : right;
449        CvMat* dst = k == 0 ? left3 : right3;
450        int sstep = src->step;
451
452        for( y = 0; y < rows; y++ )
453        {
454            const uchar* sptr = src->data.ptr + sstep*y;
455            const uchar* sptr_prev = y > 0 ? sptr - sstep : sptr;
456            const uchar* sptr_next = y < rows-1 ? sptr + sstep : sptr;
457            uchar* dptr = dst->data.ptr + dst->step*y;
458            int v_prev = sptr[0];
459
460            for( x = 0; x < cols; x++, dptr += 3 )
461            {
462                int v = sptr[x], v1, minv = v, maxv = v;
463
464                v1 = (v + v_prev)/2;
465                minv = MIN(minv, v1); maxv = MAX(maxv, v1);
466                v1 = (v + sptr_prev[x])/2;
467                minv = MIN(minv, v1); maxv = MAX(maxv, v1);
468                v1 = (v + sptr_next[x])/2;
469                minv = MIN(minv, v1); maxv = MAX(maxv, v1);
470                if( x < cols-1 )
471                {
472                    v1 = (v + sptr[x+1])/2;
473                    minv = MIN(minv, v1); maxv = MAX(maxv, v1);
474                }
475                v_prev = v;
476                dptr[0] = (uchar)v;
477                dptr[1] = (uchar)minv;
478                dptr[2] = (uchar)maxv;
479            }
480        }
481    }
482}
483
484// Optimal K is computed as avg_x(k-th-smallest_d(||I(x)-J(x+d)||)),
485// where k = number_of_disparities*0.25.
486static float
487icvComputeK( CvStereoGCState* state )
488{
489    int x, y, x1, d, i, j, rows = state->left->rows, cols = state->left->cols, n = 0;
490    int mind = state->minDisparity, nd = state->numberOfDisparities, maxd = mind + nd;
491    int k = MIN(MAX((nd + 2)/4, 3), nd);
492    int *arr = (int*)cvStackAlloc(k*sizeof(arr[0])), delta, t, sum = 0;
493
494    for( y = 0; y < rows; y++ )
495    {
496        const uchar* lptr = state->left->data.ptr + state->left->step*y;
497        const uchar* rptr = state->right->data.ptr + state->right->step*y;
498
499        for( x = 0; x < cols; x++ )
500        {
501            for( d = maxd-1, i = 0; d >= mind; d-- )
502            {
503                x1 = x - d;
504                if( (unsigned)x1 >= (unsigned)cols )
505                    continue;
506                delta = icvDataCostFuncGraySubpix( lptr + x*3, rptr + x1*3 );
507                if( i < k )
508                    arr[i++] = delta;
509                else
510                    for( i = 0; i < k; i++ )
511                        if( delta < arr[i] )
512                            CV_SWAP( arr[i], delta, t );
513            }
514            delta = arr[0];
515            for( j = 1; j < i; j++ )
516                delta = MAX(delta, arr[j]);
517            sum += delta;
518            n++;
519        }
520    }
521
522    return (float)sum/n;
523}
524
525static int64 icvComputeEnergy( const CvStereoGCState* state, const CvStereoGCState2* state2,
526                               bool allOccluded )
527{
528    int x, y, rows = state->left->rows, cols = state->left->cols;
529    int64 E = 0;
530    const int* dtab = state2->dataCostFuncTab;
531    int maxR = state2->interactionRadius;
532    const int* stabR = state2->smoothnessR + CUTOFF;
533    const int* stabI = state2->smoothnessGrayDiff + 255;
534    const uchar* left = state->left->data.ptr;
535    const uchar* right = state->right->data.ptr;
536    short* dleft = state->dispLeft->data.s;
537    short* dright = state->dispRight->data.s;
538    int step = state->left->step;
539    int dstep = (int)(state->dispLeft->step/sizeof(short));
540
541    assert( state->left->step == state->right->step &&
542        state->dispLeft->step == state->dispRight->step );
543
544    if( allOccluded )
545        return (int64)OCCLUSION_PENALTY*rows*cols*2;
546
547    for( y = 0; y < rows; y++, left += step, right += step, dleft += dstep, dright += dstep )
548    {
549        for( x = 0; x < cols; x++ )
550        {
551            int d = dleft[x], x1, d1;
552            if( d == OCCLUDED )
553                E += OCCLUSION_PENALTY;
554            else
555            {
556                x1 = x + d;
557                if( (unsigned)x1 >= (unsigned)cols )
558                    continue;
559                d1 = dright[x1];
560                if( d == -d1 )
561                    E += dtab[icvDataCostFuncGraySubpix( left + x*3, right + x1*3 )];
562            }
563
564            if( x < cols-1 )
565            {
566                d1 = dleft[x+1];
567                E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[left[x*3] - left[x*3+3]] );
568            }
569            if( y < rows-1 )
570            {
571                d1 = dleft[x+dstep];
572                E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[left[x*3] - left[x*3+step]] );
573            }
574
575            d = dright[x];
576            if( d == OCCLUDED )
577                E += OCCLUSION_PENALTY;
578
579            if( x < cols-1 )
580            {
581                d1 = dright[x+1];
582                E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[right[x*3] - right[x*3+3]] );
583            }
584            if( y < rows-1 )
585            {
586                d1 = dright[x+dstep];
587                E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[right[x*3] - right[x*3+step]] );
588            }
589            assert( E >= 0 );
590        }
591    }
592
593    return E;
594}
595
596static inline void icvAddEdge( GCVtx *x, GCVtx* y, GCEdge* edgeBuf, int nedges, int w, int rw )
597{
598    GCEdge *xy = edgeBuf + nedges, *yx = xy + 1;
599
600    assert( x != 0 && y != 0 );
601    xy->dst = y;
602    xy->next = x->first;
603    xy->weight = (short)w;
604    x->first = nedges;
605
606    yx->dst = x;
607    yx->next = y->first;
608    yx->weight = (short)rw;
609    y->first = nedges+1;
610}
611
612static inline int icvAddTWeights( GCVtx* vtx, int sourceWeight, int sinkWeight )
613{
614    int w = vtx->weight;
615    if( w > 0 )
616        sourceWeight += w;
617    else
618        sinkWeight -= w;
619    vtx->weight = (short)(sourceWeight - sinkWeight);
620    return MIN(sourceWeight, sinkWeight);
621}
622
623static inline int icvAddTerm( GCVtx* x, GCVtx* y, int A, int B, int C, int D,
624                              GCEdge* edgeBuf, int& nedges )
625{
626    int dE = 0, w;
627
628    assert(B - A + C - D >= 0);
629    if( B < A )
630    {
631        dE += icvAddTWeights(x, D, B);
632        dE += icvAddTWeights(y, 0, A - B);
633        if( (w = B - A + C - D) != 0 )
634        {
635            icvAddEdge( x, y, edgeBuf, nedges, 0, w );
636            nedges += 2;
637        }
638    }
639    else if( C < D )
640    {
641        dE += icvAddTWeights(x, D, A + D - C);
642        dE += icvAddTWeights(y, 0, C - D);
643        if( (w = B - A + C - D) != 0 )
644        {
645            icvAddEdge( x, y, edgeBuf, nedges, w, 0 );
646            nedges += 2;
647        }
648    }
649    else
650    {
651        dE += icvAddTWeights(x, D, A);
652        if( B != A || C != D )
653        {
654            icvAddEdge( x, y, edgeBuf, nedges, B - A, C - D );
655            nedges += 2;
656        }
657    }
658    return dE;
659}
660
661static int64 icvAlphaExpand( int64 Eprev, int alpha, CvStereoGCState* state, CvStereoGCState2* state2 )
662{
663    GCVtx *var, *var1;
664    int64 E = 0;
665    int delta, E00=0, E0a=0, Ea0=0, Eaa=0;
666    int k, a, d, d1, x, y, x1, y1, rows = state->left->rows, cols = state->left->cols;
667    int nvtx = 0, nedges = 2;
668    GCVtx* vbuf = (GCVtx*)state->vtxBuf->data.ptr;
669    GCEdge* ebuf = (GCEdge*)state->edgeBuf->data.ptr;
670    int maxR = state2->interactionRadius;
671    const int* dtab = state2->dataCostFuncTab;
672    const int* stabR = state2->smoothnessR + CUTOFF;
673    const int* stabI = state2->smoothnessGrayDiff + 255;
674    const uchar* left0 = state->left->data.ptr;
675    const uchar* right0 = state->right->data.ptr;
676    short* dleft0 = state->dispLeft->data.s;
677    short* dright0 = state->dispRight->data.s;
678    GCVtx** pleft0 = (GCVtx**)state->ptrLeft->data.ptr;
679    GCVtx** pright0 = (GCVtx**)state->ptrRight->data.ptr;
680    int step = state->left->step;
681    int dstep = (int)(state->dispLeft->step/sizeof(short));
682    int pstep = (int)(state->ptrLeft->step/sizeof(GCVtx*));
683    int aa[] = { alpha, -alpha };
684
685    double t = (double)cvGetTickCount();
686
687    assert( state->left->step == state->right->step &&
688            state->dispLeft->step == state->dispRight->step &&
689            state->ptrLeft->step == state->ptrRight->step );
690    for( k = 0; k < 2; k++ )
691    {
692        ebuf[k].dst = 0;
693        ebuf[k].next = 0;
694        ebuf[k].weight = 0;
695    }
696
697    for( y = 0; y < rows; y++ )
698    {
699        const uchar* left = left0 + step*y;
700        const uchar* right = right0 + step*y;
701        const short* dleft = dleft0 + dstep*y;
702        const short* dright = dright0 + dstep*y;
703        GCVtx** pleft = pleft0 + pstep*y;
704        GCVtx** pright = pright0 + pstep*y;
705        const uchar* lr[] = { left, right };
706        const short* dlr[] = { dleft, dright };
707        GCVtx** plr[] = { pleft, pright };
708
709        for( k = 0; k < 2; k++ )
710        {
711            a = aa[k];
712            for( y1 = y+(y>0); y1 <= y+(y<rows-1); y1++ )
713            {
714                const short* disp = (k == 0 ? dleft0 : dright0) + y1*dstep;
715                GCVtx** ptr = (k == 0 ? pleft0 : pright0) + y1*pstep;
716                for( x = 0; x < cols; x++ )
717                {
718                    GCVtx* v = ptr[x] = &vbuf[nvtx++];
719                    v->first = 0;
720                    v->weight = disp[x] == (short)(OCCLUDED ? -OCCLUSION_PENALTY2 : 0);
721                }
722            }
723        }
724
725        for( x = 0; x < cols; x++ )
726        {
727            d = dleft[x];
728            x1 = x + d;
729            var = pleft[x];
730
731            // (left + x, right + x + d)
732            if( d != alpha && d != OCCLUDED && (unsigned)x1 < (unsigned)cols )
733            {
734                var1 = pright[x1];
735                d1 = dright[x1];
736                if( d == -d1 )
737                {
738                    assert( var1 != 0 );
739                    delta = IS_BLOCKED(alpha, d) ? INFINITY : 0;
740                    //add inter edge
741                    E += icvAddTerm( var, var1,
742                        dtab[icvDataCostFuncGraySubpix( left + x*3, right + x1*3 )],
743                        delta, delta, 0, ebuf, nedges );
744                }
745                else if( IS_BLOCKED(alpha, d) )
746                    E += icvAddTerm( var, var1, 0, INFINITY, 0, 0, ebuf, nedges );
747            }
748
749            // (left + x, right + x + alpha)
750            x1 = x + alpha;
751            if( (unsigned)x1 < (unsigned)cols )
752            {
753                var1 = pright[x1];
754                d1 = dright[x1];
755
756                E0a = IS_BLOCKED(d, alpha) ? INFINITY : 0;
757                Ea0 = IS_BLOCKED(-d1, alpha) ? INFINITY : 0;
758                Eaa = dtab[icvDataCostFuncGraySubpix( left + x*3, right + x1*3 )];
759                E += icvAddTerm( var, var1, 0, E0a, Ea0, Eaa, ebuf, nedges );
760            }
761
762            // smoothness
763            for( k = 0; k < 2; k++ )
764            {
765                GCVtx** p = plr[k];
766                const short* disp = dlr[k];
767                const uchar* img = lr[k] + x*3;
768                int scale;
769                var = p[x];
770                d = disp[x];
771                a = aa[k];
772
773                if( x < cols - 1 )
774                {
775                    var1 = p[x+1];
776                    d1 = disp[x+1];
777                    scale = stabI[img[0] - img[3]];
778                    E0a = icvSmoothnessCostFunc( d, a, maxR, stabR, scale );
779                    Ea0 = icvSmoothnessCostFunc( a, d1, maxR, stabR, scale );
780                    E00 = icvSmoothnessCostFunc( d, d1, maxR, stabR, scale );
781                    E += icvAddTerm( var, var1, E00, E0a, Ea0, 0, ebuf, nedges );
782                }
783
784                if( y < rows - 1 )
785                {
786                    var1 = p[x+pstep];
787                    d1 = disp[x+dstep];
788                    scale = stabI[img[0] - img[step]];
789                    E0a = icvSmoothnessCostFunc( d, a, maxR, stabR, scale );
790                    Ea0 = icvSmoothnessCostFunc( a, d1, maxR, stabR, scale );
791                    E00 = icvSmoothnessCostFunc( d, d1, maxR, stabR, scale );
792                    E += icvAddTerm( var, var1, E00, E0a, Ea0, 0, ebuf, nedges );
793                }
794            }
795
796            // visibility term
797            if( d != OCCLUDED && IS_BLOCKED(alpha, -d))
798            {
799                x1 = x + d;
800                if( (unsigned)x1 < (unsigned)cols )
801                {
802                    if( d != -dleft[x1] )
803                    {
804                        var1 = pleft[x1];
805                        E += icvAddTerm( var, var1, 0, INFINITY, 0, 0, ebuf, nedges );
806                    }
807                }
808            }
809        }
810    }
811
812    t = (double)cvGetTickCount() - t;
813    ebuf[0].weight = ebuf[1].weight = 0;
814    E += icvGCMaxFlow( vbuf, nvtx, ebuf, state2->orphans, state2->maxOrphans );
815
816    if( E < Eprev )
817    {
818        for( y = 0; y < rows; y++ )
819        {
820            short* dleft = dleft0 + dstep*y;
821            short* dright = dright0 + dstep*y;
822            GCVtx** pleft = pleft0 + pstep*y;
823            GCVtx** pright = pright0 + pstep*y;
824            for( x = 0; x < cols; x++ )
825            {
826                GCVtx* var = pleft[x];
827                if( var && var->parent && var->t )
828                    dleft[x] = (short)alpha;
829
830                var = pright[x];
831                if( var && var->parent && var->t )
832                    dright[x] = (short)-alpha;
833            }
834        }
835    }
836
837    return MIN(E, Eprev);
838}
839
840
841CV_IMPL void cvFindStereoCorrespondenceGC( const CvArr* _left, const CvArr* _right,
842    CvArr* _dispLeft, CvArr* _dispRight, CvStereoGCState* state, int useDisparityGuess )
843{
844    CvStereoGCState2 state2;
845    state2.orphans = 0;
846    state2.maxOrphans = 0;
847
848    CV_FUNCNAME( "cvFindStereoCorrespondenceGC" );
849
850    __BEGIN__;
851
852    CvMat lstub, *left = cvGetMat( _left, &lstub );
853    CvMat rstub, *right = cvGetMat( _right, &rstub );
854    CvMat dlstub, *dispLeft = cvGetMat( _dispLeft, &dlstub );
855    CvMat drstub, *dispRight = cvGetMat( _dispRight, &drstub );
856    CvSize size;
857    int iter, i, nZeroExpansions = 0;
858    CvRNG rng = cvRNG(-1);
859    int* disp;
860    CvMat _disp;
861    int64 E;
862
863    CV_ASSERT( state != 0 );
864    CV_ASSERT( CV_ARE_SIZES_EQ(left, right) && CV_ARE_TYPES_EQ(left, right) &&
865               CV_MAT_TYPE(left->type) == CV_8UC1 );
866    CV_ASSERT( !dispLeft ||
867        (CV_ARE_SIZES_EQ(dispLeft, left) && CV_MAT_CN(dispLeft->type) == 1) );
868    CV_ASSERT( !dispRight ||
869        (CV_ARE_SIZES_EQ(dispRight, left) && CV_MAT_CN(dispRight->type) == 1) );
870
871    size = cvGetSize(left);
872    if( !state->left || state->left->width != size.width || state->left->height != size.height )
873    {
874        int pcn = (int)(sizeof(GCVtx*)/sizeof(int));
875        int vcn = (int)(sizeof(GCVtx)/sizeof(int));
876        int ecn = (int)(sizeof(GCEdge)/sizeof(int));
877        cvReleaseMat( &state->left );
878        cvReleaseMat( &state->right );
879        cvReleaseMat( &state->ptrLeft );
880        cvReleaseMat( &state->ptrRight );
881        cvReleaseMat( &state->dispLeft );
882        cvReleaseMat( &state->dispRight );
883
884        state->left = cvCreateMat( size.height, size.width, CV_8UC3 );
885        state->right = cvCreateMat( size.height, size.width, CV_8UC3 );
886        state->dispLeft = cvCreateMat( size.height, size.width, CV_16SC1 );
887        state->dispRight = cvCreateMat( size.height, size.width, CV_16SC1 );
888        state->ptrLeft = cvCreateMat( size.height, size.width, CV_32SC(pcn) );
889        state->ptrRight = cvCreateMat( size.height, size.width, CV_32SC(pcn) );
890        state->vtxBuf = cvCreateMat( 1, size.height*size.width*2, CV_32SC(vcn) );
891        state->edgeBuf = cvCreateMat( 1, size.height*size.width*12 + 16, CV_32SC(ecn) );
892    }
893
894    if( !useDisparityGuess )
895    {
896        cvSet( state->dispLeft, cvScalarAll(OCCLUDED));
897        cvSet( state->dispRight, cvScalarAll(OCCLUDED));
898    }
899    else
900    {
901        CV_ASSERT( dispLeft && dispRight );
902        cvConvert( dispLeft, state->dispLeft );
903        cvConvert( dispRight, state->dispRight );
904    }
905
906    state2.Ithreshold = state->Ithreshold;
907    state2.interactionRadius = state->interactionRadius;
908    state2.lambda = cvRound(state->lambda*DENOMINATOR);
909    state2.lambda1 = cvRound(state->lambda1*DENOMINATOR);
910    state2.lambda2 = cvRound(state->lambda2*DENOMINATOR);
911    state2.K = cvRound(state->K*DENOMINATOR);
912
913    icvInitStereoConstTabs();
914    icvInitGraySubpix( left, right, state->left, state->right );
915    disp = (int*)cvStackAlloc( state->numberOfDisparities*sizeof(disp[0]) );
916    _disp = cvMat( 1, state->numberOfDisparities, CV_32S, disp );
917    cvRange( &_disp, state->minDisparity, state->minDisparity + state->numberOfDisparities );
918    cvRandShuffle( &_disp, &rng );
919
920    if( state2.lambda < 0 && (state2.K < 0 || state2.lambda1 < 0 || state2.lambda2 < 0) )
921    {
922        float L = icvComputeK(state)*0.2f;
923        state2.lambda = cvRound(L*DENOMINATOR);
924    }
925
926    if( state2.K < 0 )
927        state2.K = state2.lambda*5;
928    if( state2.lambda1 < 0 )
929        state2.lambda1 = state2.lambda*3;
930    if( state2.lambda2 < 0 )
931        state2.lambda2 = state2.lambda;
932
933    icvInitStereoTabs( &state2 );
934
935    E = icvComputeEnergy( state, &state2, !useDisparityGuess );
936    for( iter = 0; iter < state->maxIters; iter++ )
937    {
938        for( i = 0; i < state->numberOfDisparities; i++ )
939        {
940            int alpha = disp[i];
941            int64 Enew = icvAlphaExpand( E, -alpha, state, &state2 );
942            if( Enew < E )
943            {
944                nZeroExpansions = 0;
945                E = Enew;
946            }
947            else if( ++nZeroExpansions >= state->numberOfDisparities )
948                break;
949        }
950    }
951
952    if( dispLeft )
953        cvConvert( state->dispLeft, dispLeft );
954    if( dispRight )
955        cvConvert( state->dispRight, dispRight );
956
957    __END__;
958
959    cvFree( &state2.orphans );
960}
961