Update the trunk to the OpenCV's CVS (2008-07-14)
[opencv] / cvaux / src / vs / testseq.cpp
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 //
12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
13 // Third party copyrights are property of their respective owners.
14 //
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
17 //
18 //   * Redistribution's of source code must retain the above copyright notice,
19 //     this list of conditions and the following disclaimer.
20 //
21 //   * Redistribution's in binary form must reproduce the above copyright notice,
22 //     this list of conditions and the following disclaimer in the documentation
23 //     and/or other materials provided with the distribution.
24 //
25 //   * The name of Intel Corporation may not be used to endorse or promote products
26 //     derived from this software without specific prior written permission.
27 //
28 // This software is provided by the copyright holders and contributors "as is" and
29 // any express or implied warranties, including, but not limited to, the implied
30 // warranties of merchantability and fitness for a particular purpose are disclaimed.
31 // In no event shall the Intel Corporation or contributors be liable for any direct,
32 // indirect, incidental, special, exemplary, or consequential damages
33 // (including, but not limited to, procurement of substitute goods or services;
34 // loss of use, data, or profits; or business interruption) however caused
35 // and on any theory of liability, whether in contract, strict liability,
36 // or tort (including negligence or otherwise) arising in any way out of
37 // the use of this software, even if advised of the possibility of such damage.
38 //
39 //M*/
40
41 /*
42 This file contain implementation of virtual interface of CvTestSeq
43 */
44
45 #include "_cvaux.h" /* virtual interface if CvTestSeq */
46
47 #define FG_BG_THRESHOLD 3
48
49 #define SRC_TYPE_AVI 1
50 #define SRC_TYPE_IMAGE 0
51
52 /* Transformation structure: */
53 typedef struct CvTSTrans
54 {
55     float           T[6]; /* geometry transformation */
56     CvPoint2D32f    Shift;
57     CvPoint2D32f    Scale;
58     float           I;
59     float           C;
60     float           GN; /* standart deviation of added gaussian noise */
61     float           NoiseAmp; /* amplifier of noise power */
62     float           angle;
63 } CvTSTrans;
64
65 void SET_TRANS_0(CvTSTrans *pT)
66 {
67     memset(pT,0,sizeof(CvTSTrans));
68     pT->C = 1;
69     pT->Scale.x = 1;
70     pT->Scale.y = 1;
71     pT->T[4] = pT->T[0] = 1;
72     pT->NoiseAmp = 1;
73 }
74
75 /* === Some definitions and functions for transformation update: ===*/
76 #define P_ANGLE 0
77 #define P_S     1
78 #define P_SX    2
79 #define P_SY    3
80 #define P_DX    4
81 #define P_DY    5
82 #define P_I     6
83 #define P_C     7
84 #define P_GN    8
85 #define P_NAmp  9
86 static char*   param_name[] =    {"angle","s","sx","sy","dx","dy","I","C","GN","NoiseAmp", NULL};
87 static float   param_defval[] =  { 0,      1,  1,   1,   0,   0,   0,  1,  0,   1};
88 static void icvUpdateTrans(CvTSTrans* pTrans, int param, double val, float MaxX, float MaxY)
89 {
90     assert(pTrans);
91     if(param==P_ANGLE)
92     {
93
94         double  C = cos(3.1415926535897932384626433832795*val/180.0);
95         double  S = sin(3.1415926535897932384626433832795*val/180.0);
96         float*  T = pTrans->T;
97         double  TR[6];
98         int     i;
99         pTrans->angle = (float)(pTrans->angle + val);
100         TR[0] = C*T[0]-S*T[3];
101         TR[1] = C*T[1]-S*T[4];
102         TR[2] = C*T[2]-S*T[5];
103         TR[3] = S*T[0]+C*T[3];
104         TR[4] = S*T[1]+C*T[4];
105         TR[5] = S*T[2]+C*T[5];
106         for(i=0;i<6;++i)T[i]=(float)TR[i];
107     }
108
109     if(param==P_S)
110     {
111         int i;
112         for(i=0;i<6;++i)pTrans->T[i] = (float)(pTrans->T[i]*val);
113         pTrans->Scale.x = (float)(pTrans->Scale.x *val);
114         pTrans->Scale.y = (float)(pTrans->Scale.y *val);
115         pTrans->Shift.x = (float)(pTrans->Shift.x *val);
116         pTrans->Shift.y = (float)(pTrans->Shift.y *val);
117     }
118
119     if(param==P_SX)
120     {
121         int i;
122         for(i=0;i<3;++i)pTrans->T[i] = (float)(pTrans->T[i]*val);
123         pTrans->Scale.x = (float)(pTrans->Scale.x*val);
124         pTrans->Shift.x = (float)(pTrans->Shift.x*val);
125     }
126
127     if(param==P_SY)
128     {
129         int i;
130         for(i=0;i<3;++i)pTrans->T[i+3] = (float)(pTrans->T[i+3]*val);
131         pTrans->Scale.y = (float)(pTrans->Scale.y *val);
132         pTrans->Shift.y = (float)(pTrans->Shift.y *val);
133     }
134
135     if(param==P_DX)
136     {
137         pTrans->Shift.x = (float)(pTrans->Shift.x +val);
138         pTrans->T[2] = (float)(pTrans->T[2] +val*MaxX);
139     }
140
141     if(param==P_DY)
142     {
143         pTrans->Shift.y = (float)(pTrans->Shift.y +val);
144         pTrans->T[5] = (float)(pTrans->T[5] +val*MaxY);
145     }
146
147     if(param==P_C)
148     {
149         pTrans->C = (float)(pTrans->C *val);
150         pTrans->I = (float)(pTrans->I *val);
151     }
152
153     if(param==P_I) pTrans->I = (float)(pTrans->I +val);
154
155     if(param==P_GN)
156     {
157         pTrans->GN = (float)sqrt(val*val+pTrans->GN*pTrans->GN);
158     }
159
160     if(param==P_NAmp) pTrans->NoiseAmp = (float)(pTrans->NoiseAmp *val);
161 }   /* icvUpdateTrans */
162
163 /* === END some defenitions and function for transformation update ===*/
164
165 typedef struct CvTestSeqElem
166 {
167     const char*     pObjName;
168     const char*     pFileName;
169     int             type; /* video or image */
170     CvPoint2D32f*   pPos; /* positions of object in sequence */
171     int             PosNum;
172     CvPoint2D32f*   pSize; /* sizes of object in sequence */
173     int             SizeNum;
174     CvTSTrans*      pTrans; /* transforation of image in sequence */
175     int             TransNum;
176     int             ShiftByPos;
177     CvPoint2D32f    ShiftBegin;
178     CvPoint2D32f    ShiftEnd;
179     int             FrameBegin;
180     int             FrameNum;
181     IplImage*       pImg;
182     IplImage*       pImgMask;
183     void*           pAVI;
184     //CvCapture*      pAVI;
185     int             AVILen;
186     int             BG; /* flag is it background (1) or foreground (0) */
187     int             Mask; /* flag is it foreground mask (1) or usual video (0) */
188     CvTestSeqElem   *next;
189     int             noise_type;
190     CvRandState     rnd_state;
191     int             ObjID;
192 } CvTestSeqElem;
193
194 /* Test seq main structure: */
195 typedef struct CvTestSeq_
196 {
197     int             ID;
198     CvFileStorage*  pFileStorage;
199     CvTestSeqElem*  pElemList;
200     int             ListNum;
201     IplImage*       pImg;
202     IplImage*       pImgMask;
203     int             CurFrame;
204     int             FrameNum;
205     int             noise_type;
206     double          noise_ampl;
207     float           IVar_DI;
208     float           IVar_MinI;
209     float           IVar_MaxI;
210     float           IVar_CurDI;
211     float           IVar_CurI;
212     int             ObjNum;
213
214 } CvTestSeq_;
215
216
217 CvSize cvTestSeqGetImageSize(CvTestSeq* pTestSeq){return cvSize(((CvTestSeq_*)(pTestSeq))->pImg->width,((CvTestSeq_*)(pTestSeq))->pImg->height);}
218 int cvTestSeqFrameNum(CvTestSeq* pTestSeq){return ((CvTestSeq_*)(pTestSeq))->FrameNum;}
219
220 static void icvTestSeqCreateMask(IplImage* pImg,IplImage* pImgMask, int threshold)
221 {
222     if(pImg->nChannels > 1)
223     {
224         cvCvtColor( pImg,pImgMask,CV_BGR2GRAY);
225         cvThreshold(pImgMask,pImgMask,threshold,255,CV_THRESH_BINARY);
226     }
227     else
228     {
229         cvThreshold(pImg,pImgMask,threshold,255,CV_THRESH_BINARY);
230     }
231 }   /* icvTestSeqCreateMask */
232
233
234 static void icvTestSeqQureyFrameElem(CvTestSeqElem* p, int /*frame*/)
235 {   /* Read next frame from avi for one record: */
236     if(p->type == SRC_TYPE_AVI)
237     {
238         IplImage*   pI = NULL;
239         //int         frameNum = p->AVILen;
240
241         if(p->pAVI == NULL && p->pFileName)
242         {   /* Open avi file if necessary: */
243             p->pAVI = 0;//cvCaptureFromFile(p->pFileName);
244             if(p->pAVI == NULL)
245             {
246                 printf("WARNING!!! Can not open avi file %s\n",p->pFileName);
247                 return;
248             }
249         }   /* Open avi file if necessary. */
250
251         assert(p->pAVI);
252         //if(frame >= frameNum)
253         {   /* Set new position: */
254             //int N = frame%frameNum;
255
256             /*if( N==0 ||
257                 N != (int)cvGetCaptureProperty(p->pAVI,CV_CAP_PROP_POS_FRAMES))
258             {
259                 cvSetCaptureProperty(p->pAVI,CV_CAP_PROP_POS_FRAMES,N);
260             }*/
261         }   /* Set new position. */
262
263         //pI = cvQueryFrame(p->pAVI);
264         if(pI)
265         {
266             if(pI->origin != p->pImg->origin)
267                 cvFlip( pI, p->pImg, 0 );
268             else
269                 cvCopyImage(pI, p->pImg);
270         }
271
272         if(p->pImg)
273         {
274             if(p->pImgMask==NULL)
275             {
276                 p->pImgMask = cvCreateImage(
277                     cvSize(p->pImg->width,p->pImg->height),
278                     IPL_DEPTH_8U,1);
279             }
280             icvTestSeqCreateMask(p->pImg,p->pImgMask,p->Mask?128:FG_BG_THRESHOLD);
281         }
282     }
283
284 }   /* icvTestSeqQureyFrameElem */
285
286 /*------------- Recursive function to read all images, ------------------------*/
287 /*------------- videos and objects from config file.   ------------------------*/
288
289 static CvTestSeqElem* icvTestSeqReadElemAll(CvTestSeq_* pTS, CvFileStorage* fs, const char* name);
290
291 static void icvTestSeqAllocTrans(CvTestSeqElem* p)
292 {   /* Allocate transformation array if necessary */
293     /* work with transformation */
294     if(p->pTrans == NULL/* && p->FrameNum>0*/)
295     {   /* Allocate transformation array: */
296         int num = MAX(1,p->FrameNum);
297         p->pTrans = (CvTSTrans*)cvAlloc(sizeof(CvTSTrans)*num);
298         p->TransNum = num;
299         while(num--)SET_TRANS_0(p->pTrans+num);
300     }
301
302     if(p->FrameNum > p->TransNum)
303     {   /* Allocate new transformation array: */
304         int         i;
305         int         num = p->FrameNum;
306         CvTSTrans*  pNewTrans = (CvTSTrans*)cvAlloc(sizeof(CvTSTrans)*num);
307
308         for(i=0; i<num; ++i)
309         {
310             if(p->pTrans)
311                 pNewTrans[i] = p->pTrans[i%p->TransNum];
312             else
313                 SET_TRANS_0(pNewTrans+i);
314         }
315         if(p->pTrans)cvFree(&p->pTrans);
316         p->pTrans = pNewTrans;
317         p->TransNum = num;
318     }   /* Allocate new transformation array. */
319 }   /*  Allocate transformation array if necessary. */
320
321 static CvTestSeqElem* icvTestSeqReadElemOne(CvTestSeq_* pTS, CvFileStorage* fs, CvFileNode* node)
322 {
323     int             noise_type = CV_NOISE_NONE;;
324     CvTestSeqElem*  pElem = NULL;
325     const char*     pVideoName = cvReadStringByName( fs, node,"Video", NULL);
326     const char*     pVideoObjName = cvReadStringByName( fs, node,"VideoObj", NULL);
327
328     if(pVideoName)
329     {   /* Check to noise flag: */
330         if( cv_stricmp(pVideoName,"noise_gaussian") == 0 ||
331             cv_stricmp(pVideoName,"noise_normal") == 0) noise_type = CV_NOISE_GAUSSIAN;
332         if( cv_stricmp(pVideoName,"noise_uniform") == 0) noise_type = CV_NOISE_UNIFORM;
333         if( cv_stricmp(pVideoName,"noise_speckle") == 0) noise_type = CV_NOISE_SPECKLE;
334         if( cv_stricmp(pVideoName,"noise_salt_and_pepper") == 0) noise_type = CV_NOISE_SALT_AND_PEPPER;
335     }
336
337     if((pVideoName || pVideoObjName ) && noise_type == CV_NOISE_NONE)
338     {   /* Read other elements: */
339         if(pVideoName) pElem = icvTestSeqReadElemAll(pTS, fs, pVideoName);
340         if(pVideoObjName)
341         {
342             CvTestSeqElem* pE;
343             pElem = icvTestSeqReadElemAll(pTS, fs, pVideoObjName);
344             for(pE=pElem;pE;pE=pE->next)
345             {
346                 pE->ObjID = pTS->ObjNum;
347                 pE->pObjName = pVideoObjName;
348             }
349             pTS->ObjNum++;
350         }
351     }   /* Read other elements. */
352     else
353     {   /* Create new element: */
354         CvFileNode* pPosNode = cvGetFileNodeByName( fs, node,"Pos");
355         CvFileNode* pSizeNode = cvGetFileNodeByName( fs, node,"Size");
356         int AutoSize = (pSizeNode && CV_NODE_IS_STRING(pSizeNode->tag) && cv_stricmp("auto",cvReadString(pSizeNode,""))==0);
357         int AutoPos = (pPosNode && CV_NODE_IS_STRING(pPosNode->tag) && cv_stricmp("auto",cvReadString(pPosNode,""))==0);
358         const char* pFileName = cvReadStringByName( fs, node,"File", NULL);
359         pElem = (CvTestSeqElem*)cvAlloc(sizeof(CvTestSeqElem));
360         memset(pElem,0,sizeof(CvTestSeqElem));
361
362         pElem->ObjID = -1;
363         pElem->noise_type = noise_type;
364         cvRandInit( &pElem->rnd_state, 1, 0, 0,CV_RAND_NORMAL);
365
366         if(pFileName && pElem->noise_type == CV_NOISE_NONE)
367         {   /* If AVI or BMP: */
368             size_t  l = strlen(pFileName);
369             pElem->pFileName = pFileName;
370
371             pElem->type = SRC_TYPE_IMAGE;
372             if(cv_stricmp(".avi",pFileName+l-4) == 0)pElem->type = SRC_TYPE_AVI;
373
374             if(pElem->type == SRC_TYPE_IMAGE)
375             {
376                 //pElem->pImg = cvLoadImage(pFileName);
377                 if(pElem->pImg)
378                 {
379                     pElem->FrameNum = 1;
380                     if(pElem->pImgMask)cvReleaseImage(&(pElem->pImgMask));
381
382                     pElem->pImgMask = cvCreateImage(
383                         cvSize(pElem->pImg->width,pElem->pImg->height),
384                         IPL_DEPTH_8U,1);
385                     icvTestSeqCreateMask(pElem->pImg,pElem->pImgMask,FG_BG_THRESHOLD);
386                 }
387             }
388
389             if(pElem->type == SRC_TYPE_AVI && pFileName)
390             {
391                 //pElem->pAVI = cvCaptureFromFile(pFileName);
392
393                 if(pElem->pAVI)
394                 {
395                     IplImage* pImg = 0;//cvQueryFrame(pElem->pAVI);
396                     pElem->pImg = cvCloneImage(pImg);
397                     pElem->pImg->origin = 0;
398                     //cvSetCaptureProperty(pElem->pAVI,CV_CAP_PROP_POS_FRAMES,0);
399                     pElem->FrameBegin = 0;
400                     pElem->AVILen = pElem->FrameNum = 0;//(int)cvGetCaptureProperty(pElem->pAVI, CV_CAP_PROP_FRAME_COUNT);
401                     //cvReleaseCapture(&pElem->pAVI);
402                     pElem->pAVI = NULL;
403                 }
404                 else
405                 {
406                     printf("WARNING!!! Cannot open avi file %s\n",pFileName);
407                 }
408             }
409
410         }   /* If AVI or BMP. */
411
412         if(pPosNode)
413         {   /* Read positions: */
414             if(CV_NODE_IS_SEQ(pPosNode->tag))
415             {
416                 int num = pPosNode->data.seq->total;
417                 pElem->pPos = (CvPoint2D32f*)cvAlloc(sizeof(float)*num);
418                 cvReadRawData( fs, pPosNode, pElem->pPos, "f" );
419                 pElem->PosNum = num/2;
420                 if(pElem->FrameNum == 0) pElem->FrameNum = pElem->PosNum;
421             }
422         }
423
424         if(pSizeNode)
425         {   /* Read sizes: */
426             if(CV_NODE_IS_SEQ(pSizeNode->tag))
427             {
428                 int num = pSizeNode->data.seq->total;
429                 pElem->pSize = (CvPoint2D32f*)cvAlloc(sizeof(float)*num);
430                 cvReadRawData( fs, pSizeNode, pElem->pSize, "f" );
431                 pElem->SizeNum = num/2;
432             }
433         }
434
435         if(AutoPos || AutoSize)
436         {   /* Auto size and pos: */
437             int     i;
438             int     num = (pElem->type == SRC_TYPE_AVI)?pElem->AVILen:1;
439             if(AutoSize)
440             {
441                 pElem->pSize = (CvPoint2D32f*)cvAlloc(sizeof(CvPoint2D32f)*num);
442                 pElem->SizeNum = num;
443             }
444             if(AutoPos)
445             {
446                 pElem->pPos = (CvPoint2D32f*)cvAlloc(sizeof(CvPoint2D32f)*num);
447                 pElem->PosNum = num;
448             }
449
450             for(i=0; i<num; ++i)
451             {
452                 IplImage* pFG = NULL;
453                 CvPoint2D32f* pPos = AutoPos?(pElem->pPos + i):NULL;
454                 CvPoint2D32f* pSize = AutoSize?(pElem->pSize + i):NULL;
455
456                 icvTestSeqQureyFrameElem(pElem,i);
457                 pFG = pElem->pImgMask;
458
459                 if(pPos)
460                 {
461                     pPos->x = 0.5f;
462                     pPos->y = 0.5f;
463                 }
464                 if(pSize)
465                 {
466                     pSize->x = 0;
467                     pSize->y = 0;
468                 }
469
470                 if(pFG)
471                 {
472                     double      M00;
473                     CvMoments   m;
474                     cvMoments( pElem->pImgMask, &m, 0 );
475                     M00 = cvGetSpatialMoment( &m, 0, 0 );
476
477                     if(M00 > 0 && pSize )
478                     {
479                         double X = cvGetSpatialMoment( &m, 1, 0 )/M00;
480                         double Y = cvGetSpatialMoment( &m, 0, 1 )/M00;
481                         double XX = (cvGetSpatialMoment( &m, 2, 0 )/M00) - X*X;
482                         double YY = (cvGetSpatialMoment( &m, 0, 2 )/M00) - Y*Y;
483                         pSize->x = (float)(4*sqrt(XX))/(pElem->pImgMask->width-1);
484                         pSize->y = (float)(4*sqrt(YY))/(pElem->pImgMask->height-1);
485                     }
486
487                     if(M00 > 0 && pPos)
488                     {
489                         pPos->x = (float)(cvGetSpatialMoment( &m, 1, 0 )/(M00*(pElem->pImgMask->width-1)));
490                         pPos->y = (float)(cvGetSpatialMoment( &m, 0, 1 )/(M00*(pElem->pImgMask->height-1)));
491                     }
492
493                     if(pPos)
494                     {   /* Another way to calculate y pos
495                          * using object median:
496                          */
497                         int y0=0, y1=pFG->height-1;
498                         for(y0=0; y0<pFG->height; ++y0)
499                         {
500                             CvMat       m;
501                             CvScalar    s = cvSum(cvGetRow(pFG, &m, y0));
502                             if(s.val[0] > 255*7) break;
503                         }
504
505                         for(y1=pFG->height-1; y1>0; --y1)
506                         {
507                             CvMat m;
508                             CvScalar s = cvSum(cvGetRow(pFG, &m, y1));
509                             if(s.val[0] > 255*7) break;
510                         }
511
512                         pPos->y = (y0+y1)*0.5f/(pFG->height-1);
513                     }
514                 }   /* pFG */
515             }   /* Next frame. */
516
517             //if(pElem->pAVI) cvReleaseCapture(&pElem->pAVI);
518
519             pElem->pAVI = NULL;
520
521         }   /* End auto position creation. */
522     }   /*  Create new element. */
523
524     if(pElem)
525     {   /* Read transforms and: */
526         int             FirstFrame, LastFrame;
527         CvTestSeqElem*  p=pElem;
528         CvFileNode*     pTransNode = NULL;
529         CvFileNode*     pS = NULL;
530         int             ShiftByPos = 0;
531         int             KeyFrames[1024];
532         CvSeq*          pTransSeq = NULL;
533         int             KeyFrameNum = 0;
534
535         pTransNode = cvGetFileNodeByName( fs, node,"Trans");
536
537         while( pTransNode &&
538                CV_NODE_IS_STRING(pTransNode->tag) &&
539                cv_stricmp("auto",cvReadString(pTransNode,""))!=0)
540         {   /* Trans is reference: */
541             pTransNode = cvGetFileNodeByName( fs, NULL,cvReadString(pTransNode,""));
542         }
543
544         pS = cvGetFileNodeByName( fs, node,"Shift");
545         ShiftByPos = 0;
546         pTransSeq = pTransNode?(CV_NODE_IS_SEQ(pTransNode->tag)?pTransNode->data.seq:NULL):NULL;
547         KeyFrameNum = pTransSeq?pTransSeq->total:1;
548
549         if(   (pS && CV_NODE_IS_STRING(pS->tag) && cv_stricmp("auto",cvReadString(pS,""))==0)
550             ||(pTransNode && CV_NODE_IS_STRING(pTransNode->tag) && cv_stricmp("auto",cvReadString(pTransNode,""))==0))
551         {
552             ShiftByPos = 1;
553         }
554
555         FirstFrame = pElem->FrameBegin;
556         LastFrame = pElem->FrameBegin+pElem->FrameNum-1;
557
558         /* Calculate length of video and reallocate
559          * transformation array:
560          */
561         for(p=pElem; p; p=p->next)
562         {
563             int v;
564             v = cvReadIntByName( fs, node, "BG", -1 );
565             if(v!=-1)p->BG = v;
566             v = cvReadIntByName( fs, node, "Mask", -1 );
567             if(v!=-1)p->Mask = v;
568             
569             p->FrameBegin += cvReadIntByName( fs, node, "FrameBegin", 0 );
570             p->FrameNum = cvReadIntByName( fs, node, "FrameNum", p->FrameNum );
571             p->FrameNum = cvReadIntByName( fs, node, "Dur", p->FrameNum );
572             {
573                 int LastFrame = cvReadIntByName( fs, node, "LastFrame", p->FrameBegin+p->FrameNum-1 );
574                 p->FrameNum = MIN(p->FrameNum,LastFrame - p->FrameBegin+1);
575             }
576
577             icvTestSeqAllocTrans(p);
578
579             {   /* New range estimation: */
580                 int LF = p->FrameBegin+p->FrameNum-1;
581                 if(p==pElem || FirstFrame > p->FrameBegin)FirstFrame = p->FrameBegin;
582                 if(p==pElem || LastFrame < LF)LastFrame = LF;
583             }   /* New range estimation. */
584         }   /*  End allocate new transfrom array. */
585
586         if(ShiftByPos)
587         {
588             for(p=pElem;p;p=p->next)
589             {   /* Modify transformation to make autoshift: */
590                 int         i;
591                 int         num = p->FrameNum;
592                 assert(num <= p->TransNum);
593                 p->TransNum = MAX(1,num);
594
595                 for(i=0; i<num; ++i)
596                 {
597                     CvTSTrans*  pT = p->pTrans+i;
598                     //float   t = (num>1)?((float)i/(num-1)):0.0f;
599                     float newx = p->pPos[i%p->PosNum].x;
600                     float newy = p->pPos[i%p->PosNum].y;
601                     pT->Shift.x = -newx*pT->Scale.x;
602                     pT->Shift.y = -newy*pT->Scale.y;
603
604                     if(p->pImg)
605                     {
606                         newx *= p->pImg->width-1;
607                         newy *= p->pImg->height-1;
608                     }
609
610                     pT->T[2] = -(pT->T[0]*newx+pT->T[1]*newy);
611                     pT->T[5] = -(pT->T[3]*newx+pT->T[4]*newy);
612                 }
613             }   /* Modify transformation old. */
614         }   /*  Next record. */
615
616         /* Initialize frame number array: */
617         KeyFrames[0] = FirstFrame;
618
619         if(pTransSeq&&KeyFrameNum>1)
620         {
621             int i0,i1,i;
622             for(i=0; i<KeyFrameNum; ++i)
623             {
624                 CvFileNode* pTN = (CvFileNode*)cvGetSeqElem(pTransSeq,i);
625                 KeyFrames[i] = cvReadIntByName(fs,pTN,"frame",-1);
626             }
627
628             if(KeyFrames[0]<0)KeyFrames[0]=FirstFrame;
629             if(KeyFrames[KeyFrameNum-1]<0)KeyFrames[KeyFrameNum-1]=LastFrame;
630
631             for(i0=0, i1=1; i1<KeyFrameNum;)
632             {
633                 int i;
634
635                 for(i1=i0+1; i1<KeyFrameNum && KeyFrames[i1]<0; i1++);
636
637                 assert(i1<KeyFrameNum);
638                 assert(i1>i0);
639
640                 for(i=i0+1; i<i1; ++i)
641                 {
642                     KeyFrames[i] = cvRound(KeyFrames[i0] + (float)(i-i0)*(float)(KeyFrames[i1] - KeyFrames[i0])/(float)(i1-i0));
643                 }
644                 i0 = i1;
645                 i1++;
646             }   /* Next key run. */
647         }   /*  Initialize frame number array. */
648
649         if(pTransNode || pTransSeq)
650         {   /* More complex transform. */
651             int     param;
652             CvFileNode* pTN = pTransSeq?(CvFileNode*)cvGetSeqElem(pTransSeq,0):pTransNode;
653
654             for(p=pElem; p; p=p->next)
655             {
656                 //int trans_num = p->TransNum;
657                 for(param=0; param_name[param]; ++param)
658                 {
659                     char*   name = param_name[param];
660                     float   defv = param_defval[param];
661                     if(KeyFrameNum==1)
662                     {   /* Only one transform record: */
663                         int     i;
664                         double  val;
665                         CvFileNode* node = cvGetFileNodeByName( fs, pTN,name);
666                         if(node == NULL) continue;
667                         val = cvReadReal(node,defv);
668
669                         for(i=0; i<p->TransNum; ++i)
670                         {
671                             icvUpdateTrans(
672                                 p->pTrans+i, param, val,
673                                 p->pImg?(float)(p->pImg->width-1):1.0f,
674                                 p->pImg?(float)(p->pImg->height-1):1.0f);
675                         }
676                     }   /* Next record. */
677                     else
678                     {   /* Several transforms: */
679                         int         i0,i1;
680                         double      v0;
681                         double      v1;
682
683                         CvFileNode* pTN = (CvFileNode*)cvGetSeqElem(pTransSeq,0);
684                         v0 = cvReadRealByName(fs, pTN,name,defv);
685
686                         for(i1=1,i0=0; i1<KeyFrameNum; ++i1)
687                         {
688                             int         f0,f1;
689                             int         i;
690                             CvFileNode* pTN = (CvFileNode*)cvGetSeqElem(pTransSeq,i1);
691                             CvFileNode* pVN = cvGetFileNodeByName(fs,pTN,name);
692
693                             if(pVN)v1 = cvReadReal(pVN,defv);
694                             else if(pVN == NULL && i1 == KeyFrameNum-1) v1 = defv;
695                             else continue;
696
697                             f0 = KeyFrames[i0];
698                             f1 = KeyFrames[i1];
699
700                             if(i1==(KeyFrameNum-1)) f1++;
701
702                             for(i=f0; i<f1; ++i)
703                             {
704                                 double   val;
705                                 double   t = (float)(i-f0);
706                                 int      li = i - p->FrameBegin;
707                                 if(li<0) continue;
708                                 if(li>= p->TransNum) break;
709                                 if(KeyFrames[i1]>KeyFrames[i0]) t /=(float)(KeyFrames[i1]-KeyFrames[i0]);
710                                 val = t*(v1-v0)+v0;
711
712                                 icvUpdateTrans(
713                                     p->pTrans+li, param, val,
714                                     p->pImg?(float)(p->pImg->width-1):1.0f,
715                                     p->pImg?(float)(p->pImg->height-1):1.0f);
716
717                             }   /* Next transform. */
718                             i0 = i1;
719                             v0 = v1;
720
721                         }   /* Next value run. */
722                     }   /*  Several transforms. */
723                 }   /*  Next parameter. */
724             }   /*  Next record. */
725         }   /*  More complex transform. */
726     }   /*  Read transfroms. */
727
728     return pElem;
729
730 }   /* icvTestSeqReadElemOne */
731
732 static CvTestSeqElem* icvTestSeqReadElemAll(CvTestSeq_* pTS, CvFileStorage* fs, const char* name)
733 {
734     CvTestSeqElem*  pElem = NULL;
735     CvFileNode*     node;
736
737     if(name == NULL) return NULL;
738
739     node = cvGetFileNodeByName( fs, NULL, name );
740
741     if(node == NULL)
742     {
743         printf("WARNING!!! - Video %s does not exist!\n", name);
744         return NULL;
745     }
746
747     printf("Read node %s\n",name);
748
749     if(CV_NODE_IS_SEQ(node->tag))
750     {   /* Read all element in sequence: */
751         int             i;
752         CvSeq*          seq = node->data.seq;
753         CvTestSeqElem*  pElemLast = NULL;
754
755         for(i=0; i<seq->total; ++i)
756         {
757             CvFileNode*     next_node = (CvFileNode*)cvGetSeqElem( seq, i );
758             CvTestSeqElem*  pElemNew = icvTestSeqReadElemOne(pTS, fs, next_node );
759             CvFileNode*     pDurNode = cvGetFileNodeByName( fs, next_node,"Dur");
760
761             if(pElemNew == NULL )
762             {
763                 printf("WARNING in parsing %s record!!! Cannot read array element\n", name);
764                 continue;
765             }
766
767             if(pElem && pElemLast)
768             {
769                 pElemLast->next = pElemNew;
770                 if(pDurNode)
771                 {
772                     pElemNew->FrameBegin = pElemLast->FrameBegin + pElemLast->FrameNum;
773                 }
774             }
775             else
776             {
777                 pElem = pElemNew;
778             }
779
780             /* Find last element: */
781             for(pElemLast=pElemNew;pElemLast && pElemLast->next;pElemLast= pElemLast->next);
782
783         }   /* Next element. */
784     }   /*  Read all element in sequence. */
785     else
786     {   /* Read one element: */
787         pElem = icvTestSeqReadElemOne(pTS, fs, node );
788     }
789
790     return pElem;
791
792 }   /* icvTestSeqReadElemAll */
793
794 static void icvTestSeqReleaseAll(CvTestSeqElem** ppElemList)
795 {
796     CvTestSeqElem* p = ppElemList[0];
797
798     while(p)
799     {
800         CvTestSeqElem* pd = p;
801         if(p->pAVI)
802         {
803             //cvReleaseCapture(&p->pAVI);
804         }
805         if(p->pImg)cvReleaseImage(&p->pImg);
806         if(p->pImgMask)cvReleaseImage(&p->pImgMask);
807         if(p->pPos)cvFree(&p->pPos);
808         if(p->pTrans)cvFree(&p->pTrans);
809         if(p->pSize)cvFree(&p->pSize);
810         p=p->next;
811         cvFree(&pd);
812
813     }   /* Next element. */
814
815     ppElemList[0] = NULL;
816
817 }   /* icvTestSeqReleaseAll */
818
819 CvTestSeq* cvCreateTestSeq(char* pConfigfile, char** videos, int numvideo, float Scale, int noise_type, double noise_ampl)
820 {
821     int             size = sizeof(CvTestSeq_);
822     CvTestSeq_*     pTS = (CvTestSeq_*)cvAlloc(size);
823     CvFileStorage*  fs = cvOpenFileStorage( pConfigfile, NULL, CV_STORAGE_READ);
824     int         i;
825
826     if(pTS == NULL || fs == NULL) return NULL;
827     memset(pTS,0,size);
828
829     pTS->pFileStorage = fs;
830     pTS->noise_ampl = noise_ampl;
831     pTS->noise_type = noise_type;
832     pTS->IVar_DI = 0;
833     pTS->ObjNum = 0;
834
835     /* Read all videos: */
836     for (i=0; i<numvideo; ++i)
837     {
838         CvTestSeqElem*  pElemNew = icvTestSeqReadElemAll(pTS, fs, videos[i]);
839
840         if(pTS->pElemList==NULL)pTS->pElemList = pElemNew;
841         else
842         {
843             CvTestSeqElem* p = NULL;
844             for(p=pTS->pElemList;p->next;p=p->next);
845             p->next = pElemNew;
846         }
847     }   /* Read all videos. */
848
849     {   /* Calculate elements and image size and video length: */
850         CvTestSeqElem*  p = pTS->pElemList;
851         int             num = 0;
852         CvSize          MaxSize = {0,0};
853         int             MaxFN = 0;
854
855         for(p = pTS->pElemList; p; p=p->next, num++)
856         {
857             int     FN = p->FrameBegin+p->FrameNum;
858             CvSize  S = {0,0};
859
860             if(p->pImg && p->BG)
861             {
862                 S.width = p->pImg->width;
863                 S.height = p->pImg->height;
864             }
865
866             if(MaxSize.width < S.width) MaxSize.width = S.width;
867             if(MaxSize.height < S.height) MaxSize.height = S.height;
868             if(MaxFN < FN)MaxFN = FN;
869         }
870
871         pTS->ListNum = num;
872
873         if(MaxSize.width == 0)MaxSize.width = 320;
874         if(MaxSize.height == 0)MaxSize.height = 240;
875
876         MaxSize.width = cvRound(Scale*MaxSize.width);
877         MaxSize.height = cvRound(Scale*MaxSize.height);
878
879         pTS->pImg = cvCreateImage(MaxSize,IPL_DEPTH_8U,3);
880         pTS->pImgMask = cvCreateImage(MaxSize,IPL_DEPTH_8U,1);
881         pTS->FrameNum = MaxFN;
882
883         for(p = pTS->pElemList; p; p=p->next)
884         {
885             if(p->FrameNum<=0)p->FrameNum=MaxFN;
886         }
887     }   /* Calculate elements and image size. */
888
889     return (CvTestSeq*)pTS;
890
891 }   /* cvCreateTestSeq */
892
893 void cvReleaseTestSeq(CvTestSeq** ppTestSeq)
894 {
895     CvTestSeq_* pTS = (CvTestSeq_*)ppTestSeq[0];
896
897     icvTestSeqReleaseAll(&pTS->pElemList);
898     if(pTS->pImg) cvReleaseImage(&pTS->pImg);
899     if(pTS->pImgMask) cvReleaseImage(&pTS->pImgMask);
900     if(pTS->pFileStorage)cvReleaseFileStorage(&pTS->pFileStorage);
901
902     cvFree(ppTestSeq);
903
904 }   /* cvReleaseTestSeq */
905
906 void cvTestSeqSetFrame(CvTestSeq* pTestSeq, int n)
907 {
908     CvTestSeq_*     pTS = (CvTestSeq_*)pTestSeq;
909     pTS->CurFrame = n;
910 }
911
912 IplImage* cvTestSeqQueryFrame(CvTestSeq* pTestSeq)
913 {
914     CvTestSeq_*     pTS = (CvTestSeq_*)pTestSeq;
915     CvTestSeqElem*  p = pTS->pElemList;
916     IplImage*       pImg = pTS->pImg;
917     IplImage*       pImgAdd = cvCloneImage(pTS->pImg);
918     IplImage*       pImgAddG = cvCreateImage(cvSize(pImgAdd->width,pImgAdd->height),IPL_DEPTH_8U,1);
919     IplImage*       pImgMask = pTS->pImgMask;
920     IplImage*       pImgMaskAdd = cvCloneImage(pTS->pImgMask);
921     CvMat*          pT = cvCreateMat(2,3,CV_32F);
922
923     if(pTS->CurFrame >= pTS->FrameNum) return NULL;
924     cvZero(pImg);
925     cvZero(pImgMask);
926
927     for(p=pTS->pElemList; p; p=p->next)
928     {
929         int             DirectCopy = FALSE;
930         int             frame = pTS->CurFrame - p->FrameBegin;
931         //float           t = p->FrameNum>1?((float)frame/(p->FrameNum-1)):0;
932         CvTSTrans*      pTrans = p->pTrans + frame%p->TransNum;
933
934         assert(pTrans);
935
936         if( p->FrameNum > 0 && (frame < 0 || frame >= p->FrameNum) )
937         {   /* Current frame is out of range: */
938             //if(p->pAVI)cvReleaseCapture(&p->pAVI);
939             p->pAVI = NULL;
940             continue;
941         }
942
943         cvZero(pImgAdd);
944         cvZero(pImgAddG);
945         cvZero(pImgMaskAdd);
946
947         if(p->noise_type == CV_NOISE_NONE)
948         {   /* For not noise:  */
949             /* Get next frame: */
950             icvTestSeqQureyFrameElem(p, frame);
951             if(p->pImg == NULL) continue;
952
953 #if 1 /* transform using T filed in Trans */
954             {   /* Calculate transform matrix: */
955                 float   W = (float)(pImgAdd->width-1);
956                 float   H = (float)(pImgAdd->height-1);
957                 float   W0 = (float)(p->pImg->width-1);
958                 float   H0 = (float)(p->pImg->height-1);
959                 cvZero(pT);
960                 {   /* Calcualte inverse matrix: */
961                     CvMat   mat = cvMat(2,3,CV_32F, pTrans->T);
962                     mat.width--;
963                     pT->width--;
964                     cvInvert(&mat, pT);
965                     pT->width++;
966                 }
967
968                 CV_MAT_ELEM(pT[0], float, 0, 2) =
969                     CV_MAT_ELEM(pT[0], float, 0, 0)*(W0/2-pTrans->T[2])+
970                     CV_MAT_ELEM(pT[0], float, 0, 1)*(H0/2-pTrans->T[5]);
971
972                 CV_MAT_ELEM(pT[0], float, 1, 2) =
973                     CV_MAT_ELEM(pT[0], float, 1, 0)*(W0/2-pTrans->T[2])+
974                     CV_MAT_ELEM(pT[0], float, 1, 1)*(H0/2-pTrans->T[5]);
975
976                 CV_MAT_ELEM(pT[0], float, 0, 0) *= W0/W;
977                 CV_MAT_ELEM(pT[0], float, 0, 1) *= H0/H;
978                 CV_MAT_ELEM(pT[0], float, 1, 0) *= W0/W;
979                 CV_MAT_ELEM(pT[0], float, 1, 1) *= H0/H;
980
981             }   /* Calculate transform matrix. */
982 #else
983             {   /* Calculate transform matrix: */
984                 float   SX = (float)(p->pImg->width-1)/((pImgAdd->width-1)*pTrans->Scale.x);
985                 float   SY = (float)(p->pImg->height-1)/((pImgAdd->height-1)*pTrans->Scale.y);
986                 float   DX = pTrans->Shift.x;
987                 float   DY = pTrans->Shift.y;;
988                 cvZero(pT);
989                 ((float*)(pT->data.ptr+pT->step*0))[0]=SX;
990                 ((float*)(pT->data.ptr+pT->step*1))[1]=SY;
991                 ((float*)(pT->data.ptr+pT->step*0))[2]=SX*(pImgAdd->width-1)*(0.5f-DX);
992                 ((float*)(pT->data.ptr+pT->step*1))[2]=SY*(pImgAdd->height-1)*(0.5f-DY);
993             }   /* Calculate transform matrix. */
994 #endif
995
996
997             {   /* Check for direct copy: */
998                 DirectCopy = TRUE;
999                 if( fabs(CV_MAT_ELEM(pT[0],float,0,0)-1) > 0.00001) DirectCopy = FALSE;
1000                 if( fabs(CV_MAT_ELEM(pT[0],float,1,0)) > 0.00001) DirectCopy = FALSE;
1001                 if( fabs(CV_MAT_ELEM(pT[0],float,0,1)) > 0.00001) DirectCopy = FALSE;
1002                 if( fabs(CV_MAT_ELEM(pT[0],float,0,1)) > 0.00001) DirectCopy = FALSE;
1003                 if( fabs(CV_MAT_ELEM(pT[0],float,0,2)-(pImg->width-1)*0.5) > 0.5) DirectCopy = FALSE;
1004                 if( fabs(CV_MAT_ELEM(pT[0],float,1,2)-(pImg->height-1)*0.5) > 0.5) DirectCopy = FALSE;
1005             }
1006
1007             /* Extract image and mask: */
1008             if(p->pImg->nChannels == 1)
1009             {
1010                 if(DirectCopy)
1011                 {
1012                     cvCvtColor( p->pImg,pImgAdd,CV_GRAY2BGR);
1013                 }
1014                 else
1015                 {
1016                     cvGetQuadrangleSubPix( p->pImg, pImgAddG, pT);
1017                     cvCvtColor( pImgAddG,pImgAdd,CV_GRAY2BGR);
1018                 }
1019             }
1020
1021             if(p->pImg->nChannels == 3)
1022             {
1023                 if(DirectCopy)
1024                     cvCopyImage(p->pImg, pImgAdd);
1025                 else
1026                     cvGetQuadrangleSubPix( p->pImg, pImgAdd, pT);
1027             }
1028
1029             if(p->pImgMask)
1030             {
1031                 if(DirectCopy)
1032                     cvCopyImage(p->pImgMask, pImgMaskAdd);
1033                 else
1034                     cvGetQuadrangleSubPix( p->pImgMask, pImgMaskAdd, pT);
1035
1036                 cvThreshold(pImgMaskAdd,pImgMaskAdd,128,255,CV_THRESH_BINARY);
1037             }
1038
1039             if(pTrans->C != 1 || pTrans->I != 0)
1040             {   /* Intensity transformation: */
1041                 cvScale(pImgAdd, pImgAdd, pTrans->C,pTrans->I);
1042             }   /* Intensity transformation: */
1043
1044             if(pTrans->GN > 0)
1045             {   /* Add noise: */
1046                 IplImage* pImgN = cvCloneImage(pImgAdd);
1047                 cvRandSetRange( &p->rnd_state, pTrans->GN, 0, -1 );
1048                 cvRand(&p->rnd_state, pImgN);
1049                 cvAdd(pImgN,pImgAdd,pImgAdd);
1050                 cvReleaseImage(&pImgN);
1051             }   /* Add noise. */
1052
1053             if(p->Mask)
1054             {   /* Update only mask: */
1055                 cvOr(pImgMaskAdd, pImgMask, pImgMask);
1056             }
1057             else
1058             {   /* Add image and mask to exist main image and mask: */
1059                 if(p->BG)
1060                 {   /* If image is background: */
1061                     cvCopy( pImgAdd, pImg, NULL);
1062                 }
1063                 else
1064                 {   /* If image is foreground: */
1065                     cvCopy( pImgAdd, pImg, pImgMaskAdd);
1066                     if(p->ObjID>=0)
1067                         cvOr(pImgMaskAdd, pImgMask, pImgMask);
1068                 }
1069             }   /* Not mask. */
1070         }   /*  For not noise. */
1071         else
1072         {   /* Process noise video: */
1073
1074             if( p->noise_type == CV_NOISE_GAUSSIAN ||
1075                 p->noise_type == CV_NOISE_UNIFORM)
1076
1077             {   /* Gaussan and uniform additive noise: */
1078                 cvAddNoise(pImg,p->noise_type,pTrans->NoiseAmp * pTrans->C, &p->rnd_state);
1079             }   /* Gaussan and uniform additive noise. */
1080
1081             if( p->noise_type == CV_NOISE_SPECKLE)
1082             {   /* Speckle -- multiplicative noise: */
1083                 if(pTrans->I != 0)cvSubS(pImg,cvScalar(pTrans->I,pTrans->I,pTrans->I),pImg);
1084                 cvAddNoise(pImg,p->noise_type,pTrans->NoiseAmp, &p->rnd_state);
1085                 if(pTrans->I != 0)cvAddS(pImg,cvScalar(pTrans->I,pTrans->I,pTrans->I),pImg);
1086             }   /* Speckle -- multiplicative noise. */
1087
1088             if( p->noise_type == CV_NOISE_SALT_AND_PEPPER)
1089             {   /* Salt and pepper: */
1090                 cvAddNoise(pImg,p->noise_type,pTrans->NoiseAmp, &p->rnd_state);
1091             }   /* Salt and pepper. */
1092         }   /*  Process noise video.*/
1093     }   /*  Next item. */
1094
1095     if(pImg)
1096     {
1097         if(pTS->noise_type != CV_NOISE_NONE)
1098         {   /* Add noise: */
1099             cvAddNoise(pImg,pTS->noise_type,pTS->noise_ampl);
1100         }
1101
1102         if(pTS->IVar_DI != 0)
1103         {   /* Change intensity: */
1104             float   I = MIN(pTS->IVar_CurI,pTS->IVar_MaxI);
1105             I = MAX(I,pTS->IVar_MinI);
1106             cvScale(pImg,pImg,1,I);
1107
1108             if(pTS->IVar_CurI >= pTS->IVar_MaxI)
1109                 pTS->IVar_CurDI = (float)-fabs(pTS->IVar_DI);
1110
1111             if(pTS->IVar_CurI <= pTS->IVar_MinI)
1112                 pTS->IVar_CurDI = (float)+fabs(pTS->IVar_DI);
1113
1114             pTS->IVar_CurI += pTS->IVar_CurDI;
1115         }
1116     }
1117
1118
1119     pTS->CurFrame++;
1120     cvReleaseImage(&pImgAdd);
1121     cvReleaseImage(&pImgAddG);
1122     cvReleaseImage(&pImgMaskAdd);
1123     cvReleaseMat(&pT);
1124     return pImg;
1125
1126 }   /*cvTestSeqQueryFrame*/
1127
1128 IplImage* cvTestSeqGetFGMask(CvTestSeq* pTestSeq)
1129 {
1130     return ((CvTestSeq_*)pTestSeq)->pImgMask;
1131 }
1132
1133 IplImage* cvTestSeqGetImage(CvTestSeq* pTestSeq)
1134 {
1135     return ((CvTestSeq_*)pTestSeq)->pImg;
1136 }
1137
1138 int cvTestSeqGetObjectNum(CvTestSeq* pTestSeq)
1139 {
1140     //return ((CvTestSeq_*)pTestSeq)->ListNum;
1141     return ((CvTestSeq_*)pTestSeq)->ObjNum;
1142 }
1143
1144 int cvTestSeqGetObjectPos(CvTestSeq* pTestSeq, int ObjIndex, CvPoint2D32f* pPos)
1145 {
1146     CvTestSeq_*     pTS = (CvTestSeq_*)pTestSeq;
1147     CvTestSeqElem*  p = pTS->pElemList;
1148     if(pTS->CurFrame > pTS->FrameNum) return 0;
1149
1150     for(p=pTS->pElemList; p; p=p->next)
1151     {
1152         int frame = pTS->CurFrame - p->FrameBegin - 1;
1153         if(ObjIndex==p->ObjID && frame >= 0 && frame < p->FrameNum) break;
1154     }
1155
1156     if(p && p->pPos && p->PosNum>0)
1157     {
1158         CvTSTrans*  pTrans;
1159         float       t;
1160         int         frame = pTS->CurFrame - p->FrameBegin - 1;
1161         if(frame < 0 || frame >= p->FrameNum) return 0;
1162         t = (p->FrameNum>1)?((float)frame / (p->FrameNum-1)):0;
1163         pTrans = p->pTrans + frame%p->TransNum;
1164         pPos[0] = p->pPos[frame%p->PosNum];
1165
1166 #if 1   /* Transform using T filed in Trans: */
1167         {
1168             float x = pPos->x * (p->pImg?(p->pImg->width-1):1);
1169             float y = pPos->y * (p->pImg?(p->pImg->height-1):1);
1170
1171             pPos->x = pTrans->T[0]*x+pTrans->T[1]*y+pTrans->T[2];
1172             pPos->y = pTrans->T[3]*x+pTrans->T[4]*y+pTrans->T[5];
1173
1174             if(p->pImg)
1175             {
1176                 pPos->x /= p->pImg->width-1;
1177                 pPos->y /= p->pImg->height-1;
1178             }
1179
1180         }
1181
1182
1183 #else
1184         pPos->x = pPos->x * pTrans->Scale.x + pTrans->Shift.x;
1185         pPos->y = pPos->y * pTrans->Scale.y + pTrans->Shift.y;
1186 #endif
1187         pPos->x *= pTS->pImg->width-1;
1188         pPos->y *= pTS->pImg->height-1;
1189         return 1;
1190     }
1191     return 0;
1192
1193 }   /* cvTestSeqGetObjectPos */
1194
1195 int cvTestSeqGetObjectSize(CvTestSeq* pTestSeq, int ObjIndex, CvPoint2D32f* pSize)
1196 {
1197     CvTestSeq_*     pTS = (CvTestSeq_*)pTestSeq;
1198     CvTestSeqElem*  p = pTS->pElemList;
1199     if(pTS->CurFrame > pTS->FrameNum) return 0;
1200
1201     for(p=pTS->pElemList; p; p=p->next)
1202     {
1203         int frame = pTS->CurFrame - p->FrameBegin - 1;
1204         if(ObjIndex==p->ObjID && frame >= 0 && frame < p->FrameNum) break;
1205     }
1206
1207     if(p && p->pSize && p->SizeNum>0)
1208     {
1209         CvTSTrans*  pTrans;
1210         float       t;
1211         int         frame = pTS->CurFrame - p->FrameBegin - 1;
1212
1213         if(frame < 0 || frame >= p->FrameNum) return 0;
1214
1215         t = (p->FrameNum>1)?((float)frame / (p->FrameNum-1)):0;
1216         pTrans = p->pTrans + frame%p->TransNum;
1217         pSize[0] = p->pSize[frame%p->SizeNum];
1218
1219 #if 1   /* Transform using T filed in Trans: */
1220         {
1221             float x = pSize->x * (p->pImg?(p->pImg->width-1):1);
1222             float y = pSize->y * (p->pImg?(p->pImg->height-1):1);
1223             float   dx1, dx2;
1224             float   dy1, dy2;
1225
1226             dx1 = (float)fabs(pTrans->T[0]*x+pTrans->T[1]*y);
1227             dy1 = (float)fabs(pTrans->T[3]*x+pTrans->T[4]*y);
1228
1229             dx2 = (float)fabs(pTrans->T[0]*x - pTrans->T[1]*y);
1230             dy2 = (float)fabs(pTrans->T[3]*x - pTrans->T[4]*y);
1231
1232             pSize->x = MAX(dx1,dx2);
1233             pSize->y = MAX(dy1,dy2);
1234
1235             if(p->pImg)
1236             {
1237                 pSize->x /= p->pImg->width-1;
1238                 pSize->y /= p->pImg->height-1;
1239             }
1240
1241         }
1242
1243
1244 #else
1245         pSize->x = pSize->x * pTrans->Scale.x;
1246         pSize->y = pSize->y * pTrans->Scale.y;
1247 #endif
1248         pSize->x *= pTS->pImg->width-1;
1249         pSize->y *= pTS->pImg->height-1;
1250         return 1;
1251     }
1252
1253     return 0;
1254
1255 }   /* cvTestSeqGetObjectSize */
1256
1257 /* Add noise to finile image: */
1258 void cvTestSeqAddNoise(CvTestSeq* pTestSeq, int noise_type, double noise_ampl)
1259 {
1260     CvTestSeq_*     pTS = (CvTestSeq_*)pTestSeq;
1261     pTS->noise_type = noise_type;
1262     pTS->noise_ampl = noise_ampl;
1263 }
1264
1265 /* Add Intensity variation: */
1266 void cvTestSeqAddIntensityVariation(CvTestSeq* pTestSeq, float DI_per_frame, float MinI, float MaxI)
1267 {
1268     CvTestSeq_* pTS = (CvTestSeq_*)pTestSeq;
1269     pTS->IVar_CurDI = pTS->IVar_DI = DI_per_frame;
1270     pTS->IVar_MaxI = MaxI;
1271     pTS->IVar_MinI = MinI;
1272 }
1273
1274 void cvAddNoise(IplImage* pImg, int noise_type, double Ampl, CvRandState* rnd_state)
1275 {   /* Add noise to image: */
1276     CvSize      S = cvSize(pImg->width,pImg->height);
1277     IplImage*   pImgAdd = cvCreateImage(S,pImg->depth,pImg->nChannels);
1278     static CvRandState local_rnd_state;
1279     static int  first = 1;
1280
1281     if(first)
1282     {
1283         first = 0;
1284         cvRandInit( &local_rnd_state, 1, 0, 0,CV_RAND_NORMAL);
1285     }
1286
1287     if(rnd_state == NULL)rnd_state = &local_rnd_state;
1288
1289     if( noise_type == CV_NOISE_GAUSSIAN ||
1290         noise_type == CV_NOISE_UNIFORM)
1291     {   /* Gaussan and uniform additive noise: */
1292         int set_zero = 0;
1293
1294         if( noise_type == CV_NOISE_GAUSSIAN)
1295         {
1296             rnd_state->disttype = CV_RAND_NORMAL;
1297             cvRandSetRange( rnd_state,  Ampl, 0, -1 );
1298             if(Ampl <= 0) set_zero = 1;
1299         }
1300
1301         if( noise_type == CV_NOISE_UNIFORM)
1302         {
1303             double max_val =
1304                 1.7320508075688772935274463415059 * Ampl;
1305             rnd_state->disttype = CV_RAND_UNI;
1306             cvRandSetRange( rnd_state, -max_val, max_val, -1 );
1307             if(max_val < 1) set_zero = 1;
1308         }
1309
1310         if(!set_zero)
1311         {
1312             IplImage*   pImgNoise = cvCreateImage(S,IPL_DEPTH_32F,pImg->nChannels);
1313             IplImage*   pImgOrg = cvCreateImage(S,IPL_DEPTH_32F,pImg->nChannels);
1314             cvConvert(pImg, pImgOrg);
1315             cvRand(rnd_state, pImgNoise);
1316             cvAdd(pImgOrg,pImgNoise,pImgOrg);
1317             cvConvert(pImgOrg,pImg);
1318             cvReleaseImage(&pImgNoise);
1319             cvReleaseImage(&pImgOrg);
1320         }
1321     }   /* Gaussan and uniform additive noise. */
1322
1323     if( noise_type == CV_NOISE_SPECKLE)
1324     {   /* Speckle -- multiplicative noise: */
1325         IplImage* pImgSP = cvCreateImage( S,IPL_DEPTH_32F, pImg->nChannels );
1326         IplImage* pImgTemp = cvCreateImage(S,IPL_DEPTH_32F, pImg->nChannels );
1327         rnd_state->disttype = CV_RAND_NORMAL;
1328         cvRandSetRange( rnd_state, Ampl, 0, -1 );
1329         cvRand(rnd_state, pImgSP);
1330         cvConvert(pImg,pImgTemp);
1331         cvMul(pImgSP,pImgTemp,pImgSP);
1332         cvAdd(pImgTemp,pImgSP,pImgTemp);
1333         cvConvert(pImgTemp,pImg);
1334         cvReleaseImage(&pImgSP);
1335         cvReleaseImage(&pImgTemp);
1336     }   /* Speckle -- multiplicative noise. */
1337
1338     if( noise_type == CV_NOISE_SALT_AND_PEPPER && Ampl > 0)
1339     {   /* Salt and pepper: */
1340         IplImage* pImgMask = cvCreateImage( S,IPL_DEPTH_32F, 1 );
1341         IplImage* pImgMaskBin = cvCreateImage( S,IPL_DEPTH_8U, 1 );
1342         IplImage* pImgVal = cvCreateImage( S,IPL_DEPTH_8U, 1 );
1343         rnd_state->disttype = CV_RAND_UNI;
1344
1345         /* Create mask: */
1346         cvRandSetRange( rnd_state, 0, 1, -1 );
1347         cvRand(rnd_state, pImgMask);
1348         cvThreshold(pImgMask,pImgMask, Ampl, 255, CV_THRESH_BINARY_INV );
1349         cvConvert(pImgMask,pImgMaskBin);
1350
1351         /* Create vals: */
1352         cvRandSetRange( rnd_state, 0, 255, -1 );
1353         cvRand(rnd_state, pImgVal);
1354         cvThreshold(pImgVal,pImgVal,128, 255, CV_THRESH_BINARY );
1355         cvMerge(
1356             pImgAdd->nChannels>0?pImgVal:NULL,
1357             pImgAdd->nChannels>1?pImgVal:NULL,
1358             pImgAdd->nChannels>2?pImgVal:NULL,
1359             pImgAdd->nChannels>3?pImgVal:NULL,
1360             pImgAdd);
1361         cvCopy(pImgAdd, pImg, pImgMaskBin);
1362         cvReleaseImage(&pImgMask);
1363         cvReleaseImage(&pImgMaskBin);
1364         cvReleaseImage(&pImgVal);
1365
1366     }   /* Salt and pepper. */
1367
1368     cvReleaseImage(&pImgAdd);
1369
1370 }   /* cvAddNoise */
1371