int test_store_restore(TestData* testdata){ MotionDetect md; test_bool(initMotionDetect(&md, &testdata->fi, "test") == VS_OK); test_bool(configureMotionDetect(&md)== VS_OK); LocalMotions lms; int i; for(i=0; i<2; i++){ test_bool(motionDetection(&md, &lms,&testdata->frames[i])== VS_OK); if (i==0) vs_vector_del(&lms); } FILE* f = fopen("lmtest","w"); storeLocalmotions(f,&lms); fclose(f); f = fopen("lmtest","r"); LocalMotions test = restoreLocalmotions(f); fclose(f); storeLocalmotions(stderr,&test); compare_localmotions(&lms,&test); fprintf(stderr,"\n** LM and LMS OKAY\n"); f = fopen("lmstest","w"); md.frameNum=1; prepareFile(&md,f); writeToFile(&md,f,&lms); md.frameNum=2; writeToFile(&md,f,&test); fclose(f); f = fopen("lmstest","r"); test_bool(readFileVersion(f)==1); LocalMotions read1; test_bool(readFromFile(f,&read1)==1); compare_localmotions(&lms,&read1); LocalMotions read2; test_bool(readFromFile(f,&read2)==2); compare_localmotions(&test,&read2); fclose(f); fprintf(stderr,"** Reading file stepwise OKAY\n"); vs_vector_del(&read1); vs_vector_del(&read2); vs_vector_del(&test); vs_vector_del(&lms); f = fopen("lmstest","r"); ManyLocalMotions mlms; test_bool(readLocalMotionsFile(f,&mlms)==VS_OK); test_bool(vs_vector_size(&mlms)==2); fprintf(stderr,"** Entire file routine OKAY\n\n"); for(i=0; i< vs_vector_size(&mlms); i++){ if(MLMGet(&mlms,i)) vs_vector_del(MLMGet(&mlms,i)); } vs_vector_del(&mlms); return 1; }
int test_store_restore(TestData* testdata){ VSMotionDetectConfig mdconf = vsMotionDetectGetDefaulfConfig("test_motionDetect"); VSMotionDetect md; test_bool(vsMotionDetectInit(&md, &mdconf, &testdata->fi) == VS_OK); LocalMotions lms; int i; for(i=0; i<2; i++){ test_bool(vsMotionDetection(&md, &lms,&testdata->frames[i])== VS_OK); if (i==0) vs_vector_del(&lms); } FILE* f = fopen("lmtest","w"); vsStoreLocalmotions(f,&lms); fclose(f); f = fopen("lmtest","r"); LocalMotions test = vsRestoreLocalmotions(f); fclose(f); vsStoreLocalmotions(stderr,&test); compare_localmotions(&lms,&test); fprintf(stderr,"\n** LM and LMS OKAY\n"); f = fopen("lmstest","w"); md.frameNum=1; vsPrepareFile(&md,f); vsWriteToFile(&md,f,&lms); md.frameNum=2; vsWriteToFile(&md,f,&test); fclose(f); f = fopen("lmstest","r"); test_bool(vsReadFileVersion(f)==1); LocalMotions read1; test_bool(vsReadFromFile(f,&read1)==1); compare_localmotions(&lms,&read1); LocalMotions read2; test_bool(vsReadFromFile(f,&read2)==2); compare_localmotions(&test,&read2); fclose(f); fprintf(stderr,"** Reading file stepwise OKAY\n"); vs_vector_del(&read1); vs_vector_del(&read2); vs_vector_del(&test); vs_vector_del(&lms); f = fopen("lmstest","r"); VSManyLocalMotions mlms; test_bool(vsReadLocalMotionsFile(f,&mlms)==VS_OK); test_bool(vs_vector_size(&mlms)==2); fprintf(stderr,"** Entire file routine OKAY\n\n"); for(i=0; i< vs_vector_size(&mlms); i++){ if(VSMLMGet(&mlms,i)) vs_vector_del(VSMLMGet(&mlms,i)); } vs_vector_del(&mlms); return 1; }
int compare_localmotions(const LocalMotions* lms1, const LocalMotions* lms2){ test_bool(vs_vector_size(lms1) == vs_vector_size(lms2)); int i; for(i=0; i<vs_vector_size(lms1); i++){ test_bool(LMGet(lms1,i)->v.x == LMGet(lms2,i)->v.x); test_bool(LMGet(lms1,i)->v.y == LMGet(lms2,i)->v.y); } return 1; }
int localmotions2TransformsSimple(TransformData* td, const ManyLocalMotions* motions, Transformations* trans ){ int i; int len = vs_vector_size(motions); assert(trans->len==0 && trans->ts == 0); trans->ts = vs_malloc(sizeof(Transform)*len ); for(i=0; i< vs_vector_size(motions); i++) { trans->ts[i]=simpleMotionsToTransform(td,MLMGet(motions,i)); // storeLocalmotions(stderr,MLMGet(motions,i)); // storeTransform(stderr,&trans->ts[i]); } trans->len=len; return VS_OK; }
/// restores local motions from file LocalMotions vsRestoreLocalmotions(FILE* f){ LocalMotions lms; int i; char c; int len; vs_vector_init(&lms,0); if(fscanf(f,"List %i [", &len) != 1) { vs_log_error(modname, "Cannot parse localmotions list expect 'List len ['!\n"); return lms; } if (len>0){ vs_vector_init(&lms,len); for (i=0; i<len; i++){ if(i>0) while((c=fgetc(f)) && c!=',' && c!=EOF); LocalMotion lm = restoreLocalmotion(f); vs_vector_append_dup(&lms,&lm,sizeof(LocalMotion)); } } if(len != vs_vector_size(&lms)){ vs_log_error(modname, "Cannot parse the given number of localmotions!\n"); return lms; } while((c=fgetc(f)) && c!=']' && c!=EOF); if(c==EOF){ vs_log_error(modname, "Cannot parse localmotions list missing ']'!\n"); return lms; } return lms; }
int* localmotions_gety(const LocalMotions* localmotions){ int len = vs_vector_size(localmotions); int* ys = vs_malloc(sizeof(int) * len); int i; for (i=0; i<len; i++){ ys[i]=LMGet(localmotions,i)->v.y; } return ys; }
int vsStoreLocalmotions(FILE* f, const LocalMotions* lms){ int len = vs_vector_size(lms); int i; fprintf(f,"List %i [",len); for (i=0; i<len; i++){ if(i>0) fprintf(f,","); if(storeLocalmotion(f,LMGet(lms,i)) <= 0) return 0; } fprintf(f,"]"); return 1; }
Transform simpleMotionsToTransform(TransformData* td, const LocalMotions* motions){ int center_x = 0; int center_y = 0; Transform t = null_transform(); if(motions==0) return t; int num_motions=vs_vector_size(motions); double *angles = (double*) vs_malloc(sizeof(double) * num_motions); LocalMotion meanmotion; int i; if(num_motions < 1) return t; // calc center point of all remaining fields for (i = 0; i < num_motions; i++) { center_x += LMGet(motions,i)->f.x; center_y += LMGet(motions,i)->f.y; } center_x /= num_motions; center_y /= num_motions; // cleaned mean meanmotion = cleanmean_localmotions(motions); // figure out angle if (num_motions < 6) { // the angle calculation is inaccurate for 5 and less fields t.alpha = 0; } else { for (i = 0; i < num_motions; i++) { // substract avg and calc angle LocalMotion m = sub_localmotion(LMGet(motions,i),&meanmotion); angles[i] = calcAngle(&m, center_x, center_y); } double min, max; t.alpha = -cleanmean(angles, num_motions, &min, &max); if (max - min > td->maxAngleVariation) { t.alpha = 0; vs_log_info(td->modName, "too large variation in angle(%f)\n", max-min); } } vs_free(angles); // compensate for off-center rotation double p_x = (center_x - td->fiSrc.width / 2); double p_y = (center_y - td->fiSrc.height / 2); t.x = meanmotion.v.x + (cos(t.alpha) - 1) * p_x - sin(t.alpha) * p_y; t.y = meanmotion.v.y + sin(t.alpha) * p_x + (cos(t.alpha) - 1) * p_y; return t; }
char* lm_serializer(LocalMotions *lms, int length) { std::ostringstream oss; int size = vs_vector_size(lms); for (int i = 0; i < size; ++i) { LocalMotion* lm = (LocalMotion*) vs_vector_get(lms, i); oss << lm->v.x << ' '; oss << lm->v.y << ' '; oss << lm->f.x << ' '; oss << lm->f.y << ' '; oss << lm->f.size << ' '; oss << lm->contrast << ' '; oss << lm->match << ' '; } return strdup(oss.str().c_str()); }
/** * cleanmean_localmotions: calulcates the cleaned mean of a vector * of local motions considering * * Parameters: * localmotions : vs_vector of local motions * Return value: * A localmotion with vec with x and y being the cleaned mean * (meaning upper and lower pentile are removed) of * all local motions. all other fields are 0. * Preconditions: * size of vector >0 * Side effects: * None */ LocalMotion cleanmean_localmotions(const LocalMotions* localmotions) { int len = vs_vector_size(localmotions); int i, cut = len / 5; int* xs = localmotions_getx(localmotions); int* ys = localmotions_gety(localmotions); LocalMotion m = null_localmotion(); m.v.x=0; m.v.y=0; qsort(xs,len, sizeof(int), cmp_int); for (i = cut; i < len - cut; i++){ // all but cutted m.v.x += xs[i]; } qsort(ys, len, sizeof(int), cmp_int); for (i = cut; i < len - cut; i++){ // all but cutted m.v.y += ys[i]; } vs_free(xs); vs_free(ys); m.v.x/=(len - (2.0 * cut)); m.v.y/=(len - (2.0 * cut)); return m; }
int vsMotionDetection(VSMotionDetect* md, LocalMotions* motions, VSFrame *frame) { assert(md->initialized==2); md->currorig = *frame; // smoothen image to do better motion detection // (larger stepsize or eventually gradient descent (need higher resolution)) if (md->fi.pFormat > PF_PACKED) { // we could calculate a grayscale version and use the PLANAR stuff afterwards // so far smoothing is only implemented for PLANAR vsFrameCopy(&md->curr, frame, &md->fi); } else { // box-kernel smoothing (plain average of pixels), which is fine for us boxblurPlanar(&md->curr, frame, &md->currtmp, &md->fi, md->conf.stepSize*1/*1.4*/, BoxBlurNoColor); // two times yields tent-kernel smoothing, which may be better, but I don't // think we need it //boxblurPlanar(md->curr, md->curr, md->currtmp, &md->fi, md->stepSize*1, // BoxBlurNoColor); } if (md->hasSeenOneFrame) { LocalMotions motionscoarse; LocalMotions motionsfine; vs_vector_init(&motionsfine,0); // md->curr = frame; if (md->fi.pFormat > PF_PACKED) { motionscoarse = calcTransFields(md, &md->fieldscoarse, calcFieldTransPacked, contrastSubImgPacked); } else { // PLANAR motionscoarse = calcTransFields(md, &md->fieldscoarse, calcFieldTransPlanar, contrastSubImgPlanar); } int num_motions = vs_vector_size(&motionscoarse); if (num_motions < 1) { vs_log_warn(md->conf.modName, "too low contrast. \ (no translations are detected in frame %i)\n", md->frameNum); }else{
static void init_apply_data( mlt_filter filter, mlt_frame frame, VSPixelFormat vs_format, int width, int height ) { mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); vs_data* data = (vs_data*)filter->child; vs_apply* apply_data = (vs_apply*)calloc( 1, sizeof(vs_apply) ); char* filename = mlt_properties_get( properties, "results" ); memset( apply_data, 0, sizeof( vs_apply ) ); mlt_log_info( MLT_FILTER_SERVICE(filter), "Load results from %s\n", filename ); // Initialize the VSTransformConfig get_transform_config( &apply_data->conf, filter, frame ); // Initialize VSTransformData VSFrameInfo fi_src, fi_dst; vsFrameInfoInit( &fi_src, width, height, vs_format ); vsFrameInfoInit( &fi_dst, width, height, vs_format ); vsTransformDataInit( &apply_data->td, &apply_data->conf, &fi_src, &fi_dst ); // Initialize VSTransformations vsTransformationsInit( &apply_data->trans ); // Convert file name string encoding. mlt_properties_from_utf8( properties, "results", "_results" ); filename = mlt_properties_get( properties, "_results" ); // Load the motions from the analyze step and convert them to VSTransformations FILE* f = fopen( filename, "r" ); VSManyLocalMotions mlms; if( vsReadLocalMotionsFile( f, &mlms ) == VS_OK ) { int i = 0; mlt_log_info( MLT_FILTER_SERVICE(filter), "Successfully loaded %d motions\n", vs_vector_size( &mlms ) ); vsLocalmotions2Transforms( &apply_data->td, &mlms, &apply_data->trans ); vsPreprocessTransforms( &apply_data->td, &apply_data->trans ); // Free the MultipleLocalMotions for( i = 0; i < vs_vector_size( &mlms ); i++ ) { LocalMotions* lms = (LocalMotions*)vs_vector_get( &mlms, i ); if( lms ) { vs_vector_del( lms ); } } vs_vector_del( &mlms ); data->apply_data = apply_data; } else { mlt_log_error( MLT_FILTER_SERVICE(filter), "Can not read results file: %s\n", filename ); destory_apply_data( apply_data ); data->apply_data = NULL; } if( f ) { fclose( f ); } }