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