1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
13 // Third party copyrights are property of their respective owners.
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
18 // * Redistribution's of source code must retain the above copyright notice,
19 // this list of conditions and the following disclaimer.
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.
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.
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.
42 This file contain implementation of virtual interface of CvTestSeq
45 #include "precomp.hpp" /* virtual interface if CvTestSeq */
48 void cvAddNoise(IplImage* pImg, int noise_type, double Ampl, CvRandState* rnd_state = NULL);
50 #define FG_BG_THRESHOLD 3
52 #define SRC_TYPE_AVI 1
53 #define SRC_TYPE_IMAGE 0
55 /* Transformation structure: */
56 typedef struct CvTSTrans
58 float T[6]; /* geometry transformation */
63 float GN; /* standart deviation of added gaussian noise */
64 float NoiseAmp; /* amplifier of noise power */
68 void SET_TRANS_0(CvTSTrans *pT)
70 memset(pT,0,sizeof(CvTSTrans));
74 pT->T[4] = pT->T[0] = 1;
78 /* === Some definitions and functions for transformation update: ===*/
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)
97 double C = cos(3.1415926535897932384626433832795*val/180.0);
98 double S = sin(3.1415926535897932384626433832795*val/180.0);
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];
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);
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);
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);
140 pTrans->Shift.x = (float)(pTrans->Shift.x +val);
141 pTrans->T[2] = (float)(pTrans->T[2] +val*MaxX);
146 pTrans->Shift.y = (float)(pTrans->Shift.y +val);
147 pTrans->T[5] = (float)(pTrans->T[5] +val*MaxY);
152 pTrans->C = (float)(pTrans->C *val);
153 pTrans->I = (float)(pTrans->I *val);
156 if(param==P_I) pTrans->I = (float)(pTrans->I +val);
160 pTrans->GN = (float)sqrt(val*val+pTrans->GN*pTrans->GN);
163 if(param==P_NAmp) pTrans->NoiseAmp = (float)(pTrans->NoiseAmp *val);
164 } /* icvUpdateTrans */
166 /* === END some defenitions and function for transformation update ===*/
168 typedef struct CvTestSeqElem
170 const char* pObjName;
171 const char* pFileName;
172 int type; /* video or image */
173 CvPoint2D32f* pPos; /* positions of object in sequence */
175 CvPoint2D32f* pSize; /* sizes of object in sequence */
177 CvTSTrans* pTrans; /* transforation of image in sequence */
180 CvPoint2D32f ShiftBegin;
181 CvPoint2D32f ShiftEnd;
189 int BG; /* flag is it background (1) or foreground (0) */
190 int Mask; /* flag is it foreground mask (1) or usual video (0) */
193 CvRandState rnd_state;
197 /* Test seq main structure: */
198 typedef struct CvTestSeq_
201 CvFileStorage* pFileStorage;
202 CvTestSeqElem* pElemList;
220 CvSize cvTestSeqGetImageSize(CvTestSeq* pTestSeq){return cvSize(((CvTestSeq_*)(pTestSeq))->pImg->width,((CvTestSeq_*)(pTestSeq))->pImg->height);}
221 int cvTestSeqFrameNum(CvTestSeq* pTestSeq){return ((CvTestSeq_*)(pTestSeq))->FrameNum;}
223 static void icvTestSeqCreateMask(IplImage* pImg,IplImage* pImgMask, int threshold)
225 if(pImg->nChannels > 1)
227 cvCvtColor( pImg,pImgMask,CV_BGR2GRAY);
228 cvThreshold(pImgMask,pImgMask,threshold,255,CV_THRESH_BINARY);
232 cvThreshold(pImg,pImgMask,threshold,255,CV_THRESH_BINARY);
234 } /* icvTestSeqCreateMask */
237 static void icvTestSeqQureyFrameElem(CvTestSeqElem* p, int /*frame*/)
238 { /* Read next frame from avi for one record: */
239 if(p->type == SRC_TYPE_AVI)
242 //int frameNum = p->AVILen;
244 if(p->pAVI == NULL && p->pFileName)
245 { /* Open avi file if necessary: */
246 p->pAVI = 0;//cvCaptureFromFile(p->pFileName);
249 printf("WARNING!!! Can not open avi file %s\n",p->pFileName);
252 } /* Open avi file if necessary. */
255 //if(frame >= frameNum)
256 { /* Set new position: */
257 //int N = frame%frameNum;
260 N != (int)cvGetCaptureProperty(p->pAVI,CV_CAP_PROP_POS_FRAMES))
262 cvSetCaptureProperty(p->pAVI,CV_CAP_PROP_POS_FRAMES,N);
264 } /* Set new position. */
266 //pI = cvQueryFrame(p->pAVI);
269 if(pI->origin != p->pImg->origin)
270 cvFlip( pI, p->pImg, 0 );
277 if(p->pImgMask==NULL)
279 p->pImgMask = cvCreateImage(
280 cvSize(p->pImg->width,p->pImg->height),
283 icvTestSeqCreateMask(p->pImg,p->pImgMask,p->Mask?128:FG_BG_THRESHOLD);
287 } /* icvTestSeqQureyFrameElem */
289 /*------------- Recursive function to read all images, ------------------------*/
290 /*------------- videos and objects from config file. ------------------------*/
292 static CvTestSeqElem* icvTestSeqReadElemAll(CvTestSeq_* pTS, CvFileStorage* fs, const char* name);
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);
302 while(num--)SET_TRANS_0(p->pTrans+num);
305 if(p->FrameNum > p->TransNum)
306 { /* Allocate new transformation array: */
308 int num = p->FrameNum;
309 CvTSTrans* pNewTrans = (CvTSTrans*)cvAlloc(sizeof(CvTSTrans)*num);
314 pNewTrans[i] = p->pTrans[i%p->TransNum];
316 SET_TRANS_0(pNewTrans+i);
318 if(p->pTrans)cvFree(&p->pTrans);
319 p->pTrans = pNewTrans;
321 } /* Allocate new transformation array. */
322 } /* Allocate transformation array if necessary. */
324 static CvTestSeqElem* icvTestSeqReadElemOne(CvTestSeq_* pTS, CvFileStorage* fs, CvFileNode* node)
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);
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;
340 if((pVideoName || pVideoObjName ) && noise_type == CV_NOISE_NONE)
341 { /* Read other elements: */
342 if(pVideoName) pElem = icvTestSeqReadElemAll(pTS, fs, pVideoName);
346 pElem = icvTestSeqReadElemAll(pTS, fs, pVideoObjName);
347 for(pE=pElem;pE;pE=pE->next)
349 pE->ObjID = pTS->ObjNum;
350 pE->pObjName = pVideoObjName;
354 } /* Read other elements. */
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));
366 pElem->noise_type = noise_type;
367 cvRandInit( &pElem->rnd_state, 1, 0, 0,CV_RAND_NORMAL);
369 if(pFileName && pElem->noise_type == CV_NOISE_NONE)
370 { /* If AVI or BMP: */
371 size_t l = strlen(pFileName);
372 pElem->pFileName = pFileName;
374 pElem->type = SRC_TYPE_IMAGE;
375 if(cv_stricmp(".avi",pFileName+l-4) == 0)pElem->type = SRC_TYPE_AVI;
377 if(pElem->type == SRC_TYPE_IMAGE)
379 //pElem->pImg = cvLoadImage(pFileName);
383 if(pElem->pImgMask)cvReleaseImage(&(pElem->pImgMask));
385 pElem->pImgMask = cvCreateImage(
386 cvSize(pElem->pImg->width,pElem->pImg->height),
388 icvTestSeqCreateMask(pElem->pImg,pElem->pImgMask,FG_BG_THRESHOLD);
392 if(pElem->type == SRC_TYPE_AVI && pFileName)
394 //pElem->pAVI = cvCaptureFromFile(pFileName);
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);
409 printf("WARNING!!! Cannot open avi file %s\n",pFileName);
413 } /* If AVI or BMP. */
416 { /* Read positions: */
417 if(CV_NODE_IS_SEQ(pPosNode->tag))
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;
429 if(CV_NODE_IS_SEQ(pSizeNode->tag))
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;
438 if(AutoPos || AutoSize)
439 { /* Auto size and pos: */
441 int num = (pElem->type == SRC_TYPE_AVI)?pElem->AVILen:1;
444 pElem->pSize = (CvPoint2D32f*)cvAlloc(sizeof(CvPoint2D32f)*num);
445 pElem->SizeNum = num;
449 pElem->pPos = (CvPoint2D32f*)cvAlloc(sizeof(CvPoint2D32f)*num);
455 IplImage* pFG = NULL;
456 CvPoint2D32f* pPos = AutoPos?(pElem->pPos + i):NULL;
457 CvPoint2D32f* pSize = AutoSize?(pElem->pSize + i):NULL;
459 icvTestSeqQureyFrameElem(pElem,i);
460 pFG = pElem->pImgMask;
477 cvMoments( pElem->pImgMask, &m, 0 );
478 M00 = cvGetSpatialMoment( &m, 0, 0 );
480 if(M00 > 0 && pSize )
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);
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)));
497 { /* Another way to calculate y pos
498 * using object median:
500 int y0=0, y1=pFG->height-1;
501 for(y0=0; y0<pFG->height; ++y0)
504 CvScalar s = cvSum(cvGetRow(pFG, &m, y0));
505 if(s.val[0] > 255*7) break;
508 for(y1=pFG->height-1; y1>0; --y1)
511 CvScalar s = cvSum(cvGetRow(pFG, &m, y1));
512 if(s.val[0] > 255*7) break;
515 pPos->y = (y0+y1)*0.5f/(pFG->height-1);
520 //if(pElem->pAVI) cvReleaseCapture(&pElem->pAVI);
524 } /* End auto position creation. */
525 } /* Create new element. */
528 { /* Read transforms and: */
529 int FirstFrame, LastFrame;
530 CvTestSeqElem* p=pElem;
531 CvFileNode* pTransNode = NULL;
532 CvFileNode* pS = NULL;
535 CvSeq* pTransSeq = NULL;
538 pTransNode = cvGetFileNodeByName( fs, node,"Trans");
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,""));
547 pS = cvGetFileNodeByName( fs, node,"Shift");
549 pTransSeq = pTransNode?(CV_NODE_IS_SEQ(pTransNode->tag)?pTransNode->data.seq:NULL):NULL;
550 KeyFrameNum = pTransSeq?pTransSeq->total:1;
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))
558 FirstFrame = pElem->FrameBegin;
559 LastFrame = pElem->FrameBegin+pElem->FrameNum-1;
561 /* Calculate length of video and reallocate
562 * transformation array:
564 for(p=pElem; p; p=p->next)
567 v = cvReadIntByName( fs, node, "BG", -1 );
569 v = cvReadIntByName( fs, node, "Mask", -1 );
570 if(v!=-1)p->Mask = v;
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 );
576 int LastFrame = cvReadIntByName( fs, node, "LastFrame", p->FrameBegin+p->FrameNum-1 );
577 p->FrameNum = MIN(p->FrameNum,LastFrame - p->FrameBegin+1);
580 icvTestSeqAllocTrans(p);
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. */
591 for(p=pElem;p;p=p->next)
592 { /* Modify transformation to make autoshift: */
594 int num = p->FrameNum;
595 assert(num <= p->TransNum);
596 p->TransNum = MAX(1,num);
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;
609 newx *= p->pImg->width-1;
610 newy *= p->pImg->height-1;
613 pT->T[2] = -(pT->T[0]*newx+pT->T[1]*newy);
614 pT->T[5] = -(pT->T[3]*newx+pT->T[4]*newy);
616 } /* Modify transformation old. */
619 /* Initialize frame number array: */
620 KeyFrames[0] = FirstFrame;
622 if(pTransSeq&&KeyFrameNum>1)
625 for(i=0; i<KeyFrameNum; ++i)
627 CvFileNode* pTN = (CvFileNode*)cvGetSeqElem(pTransSeq,i);
628 KeyFrames[i] = cvReadIntByName(fs,pTN,"frame",-1);
631 if(KeyFrames[0]<0)KeyFrames[0]=FirstFrame;
632 if(KeyFrames[KeyFrameNum-1]<0)KeyFrames[KeyFrameNum-1]=LastFrame;
634 for(i0=0, i1=1; i1<KeyFrameNum;)
638 for(i1=i0+1; i1<KeyFrameNum && KeyFrames[i1]<0; i1++);
640 assert(i1<KeyFrameNum);
643 for(i=i0+1; i<i1; ++i)
645 KeyFrames[i] = cvRound(KeyFrames[i0] + (float)(i-i0)*(float)(KeyFrames[i1] - KeyFrames[i0])/(float)(i1-i0));
649 } /* Next key run. */
650 } /* Initialize frame number array. */
652 if(pTransNode || pTransSeq)
653 { /* More complex transform. */
655 CvFileNode* pTN = pTransSeq?(CvFileNode*)cvGetSeqElem(pTransSeq,0):pTransNode;
657 for(p=pElem; p; p=p->next)
659 //int trans_num = p->TransNum;
660 for(param=0; param_name[param]; ++param)
662 const char* name = param_name[param];
663 float defv = param_defval[param];
665 { /* Only one transform record: */
668 CvFileNode* node = cvGetFileNodeByName( fs, pTN,name);
669 if(node == NULL) continue;
670 val = cvReadReal(node,defv);
672 for(i=0; i<p->TransNum; ++i)
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);
681 { /* Several transforms: */
686 CvFileNode* pTN = (CvFileNode*)cvGetSeqElem(pTransSeq,0);
687 v0 = cvReadRealByName(fs, pTN,name,defv);
689 for(i1=1,i0=0; i1<KeyFrameNum; ++i1)
693 CvFileNode* pTN = (CvFileNode*)cvGetSeqElem(pTransSeq,i1);
694 CvFileNode* pVN = cvGetFileNodeByName(fs,pTN,name);
696 if(pVN)v1 = cvReadReal(pVN,defv);
697 else if(pVN == NULL && i1 == KeyFrameNum-1) v1 = defv;
703 if(i1==(KeyFrameNum-1)) f1++;
708 double t = (float)(i-f0);
709 int li = i - p->FrameBegin;
711 if(li>= p->TransNum) break;
712 if(KeyFrames[i1]>KeyFrames[i0]) t /=(float)(KeyFrames[i1]-KeyFrames[i0]);
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);
720 } /* Next transform. */
724 } /* Next value run. */
725 } /* Several transforms. */
726 } /* Next parameter. */
728 } /* More complex transform. */
729 } /* Read transfroms. */
733 } /* icvTestSeqReadElemOne */
735 static CvTestSeqElem* icvTestSeqReadElemAll(CvTestSeq_* pTS, CvFileStorage* fs, const char* name)
737 CvTestSeqElem* pElem = NULL;
740 if(name == NULL) return NULL;
742 node = cvGetFileNodeByName( fs, NULL, name );
746 printf("WARNING!!! - Video %s does not exist!\n", name);
750 printf("Read node %s\n",name);
752 if(CV_NODE_IS_SEQ(node->tag))
753 { /* Read all element in sequence: */
755 CvSeq* seq = node->data.seq;
756 CvTestSeqElem* pElemLast = NULL;
758 for(i=0; i<seq->total; ++i)
760 CvFileNode* next_node = (CvFileNode*)cvGetSeqElem( seq, i );
761 CvTestSeqElem* pElemNew = icvTestSeqReadElemOne(pTS, fs, next_node );
762 CvFileNode* pDurNode = cvGetFileNodeByName( fs, next_node,"Dur");
764 if(pElemNew == NULL )
766 printf("WARNING in parsing %s record!!! Cannot read array element\n", name);
770 if(pElem && pElemLast)
772 pElemLast->next = pElemNew;
775 pElemNew->FrameBegin = pElemLast->FrameBegin + pElemLast->FrameNum;
783 /* Find last element: */
784 for(pElemLast=pElemNew;pElemLast && pElemLast->next;pElemLast= pElemLast->next);
786 } /* Next element. */
787 } /* Read all element in sequence. */
789 { /* Read one element: */
790 pElem = icvTestSeqReadElemOne(pTS, fs, node );
795 } /* icvTestSeqReadElemAll */
797 static void icvTestSeqReleaseAll(CvTestSeqElem** ppElemList)
799 CvTestSeqElem* p = ppElemList[0];
803 CvTestSeqElem* pd = p;
806 //cvReleaseCapture(&p->pAVI);
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);
816 } /* Next element. */
818 ppElemList[0] = NULL;
820 } /* icvTestSeqReleaseAll */
822 CvTestSeq* cvCreateTestSeq(char* pConfigfile, char** videos, int numvideo, float Scale, int noise_type, double noise_ampl)
824 int size = sizeof(CvTestSeq_);
825 CvTestSeq_* pTS = (CvTestSeq_*)cvAlloc(size);
826 CvFileStorage* fs = cvOpenFileStorage( pConfigfile, NULL, CV_STORAGE_READ);
829 if(pTS == NULL || fs == NULL) return NULL;
832 pTS->pFileStorage = fs;
833 pTS->noise_ampl = noise_ampl;
834 pTS->noise_type = noise_type;
838 /* Read all videos: */
839 for (i=0; i<numvideo; ++i)
841 CvTestSeqElem* pElemNew = icvTestSeqReadElemAll(pTS, fs, videos[i]);
843 if(pTS->pElemList==NULL)pTS->pElemList = pElemNew;
846 CvTestSeqElem* p = NULL;
847 for(p=pTS->pElemList;p->next;p=p->next);
850 } /* Read all videos. */
852 { /* Calculate elements and image size and video length: */
853 CvTestSeqElem* p = pTS->pElemList;
855 CvSize MaxSize = {0,0};
858 for(p = pTS->pElemList; p; p=p->next, num++)
860 int FN = p->FrameBegin+p->FrameNum;
865 S.width = p->pImg->width;
866 S.height = p->pImg->height;
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;
876 if(MaxSize.width == 0)MaxSize.width = 320;
877 if(MaxSize.height == 0)MaxSize.height = 240;
879 MaxSize.width = cvRound(Scale*MaxSize.width);
880 MaxSize.height = cvRound(Scale*MaxSize.height);
882 pTS->pImg = cvCreateImage(MaxSize,IPL_DEPTH_8U,3);
883 pTS->pImgMask = cvCreateImage(MaxSize,IPL_DEPTH_8U,1);
884 pTS->FrameNum = MaxFN;
886 for(p = pTS->pElemList; p; p=p->next)
888 if(p->FrameNum<=0)p->FrameNum=MaxFN;
890 } /* Calculate elements and image size. */
892 return (CvTestSeq*)pTS;
894 } /* cvCreateTestSeq */
896 void cvReleaseTestSeq(CvTestSeq** ppTestSeq)
898 CvTestSeq_* pTS = (CvTestSeq_*)ppTestSeq[0];
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);
907 } /* cvReleaseTestSeq */
909 void cvTestSeqSetFrame(CvTestSeq* pTestSeq, int n)
911 CvTestSeq_* pTS = (CvTestSeq_*)pTestSeq;
915 IplImage* cvTestSeqQueryFrame(CvTestSeq* pTestSeq)
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);
926 if(pTS->CurFrame >= pTS->FrameNum) return NULL;
930 for(p=pTS->pElemList; p; p=p->next)
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;
939 if( p->FrameNum > 0 && (frame < 0 || frame >= p->FrameNum) )
940 { /* Current frame is out of range: */
941 //if(p->pAVI)cvReleaseCapture(&p->pAVI);
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;
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);
963 { /* Calcualte inverse matrix: */
964 CvMat mat = cvMat(2,3,CV_32F, pTrans->T);
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]);
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]);
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;
984 } /* Calculate transform matrix. */
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;;
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. */
1000 { /* Check for direct copy: */
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;
1010 /* Extract image and mask: */
1011 if(p->pImg->nChannels == 1)
1015 cvCvtColor( p->pImg,pImgAdd,CV_GRAY2BGR);
1019 cvGetQuadrangleSubPix( p->pImg, pImgAddG, pT);
1020 cvCvtColor( pImgAddG,pImgAdd,CV_GRAY2BGR);
1024 if(p->pImg->nChannels == 3)
1027 cvCopy(p->pImg, pImgAdd);
1029 cvGetQuadrangleSubPix( p->pImg, pImgAdd, pT);
1035 cvCopy(p->pImgMask, pImgMaskAdd);
1037 cvGetQuadrangleSubPix( p->pImgMask, pImgMaskAdd, pT);
1039 cvThreshold(pImgMaskAdd,pImgMaskAdd,128,255,CV_THRESH_BINARY);
1042 if(pTrans->C != 1 || pTrans->I != 0)
1043 { /* Intensity transformation: */
1044 cvScale(pImgAdd, pImgAdd, pTrans->C,pTrans->I);
1045 } /* Intensity transformation: */
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);
1057 { /* Update only mask: */
1058 cvOr(pImgMaskAdd, pImgMask, pImgMask);
1061 { /* Add image and mask to exist main image and mask: */
1063 { /* If image is background: */
1064 cvCopy( pImgAdd, pImg, NULL);
1067 { /* If image is foreground: */
1068 cvCopy( pImgAdd, pImg, pImgMaskAdd);
1070 cvOr(pImgMaskAdd, pImgMask, pImgMask);
1073 } /* For not noise. */
1075 { /* Process noise video: */
1077 if( p->noise_type == CV_NOISE_GAUSSIAN ||
1078 p->noise_type == CV_NOISE_UNIFORM)
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. */
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. */
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.*/
1100 if(pTS->noise_type != CV_NOISE_NONE)
1102 cvAddNoise(pImg,pTS->noise_type,pTS->noise_ampl);
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);
1111 if(pTS->IVar_CurI >= pTS->IVar_MaxI)
1112 pTS->IVar_CurDI = (float)-fabs(pTS->IVar_DI);
1114 if(pTS->IVar_CurI <= pTS->IVar_MinI)
1115 pTS->IVar_CurDI = (float)+fabs(pTS->IVar_DI);
1117 pTS->IVar_CurI += pTS->IVar_CurDI;
1123 cvReleaseImage(&pImgAdd);
1124 cvReleaseImage(&pImgAddG);
1125 cvReleaseImage(&pImgMaskAdd);
1129 } /*cvTestSeqQueryFrame*/
1131 IplImage* cvTestSeqGetFGMask(CvTestSeq* pTestSeq)
1133 return ((CvTestSeq_*)pTestSeq)->pImgMask;
1136 IplImage* cvTestSeqGetImage(CvTestSeq* pTestSeq)
1138 return ((CvTestSeq_*)pTestSeq)->pImg;
1141 int cvTestSeqGetObjectNum(CvTestSeq* pTestSeq)
1143 //return ((CvTestSeq_*)pTestSeq)->ListNum;
1144 return ((CvTestSeq_*)pTestSeq)->ObjNum;
1147 int cvTestSeqGetObjectPos(CvTestSeq* pTestSeq, int ObjIndex, CvPoint2D32f* pPos)
1149 CvTestSeq_* pTS = (CvTestSeq_*)pTestSeq;
1150 CvTestSeqElem* p = pTS->pElemList;
1151 if(pTS->CurFrame > pTS->FrameNum) return 0;
1153 for(p=pTS->pElemList; p; p=p->next)
1155 int frame = pTS->CurFrame - p->FrameBegin - 1;
1156 if(ObjIndex==p->ObjID && frame >= 0 && frame < p->FrameNum) break;
1159 if(p && p->pPos && p->PosNum>0)
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];
1168 #if 1 /* Transform using T filed in Trans: */
1170 float x = pPos->x * (p->pImg?(p->pImg->width-1):1);
1171 float y = pPos->y * (p->pImg?(p->pImg->height-1):1);
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];
1178 pPos->x /= p->pImg->width-1;
1179 pPos->y /= p->pImg->height-1;
1186 pPos->x = pPos->x * pTrans->Scale.x + pTrans->Shift.x;
1187 pPos->y = pPos->y * pTrans->Scale.y + pTrans->Shift.y;
1189 pPos->x *= pTS->pImg->width-1;
1190 pPos->y *= pTS->pImg->height-1;
1195 } /* cvTestSeqGetObjectPos */
1197 int cvTestSeqGetObjectSize(CvTestSeq* pTestSeq, int ObjIndex, CvPoint2D32f* pSize)
1199 CvTestSeq_* pTS = (CvTestSeq_*)pTestSeq;
1200 CvTestSeqElem* p = pTS->pElemList;
1201 if(pTS->CurFrame > pTS->FrameNum) return 0;
1203 for(p=pTS->pElemList; p; p=p->next)
1205 int frame = pTS->CurFrame - p->FrameBegin - 1;
1206 if(ObjIndex==p->ObjID && frame >= 0 && frame < p->FrameNum) break;
1209 if(p && p->pSize && p->SizeNum>0)
1212 int frame = pTS->CurFrame - p->FrameBegin - 1;
1214 if(frame < 0 || frame >= p->FrameNum) return 0;
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];
1220 #if 1 /* Transform using T filed in Trans: */
1222 float x = pSize->x * (p->pImg?(p->pImg->width-1):1);
1223 float y = pSize->y * (p->pImg?(p->pImg->height-1):1);
1227 dx1 = (float)fabs(pTrans->T[0]*x+pTrans->T[1]*y);
1228 dy1 = (float)fabs(pTrans->T[3]*x+pTrans->T[4]*y);
1230 dx2 = (float)fabs(pTrans->T[0]*x - pTrans->T[1]*y);
1231 dy2 = (float)fabs(pTrans->T[3]*x - pTrans->T[4]*y);
1233 pSize->x = MAX(dx1,dx2);
1234 pSize->y = MAX(dy1,dy2);
1238 pSize->x /= p->pImg->width-1;
1239 pSize->y /= p->pImg->height-1;
1246 pSize->x = pSize->x * pTrans->Scale.x;
1247 pSize->y = pSize->y * pTrans->Scale.y;
1249 pSize->x *= pTS->pImg->width-1;
1250 pSize->y *= pTS->pImg->height-1;
1256 } /* cvTestSeqGetObjectSize */
1258 /* Add noise to finile image: */
1259 void cvTestSeqAddNoise(CvTestSeq* pTestSeq, int noise_type, double noise_ampl)
1261 CvTestSeq_* pTS = (CvTestSeq_*)pTestSeq;
1262 pTS->noise_type = noise_type;
1263 pTS->noise_ampl = noise_ampl;
1266 /* Add Intensity variation: */
1267 void cvTestSeqAddIntensityVariation(CvTestSeq* pTestSeq, float DI_per_frame, float MinI, float MaxI)
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;
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;
1285 cvRandInit( &local_rnd_state, 1, 0, 0,CV_RAND_NORMAL);
1288 if(rnd_state == NULL)rnd_state = &local_rnd_state;
1290 if( noise_type == CV_NOISE_GAUSSIAN ||
1291 noise_type == CV_NOISE_UNIFORM)
1292 { /* Gaussan and uniform additive noise: */
1295 if( noise_type == CV_NOISE_GAUSSIAN)
1297 rnd_state->disttype = CV_RAND_NORMAL;
1298 cvRandSetRange( rnd_state, Ampl, 0, -1 );
1299 if(Ampl <= 0) set_zero = 1;
1302 if( noise_type == CV_NOISE_UNIFORM)
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;
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);
1322 } /* Gaussan and uniform additive noise. */
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. */
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;
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);
1353 cvRandSetRange( rnd_state, 0, 255, -1 );
1354 cvRand(rnd_state, pImgVal);
1355 cvThreshold(pImgVal,pImgVal,128, 255, CV_THRESH_BINARY );
1357 pImgAdd->nChannels>0?pImgVal:NULL,
1358 pImgAdd->nChannels>1?pImgVal:NULL,
1359 pImgAdd->nChannels>2?pImgVal:NULL,
1360 pImgAdd->nChannels>3?pImgVal:NULL,
1362 cvCopy(pImgAdd, pImg, pImgMaskBin);
1363 cvReleaseImage(&pImgMask);
1364 cvReleaseImage(&pImgMaskBin);
1365 cvReleaseImage(&pImgVal);
1367 } /* Salt and pepper. */
1369 cvReleaseImage(&pImgAdd);