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#define PATH_TO_E       1
45#define PATH_TO_SE      2
46#define PATH_TO_S       3
47
48#define K_S         2
49#define E_S         2
50#define C_S         .01
51#define K_Z         5000
52#define K_NM        50000
53#define K_B         40
54#define NULL_EDGE   0.001f
55#define inf         DBL_MAX
56
57typedef struct __CvWork
58{
59    double w_east;
60    double w_southeast;
61    double w_south;
62    char path_e;
63    char path_se;
64    char path_s;
65}_CvWork;
66
67
68double _cvBendingWork(  CvPoint2D32f* B0,
69                        CvPoint2D32f* F0,
70                        CvPoint2D32f* B1,
71                        CvPoint2D32f* F1/*,
72                        CvPoint* K */);
73
74double _cvStretchingWork(CvPoint2D32f* P1,
75                         CvPoint2D32f* P2);
76
77void _cvWorkEast     (int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2);
78void _cvWorkSouthEast(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2);
79void _cvWorkSouth    (int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2);
80
81static CvPoint2D32f null_edge = {0,0};
82
83double _cvStretchingWork(CvPoint2D32f* P1,
84                         CvPoint2D32f* P2)
85{
86    double L1,L2, L_min, dL;
87
88    L1 = sqrt( (double)P1->x*P1->x + P1->y*P1->y);
89    L2 = sqrt( (double)P2->x*P2->x + P2->y*P2->y);
90
91    L_min = MIN(L1, L2);
92    dL = fabs( L1 - L2 );
93
94    return K_S * pow( dL, E_S ) / ( L_min + C_S*dL );
95}
96
97
98////////////////////////////////////////////////////////////////////////////////////
99double _cvBendingWork(  CvPoint2D32f* B0,
100                        CvPoint2D32f* F0,
101                        CvPoint2D32f* B1,
102                        CvPoint2D32f* F1/*,
103                        CvPoint* K*/)
104{
105    CvPoint2D32f Q( CvPoint2D32f q0, CvPoint2D32f q1, CvPoint2D32f q2, double t );
106    double angle( CvPoint2D32f A, CvPoint2D32f B );
107
108    CvPoint2D32f Q0, Q1, Q2;
109    CvPoint2D32f Q1_nm = { 0, 0 }, Q2_nm = { 0, 0 };
110    double d0, d1, d2, des, t_zero;
111    double k_zero, k_nonmon;
112    CvPoint2D32f center;
113    double check01, check02;
114    char check_origin;
115    double d_angle, d_nm_angle;
116/*
117    if( (B0->x==0) && (B0->y==0) )
118    {
119        if( (F0->x==0) && (F0->y==0) )
120        {
121            B1->x = -B1->x;
122            B1->y = -B1->y;
123
124            d_angle = acos( (B1->x*F1->x + B1->y*F1->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(F1->x*F1->x + F1->y*F1->y) ) );
125            d_angle = CV_PI - d_angle;
126
127            B1->x = -B1->x;
128            B1->y = -B1->y;
129
130            //return d_angle*K_B;
131            return 100;
132        }
133        K->x = -K->x;
134        K->y = -K->y;
135        B1->x = -B1->x;
136        B1->y = -B1->y;
137
138        d_angle = acos( (B1->x*F1->x + B1->y*F1->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(F1->x*F1->x + F1->y*F1->y) ) );
139        d_angle = d_angle - acos( (F0->x*K->x + F0->y*K->y)/sqrt( (F0->x*F0->x + F0->y*F0->y)*(K->x*K->x + K->y*K->y) ) );
140        d_angle = d_angle - CV_PI*0.5;
141        d_angle = fabs(d_angle);
142
143
144        K->x = -K->x;
145        K->y = -K->y;
146        B1->x = -B1->x;
147        B1->y = -B1->y;
148
149        //return d_angle*K_B;
150        return 100;
151    }
152
153
154    if( (F0->x==0) && (F0->y==0) )
155        {
156            K->x = -K->x;
157            K->y = -K->y;
158            B1->x = -B1->x;
159            B1->y = -B1->y;
160
161            d_angle = acos( (B1->x*F1->x + B1->y*F1->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(F1->x*F1->x + F1->y*F1->y) ) );
162            d_angle = d_angle - acos( (B0->x*K->x + B0->y*K->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(K->x*K->x + K->y*K->y) ) );
163            d_angle = d_angle - CV_PI*0.5;
164            d_angle = fabs(d_angle);
165
166            K->x = -K->x;
167            K->y = -K->y;
168            B1->x = -B1->x;
169            B1->y = -B1->y;
170
171            //return d_angle*K_B;
172            return 100;
173        }
174///////////////
175
176    if( (B1->x==0) && (B1->y==0) )
177    {
178        if( (F1->x==0) && (F1->y==0) )
179        {
180            B0->x = -B0->x;
181            B0->y = -B0->y;
182
183            d_angle = acos( (B0->x*F0->x + B0->y*F0->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(F0->x*F0->x + F0->y*F0->y) ) );
184            d_angle = CV_PI - d_angle;
185
186            B0->x = -B0->x;
187            B0->y = -B0->y;
188
189            //return d_angle*K_B;
190            return 100;
191        }
192        K->x = -K->x;
193        K->y = -K->y;
194        B0->x = -B0->x;
195        B0->y = -B0->y;
196
197        d_angle = acos( (B0->x*F0->x + B0->y*F0->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(F0->x*F0->x + F0->y*F0->y) ) );
198        d_angle = d_angle - acos( (F1->x*K->x + F1->y*K->y)/sqrt( (F1->x*F1->x + F1->y*F1->y)*(K->x*K->x + K->y*K->y) ) );
199        d_angle = d_angle - CV_PI*0.5;
200        d_angle = fabs(d_angle);
201
202        K->x = -K->x;
203        K->y = -K->y;
204        B0->x = -B0->x;
205        B0->y = -B0->y;
206
207        //return d_angle*K_B;
208        return 100;
209    }
210
211
212    if( (F1->x==0) && (F1->y==0) )
213        {
214            K->x = -K->x;
215            K->y = -K->y;
216            B0->x = -B0->x;
217            B0->y = -B0->y;
218
219            d_angle = acos( (B0->x*F0->x + B0->y*F0->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(F0->x*F0->x + F0->y*F0->y) ) );
220            d_angle = d_angle - acos( (B1->x*K->x + B1->y*K->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(K->x*K->x + K->y*K->y) ) );
221            d_angle = d_angle - CV_PI*0.5;
222            d_angle = fabs(d_angle);
223
224            K->x  = -K->x;
225            K->y  = -K->y;
226            B0->x = -B0->x;
227            B0->y = -B0->y;
228
229            //return d_angle*K_B;
230            return 100;
231        }
232
233*/
234
235/*
236    B0->x = -B0->x;
237    B0->y = -B0->y;
238    B1->x = -B1->x;
239    B1->y = -B1->y;
240*/
241    Q0.x = F0->x * (-B0->x) + F0->y * (-B0->y);
242    Q0.y = F0->x * (-B0->y) - F0->y * (-B0->x);
243
244    Q1.x = 0.5f*( (F1->x * (-B0->x) + F1->y * (-B0->y)) + (F0->x * (-B1->x) + F0->y * (-B1->y)) );
245    Q1.y = 0.5f*( (F1->x * (-B0->y) - F1->y * (-B0->x)) + (F0->x * (-B1->y) - F0->y * (-B1->x)) );
246
247    Q2.x = F1->x * (-B1->x) + F1->y * (-B1->y);
248    Q2.y = F1->x * (-B1->y) - F1->y * (-B1->x);
249
250    d0 = Q0.x * Q1.y - Q0.y * Q1.x;
251    d1 = 0.5f*(Q0.x * Q2.y - Q0.y * Q2.x);
252    d2 = Q1.x * Q2.y - Q1.y * Q2.x;
253
254    // Check angles goes to zero
255    des = Q1.y*Q1.y - Q0.y*Q2.y;
256
257    k_zero = 0;
258
259    if( des >= 0 )
260    {
261        t_zero = ( Q0.y - Q1.y + sqrt(des) )/( Q0.y - 2*Q1.y + Q2.y );
262
263        if( (0 < t_zero) && (t_zero < 1) && ( Q(Q0, Q1, Q2, t_zero).x > 0 ) )
264        {
265            k_zero = inf;
266        }
267
268        t_zero = ( Q0.y - Q1.y - sqrt(des) )/( Q0.y - 2*Q1.y + Q2.y );
269
270        if( (0 < t_zero) && (t_zero < 1) && ( Q(Q0, Q1, Q2, t_zero).x > 0 ) )
271        {
272            k_zero = inf;
273        }
274    }
275
276    // Check nonmonotonic
277    des = d1*d1 - d0*d2;
278
279    k_nonmon = 0;
280
281    if( des >= 0 )
282    {
283        t_zero = ( d0 - d1 - sqrt(des) )/( d0 - 2*d1 + d2 );
284
285        if( (0 < t_zero) && (t_zero < 1) )
286        {
287            k_nonmon = 1;
288            Q1_nm = Q(Q0, Q1, Q2, t_zero);
289        }
290
291        t_zero = ( d0 - d1 + sqrt(des) )/( d0 - 2*d1 + d2 );
292
293        if( (0 < t_zero) && (t_zero < 1) )
294        {
295            k_nonmon += 2;
296            Q2_nm = Q(Q0, Q1, Q2, t_zero);
297        }
298    }
299
300    // Finde origin lie in Q0Q1Q2
301    check_origin = 1;
302
303    center.x = (Q0.x + Q1.x + Q2.x)/3;
304    center.y = (Q0.y + Q1.y + Q2.y)/3;
305
306    check01 = (center.x - Q0.x)*(Q1.y - Q0.y) + (center.y - Q0.y)*(Q1.x - Q0.x);
307    check02 = (-Q0.x)*(Q1.y - Q0.y) + (-Q0.y)*(Q1.x - Q0.x);
308    if( check01*check02 > 0 )
309    {
310        check01 = (center.x - Q1.x)*(Q2.y - Q1.y) + (center.y - Q1.y)*(Q2.x - Q1.x);
311        check02 = (-Q1.x)*(Q2.y - Q1.y) + (-Q1.y)*(Q2.x - Q1.x);
312        if( check01*check02 > 0 )
313        {
314            check01 = (center.x - Q2.x)*(Q0.y - Q2.y) + (center.y - Q2.y)*(Q0.x - Q2.x);
315            check02 = (-Q2.x)*(Q0.y - Q2.y) + (-Q2.y)*(Q0.x - Q2.x);
316            if( check01*check02 > 0 )
317            {
318                check_origin = 0;
319            }
320        }
321    }
322
323    // Calculate angle
324    d_nm_angle = 0;
325    d_angle = angle(Q0,Q2);
326    if( k_nonmon == 0 )
327    {
328        if( check_origin == 0 )
329        {
330        }
331        else
332        {
333            d_angle = 2*CV_PI - d_angle;
334        }
335    }
336    else
337    {
338        if( k_nonmon == 1 )
339        {
340            d_nm_angle = angle(Q0,Q1_nm);
341            if(d_nm_angle > d_angle)
342            {
343                d_nm_angle = d_nm_angle - d_angle;
344            }
345        }
346
347        if( k_nonmon == 2 )
348        {
349            d_nm_angle = angle(Q0,Q2_nm);
350            if(d_nm_angle > d_angle)
351            {
352                d_nm_angle = d_nm_angle - d_angle;
353            }
354        }
355
356        if( k_nonmon == 3 )
357        {
358            d_nm_angle = angle(Q0,Q1_nm);
359            if(d_nm_angle > d_angle)
360            {
361                d_nm_angle = d_nm_angle - d_angle;
362                d_nm_angle = d_nm_angle + angle(Q0, Q2_nm);
363            }
364            else
365            {
366                d_nm_angle = d_nm_angle + angle(Q2,Q2_nm);
367            }
368        }
369    }
370/*
371    B0->x = -B0->x;
372    B0->y = -B0->y;
373    B1->x = -B1->x;
374    B1->y = -B1->y;
375*/
376    return d_angle*K_B + d_nm_angle*K_NM + k_zero*K_Z;
377    //return 0;
378}
379
380
381/////////////////////////////////////////////////////////////////////////////////
382void _cvWorkEast(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2)
383{
384    double w1,w2;
385    CvPoint2D32f small_edge;
386
387    //W[i,j].w_east
388    w1 = W[i-1][j].w_east /*+ _cvBendingWork(   &edges1[i-2],
389                                            &edges1[i-1],
390                                            &null_edge ,
391                                            &null_edge,
392                                            NULL)*/;
393
394    small_edge.x = NULL_EDGE*edges1[i-1].x;
395    small_edge.y = NULL_EDGE*edges1[i-1].y;
396
397    w2 = W[i-1][j].w_southeast + _cvBendingWork(&edges1[i-2],
398                                                &edges1[i-1],
399                                                &edges2[j-1],
400                                                /*&null_edge*/&small_edge/*,
401                                                &edges2[j]*/);
402
403    if(w1<w2)
404    {
405        W[i][j].w_east = w1 + _cvStretchingWork( &edges1[i-1], &null_edge );
406        W[i][j].path_e = PATH_TO_E;
407    }
408    else
409    {
410        W[i][j].w_east = w2 + _cvStretchingWork( &edges1[i-1], &null_edge );
411        W[i][j].path_e = PATH_TO_SE;
412    }
413}
414
415
416
417
418
419////////////////////////////////////////////////////////////////////////////////////
420void _cvWorkSouthEast(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2)
421{
422    double w1,w2,w3;
423    CvPoint2D32f small_edge;
424
425    //W[i,j].w_southeast
426    small_edge.x = NULL_EDGE*edges1[i-2].x;
427    small_edge.y = NULL_EDGE*edges1[i-2].y;
428
429    w1 = W[i-1][j-1].w_east + _cvBendingWork(&edges1[i-2],
430                                            &edges1[i-1],
431                                            /*&null_edge*/&small_edge,
432                                            &edges2[j-1]/*,
433                                            &edges2[j-2]*/);
434
435    w2 = W[i-1][j-1].w_southeast + _cvBendingWork(  &edges1[i-2],
436                                                    &edges1[i-1],
437                                                    &edges2[j-2],
438                                                    &edges2[j-1]/*,
439                                                    NULL*/);
440
441    small_edge.x = NULL_EDGE*edges2[j-2].x;
442    small_edge.y = NULL_EDGE*edges2[j-2].y;
443
444    w3 = W[i-1][j-1].w_south + _cvBendingWork(  /*&null_edge*/&small_edge,
445                                                &edges1[i-1],
446                                                &edges2[j-2],
447                                                &edges2[j-1]/*,
448                                                &edges1[i-2]*/);
449
450    if( w1<w2 )
451    {
452        if(w1<w3)
453        {
454            W[i][j].w_southeast = w1 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
455            W[i][j].path_se = PATH_TO_E;
456        }
457        else
458        {
459            W[i][j].w_southeast = w3 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
460            W[i][j].path_se = 3;
461        }
462    }
463    else
464    {
465        if( w2<w3)
466        {
467            W[i][j].w_southeast = w2 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
468            W[i][j].path_se = PATH_TO_SE;
469        }
470        else
471        {
472            W[i][j].w_southeast = w3 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
473            W[i][j].path_se = 3;
474        }
475    }
476}
477
478
479//////////////////////////////////////////////////////////////////////////////////////
480void _cvWorkSouth(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2)
481{
482    double w1,w2;
483    CvPoint2D32f small_edge;
484
485    //W[i,j].w_south
486
487    small_edge.x = NULL_EDGE*edges2[j-1].x;
488    small_edge.y = NULL_EDGE*edges2[j-1].y;
489
490    w1 = W[i][j-1].w_southeast + _cvBendingWork(&edges1[i-1],
491                                                /*&null_edge*/&small_edge,
492                                                &edges2[j-2],
493                                                &edges2[j-1]/*,
494                                                &edges1[i]*/);
495
496    w2 = W[i][j-1].w_south /*+ _cvBendingWork(  &null_edge ,
497                                            &null_edge,
498                                            &edges2[j-2],
499                                            &edges2[j-1],
500                                            NULL)*/;
501
502    if( w1<w2 )
503    {
504        W[i][j].w_south = w1 + _cvStretchingWork( &null_edge, &edges2[j-1] );
505        W[i][j].path_s = PATH_TO_SE;
506    }
507    else
508    {
509        W[i][j].w_south = w2 + _cvStretchingWork( &null_edge, &edges2[j-1] );
510        W[i][j].path_s = 3;
511    }
512}
513
514//===================================================
515CvPoint2D32f Q(CvPoint2D32f q0,CvPoint2D32f q1,CvPoint2D32f q2,double t)
516{
517    CvPoint2D32f q;
518
519    q.x = (float)(q0.x*(1-t)*(1-t) + 2*q1.x*t*(1-t) + q2.x*t*t);
520    q.y = (float)(q0.y*(1-t)*(1-t) + 2*q1.y*t*(1-t) + q2.y*t*t);
521
522    return q;
523}
524
525double angle(CvPoint2D32f A, CvPoint2D32f B)
526{
527    return acos( (A.x*B.x + A.y*B.y)/sqrt( (double)(A.x*A.x + A.y*A.y)*(B.x*B.x + B.y*B.y) ) );
528}
529
530/***************************************************************************************\
531*
532*   This function compute intermediate polygon between contour1 and contour2
533*
534*   Correspondence between points of contours specify by corr
535*
536*   param = [0,1];  0 correspondence to contour1, 1 - contour2
537*
538\***************************************************************************************/
539CvSeq* icvBlendContours(CvSeq* contour1,
540                        CvSeq* contour2,
541                        CvSeq* corr,
542                        double param,
543                        CvMemStorage* storage)
544{
545    int j;
546
547    CvSeqWriter writer01;
548    CvSeqReader reader01;
549
550    int Ni,Nj;              // size of contours
551    int i;                  // counter
552
553    CvPoint* point1;        // array of first contour point
554    CvPoint* point2;        // array of second contour point
555
556    CvPoint point_output;   // intermediate storage of ouput point
557
558    int corr_point;
559
560    // Create output sequence.
561    CvSeq* output = cvCreateSeq(0,
562                                sizeof(CvSeq),
563                                sizeof(CvPoint),
564                                storage );
565
566    // Find size of contours.
567    Ni = contour1->total + 1;
568    Nj = contour2->total + 1;
569
570    point1 = (CvPoint* )malloc( Ni*sizeof(CvPoint) );
571    point2 = (CvPoint* )malloc( Nj*sizeof(CvPoint) );
572
573    // Initialize arrays of point
574    cvCvtSeqToArray( contour1, point1, CV_WHOLE_SEQ );
575    cvCvtSeqToArray( contour2, point2, CV_WHOLE_SEQ );
576
577    // First and last point mast be equal.
578    point1[Ni-1] = point1[0];
579    point2[Nj-1] = point2[0];
580
581    // Initializes process of writing to sequence.
582    cvStartAppendToSeq( output, &writer01);
583
584    i = Ni-1; //correspondence to points of contour1
585    for( ; corr; corr = corr->h_next )
586    {
587        //Initializes process of sequential reading from sequence
588        cvStartReadSeq( corr, &reader01, 0 );
589
590        for(j=0; j < corr->total; j++)
591        {
592            // Read element from sequence.
593            CV_READ_SEQ_ELEM( corr_point, reader01 );
594
595            // Compute point of intermediate polygon.
596            point_output.x = cvRound(point1[i].x + param*( point2[corr_point].x - point1[i].x ));
597            point_output.y = cvRound(point1[i].y + param*( point2[corr_point].y - point1[i].y ));
598
599            // Write element to sequence.
600            CV_WRITE_SEQ_ELEM( point_output, writer01 );
601        }
602        i--;
603    }
604    // Updates sequence header.
605    cvFlushSeqWriter( &writer01 );
606
607    return output;
608}
609
610/**************************************************************************************************
611*
612*
613*
614*
615*
616*
617*
618*
619*
620*
621**************************************************************************************************/
622
623
624void icvCalcContoursCorrespondence(CvSeq* contour1,
625                                   CvSeq* contour2,
626                                   CvSeq** corr,
627                                   CvMemStorage* storage)
628{
629    int i,j;                    // counter of cycles
630    int Ni,Nj;                  // size of contours
631    _CvWork** W;                // graph for search minimum of work
632
633    CvPoint* point1;            // array of first contour point
634    CvPoint* point2;            // array of second contour point
635    CvPoint2D32f* edges1;       // array of first contour edge
636    CvPoint2D32f* edges2;       // array of second contour edge
637
638    //CvPoint null_edge = {0,0};    //
639    CvPoint2D32f small_edge;
640    //double inf;                   // infinity
641
642    CvSeq* corr01;
643    CvSeqWriter writer;
644
645    char path;                  //
646
647    // Find size of contours
648    Ni = contour1->total + 1;
649    Nj = contour2->total + 1;
650
651    // Create arrays
652    W = (_CvWork**)malloc(sizeof(_CvWork*)*Ni);
653    for(i=0; i<Ni; i++)
654    {
655        W[i] = (_CvWork*)malloc(sizeof(_CvWork)*Nj);
656    }
657
658    point1 = (CvPoint* )malloc( Ni*sizeof(CvPoint) );
659    point2 = (CvPoint* )malloc( Nj*sizeof(CvPoint) );
660    edges1 = (CvPoint2D32f* )malloc( (Ni-1)*sizeof(CvPoint2D32f) );
661    edges2 = (CvPoint2D32f* )malloc( (Nj-1)*sizeof(CvPoint2D32f) );
662
663    // Initialize arrays of point
664    cvCvtSeqToArray( contour1, point1, CV_WHOLE_SEQ );
665    cvCvtSeqToArray( contour2, point2, CV_WHOLE_SEQ );
666
667    point1[Ni-1] = point1[0];
668    point2[Nj-1] = point2[0];
669
670    for(i=0;i<Ni-1;i++)
671    {
672        edges1[i].x = (float)( point1[i+1].x - point1[i].x );
673        edges1[i].y = (float)( point1[i+1].y - point1[i].y );
674    };
675
676    for(i=0;i<Nj-1;i++)
677    {
678        edges2[i].x = (float)( point2[i+1].x - point2[i].x );
679        edges2[i].y = (float)( point2[i+1].y - point2[i].y );
680    };
681
682    // Find infinity constant
683    //inf=1;
684/////////////
685
686//Find min path in graph
687
688/////////////
689    W[0][0].w_east      = 0;
690    W[0][0].w_south     = 0;
691    W[0][0].w_southeast = 0;
692
693    W[1][1].w_southeast = _cvStretchingWork( &edges1[0], &edges2[0] );
694    W[1][1].w_east = inf;
695    W[1][1].w_south = inf;
696    W[1][1].path_se = PATH_TO_SE;
697
698    W[0][1].w_south =  _cvStretchingWork( &null_edge, &edges2[0] );
699    W[0][1].path_s = 3;
700    W[1][0].w_east =  _cvStretchingWork( &edges2[0], &null_edge );
701    W[1][0].path_e = PATH_TO_E;
702
703    for( i=1; i<Ni; i++ )
704    {
705        W[i][0].w_south     = inf;
706        W[i][0].w_southeast = inf;
707    }
708
709    for(j=1; j<Nj; j++)
710    {
711        W[0][j].w_east      = inf;
712        W[0][j].w_southeast = inf;
713    }
714
715    for(i=2; i<Ni; i++)
716    {
717        j=0;/////////
718        W[i][j].w_east = W[i-1][j].w_east;
719        W[i][j].w_east = W[i][j].w_east /*+
720            _cvBendingWork( &edges1[i-2], &edges1[i-1], &null_edge, &null_edge, NULL )*/;
721        W[i][j].w_east = W[i][j].w_east + _cvStretchingWork( &edges2[i-1], &null_edge );
722        W[i][j].path_e = PATH_TO_E;
723
724        j=1;//////////
725        W[i][j].w_south = inf;
726
727        _cvWorkEast (i, j, W, edges1, edges2);
728
729        W[i][j].w_southeast = W[i-1][j-1].w_east;
730        W[i][j].w_southeast = W[i][j].w_southeast + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
731
732        small_edge.x = NULL_EDGE*edges1[i-2].x;
733        small_edge.y = NULL_EDGE*edges1[i-2].y;
734
735        W[i][j].w_southeast = W[i][j].w_southeast +
736            _cvBendingWork( &edges1[i-2], &edges1[i-1], /*&null_edge*/&small_edge, &edges2[j-1]/*, &edges2[Nj-2]*/);
737
738        W[i][j].path_se = PATH_TO_E;
739    }
740
741    for(j=2; j<Nj; j++)
742    {
743        i=0;//////////
744        W[i][j].w_south = W[i][j-1].w_south;
745        W[i][j].w_south = W[i][j].w_south + _cvStretchingWork( &null_edge, &edges2[j-1] );
746        W[i][j].w_south = W[i][j].w_south /*+
747            _cvBendingWork( &null_edge, &null_edge, &edges2[j-2], &edges2[j-1], NULL )*/;
748        W[i][j].path_s = 3;
749
750        i=1;///////////
751        W[i][j].w_east= inf;
752
753        _cvWorkSouth(i, j, W, edges1, edges2);
754
755        W[i][j].w_southeast = W[i-1][j-1].w_south;
756        W[i][j].w_southeast = W[i][j].w_southeast + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
757
758        small_edge.x = NULL_EDGE*edges2[j-2].x;
759        small_edge.y = NULL_EDGE*edges2[j-2].y;
760
761        W[i][j].w_southeast = W[i][j].w_southeast +
762            _cvBendingWork( /*&null_edge*/&small_edge, &edges1[i-1], &edges2[j-2], &edges2[j-1]/*, &edges1[Ni-2]*/);
763        W[i][j].path_se = 3;
764    }
765
766    for(i=2; i<Ni; i++)
767        for(j=2; j<Nj; j++)
768        {
769            _cvWorkEast     (i, j, W, edges1, edges2);
770            _cvWorkSouthEast(i, j, W, edges1, edges2);
771            _cvWorkSouth    (i, j, W, edges1, edges2);
772        }
773
774    i=Ni-1;j=Nj-1;
775
776    *corr = cvCreateSeq(0,
777                        sizeof(CvSeq),
778                        sizeof(int),
779                        storage );
780
781    corr01 = *corr;
782    cvStartAppendToSeq( corr01, &writer );
783    if( W[i][j].w_east > W[i][j].w_southeast )
784        {
785            if( W[i][j].w_southeast > W[i][j].w_south )
786            {
787                path = 3;
788            }
789            else
790            {
791                path = PATH_TO_SE;
792            }
793        }
794        else
795        {
796            if( W[i][j].w_east < W[i][j].w_south )
797            {
798                path = PATH_TO_E;
799            }
800            else
801            {
802                path = 3;
803            }
804        }
805    do
806    {
807        CV_WRITE_SEQ_ELEM( j, writer );
808
809        switch( path )
810        {
811        case PATH_TO_E:
812            path = W[i][j].path_e;
813            i--;
814            cvFlushSeqWriter( &writer );
815            corr01->h_next = cvCreateSeq(   0,
816                                            sizeof(CvSeq),
817                                            sizeof(int),
818                                            storage );
819            corr01 = corr01->h_next;
820            cvStartAppendToSeq( corr01, &writer );
821            break;
822
823        case PATH_TO_SE:
824            path = W[i][j].path_se;
825            j--; i--;
826            cvFlushSeqWriter( &writer );
827            corr01->h_next = cvCreateSeq(   0,
828                                            sizeof(CvSeq),
829                                            sizeof(int),
830                                            storage );
831            corr01 = corr01->h_next;
832            cvStartAppendToSeq( corr01, &writer );
833            break;
834
835        case 3:
836            path = W[i][j].path_s;
837            j--;
838            break;
839        }
840
841    } while( (i>=0) && (j>=0) );
842    cvFlushSeqWriter( &writer );
843
844    // Free memory
845    for(i=1;i<Ni;i++)
846    {
847        free(W[i]);
848    }
849    free(W);
850    free(point1);
851    free(point2);
852    free(edges1);
853    free(edges2);
854}
855
856