int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* mlms){ int version = vsReadFileVersion(f); if(version<1) // old format or unknown return VS_ERROR; if(version>1){ vs_log_error(modname,"Version of VID.STAB file too large: got %i, expect <= 1", version); return VS_ERROR; } assert(mlms); // initial number of frames, but it will automatically be increaseed vs_vector_init(mlms,1024); int index; int oldindex = 0; LocalMotions lms; while((index = vsReadFromFile(f,&lms)) != VS_ERROR){ if(index > oldindex+1){ vs_log_info(modname,"VID.STAB file: index of frames is not continuous %i -< %i", oldindex, index); } if(index<1){ vs_log_info(modname,"VID.STAB file: Frame number < 1 (%i)", index); } else { vs_vector_set_dup(mlms,index-1,&lms, sizeof(LocalMotions)); } oldindex=index; } return VS_OK; }
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; }
int vsMotionDetectInit(VSMotionDetect* md, const VSMotionDetectConfig* conf, const VSFrameInfo* fi){ assert(md && fi); md->conf = *conf; md->fi = *fi; if(fi->pFormat<=PF_NONE || fi->pFormat==PF_PACKED || fi->pFormat>=PF_NUMBER) { vs_log_warn(md->conf.modName, "unsupported Pixel Format (%i)\n", md->fi.pFormat); return VS_ERROR; } #ifdef USE_OMP if(md->conf.numThreads==0) md->conf.numThreads=VS_MAX(omp_get_max_threads()*0.8,1); vs_log_info(md->conf.modName, "Multitheading: use %i threads\n",md->conf.numThreads); #endif vsFrameAllocate(&md->prev, &md->fi); if (vsFrameIsNull(&md->prev)) { vs_log_error(md->conf.modName, "malloc failed"); return VS_ERROR; } vsFrameNull(&md->curr); vsFrameNull(&md->currorig); vsFrameNull(&md->currtmp); md->hasSeenOneFrame = 0; md->frameNum = 0; // TODO: get rid of shakiness parameter in the long run md->conf.shakiness = VS_MIN(10,VS_MAX(1,md->conf.shakiness)); md->conf.accuracy = VS_MIN(15,VS_MAX(1,md->conf.accuracy)); if (md->conf.accuracy < md->conf.shakiness / 2) { vs_log_info(md->conf.modName, "Accuracy should not be lower than shakiness/2 -- fixed"); md->conf.accuracy = md->conf.shakiness / 2; } if (md->conf.accuracy > 9 && md->conf.stepSize > 6) { vs_log_info(md->conf.modName, "For high accuracy use lower stepsize -- set to 6 now"); md->conf.stepSize = 6; // maybe 4 } int minDimension = VS_MIN(md->fi.width, md->fi.height); // shift: shakiness 1: height/40; 10: height/4 // md->maxShift = VS_MAX(4,(minDimension*md->conf.shakiness)/40); // size: shakiness 1: height/40; 10: height/6 (clipped) // md->fieldSize = VS_MAX(4,VS_MIN(minDimension/6, (minDimension*md->conf.shakiness)/40)); // fixed size and shift now int maxShift = VS_MAX(16, minDimension/7); int fieldSize = VS_MAX(16, minDimension/10); int fieldSizeFine = VS_MAX(6, minDimension/60); #if defined(USE_SSE2) || defined(USE_SSE2_ASM) fieldSize = (fieldSize / 16 + 1) * 16; fieldSizeFine = (fieldSizeFine / 16 + 1) * 16; #endif if (!initFields(md, &md->fieldscoarse, fieldSize, maxShift, md->conf.stepSize, 1, 0, md->conf.contrastThreshold)) { return VS_ERROR; } // for the fine check we use a smaller size and smaller maximal shift (=size) if (!initFields(md, &md->fieldsfine, fieldSizeFine, fieldSizeFine, 2, 1, fieldSizeFine, md->conf.contrastThreshold/2)) { return VS_ERROR; } vsFrameAllocate(&md->curr,&md->fi); vsFrameAllocate(&md->currtmp, &md->fi); md->initialized = 2; return VS_OK; }