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