-double MotionScan::step_to_angle(int step, double center)
-{
- if(step < angle_steps / 2)
- {
- return center - angle_step * (angle_steps / 2 - step);
- }
- else
- if(step > angle_steps / 2)
- {
- return center + angle_step * (step - angle_steps / 2);
- }
- else
- {
- return center;
- }
-}
-
-#ifdef STDDEV_TEST
-static int compare(const void *p1, const void *p2)
-{
- double value1 = *(double*)p1;
- double value2 = *(double*)p2;
-
-//printf("compare %d value1=%f value2=%f\n", __LINE__, value1, value2);
- return value1 > value2;
-}
-#endif
-
-// reject vectors based on content. It's the reason Goog can't stabilize timelapses.
-//#define STDDEV_TEST
-
-// pixel accurate motion search
-void MotionScan::pixel_search(int &x_result, int &y_result, double &r_result)
-{
-// reduce level of detail until enough steps
- while(current_downsample > 1 &&
- ((block_x2 - block_x1) / current_downsample < MIN_DOWNSAMPLED_SIZE ||
- (block_y2 - block_y1) / current_downsample < MIN_DOWNSAMPLED_SIZE
- ||
- (scan_x2 - scan_x1) / current_downsample < MIN_DOWNSAMPLED_SCAN ||
- (scan_y2 - scan_y1) / current_downsample < MIN_DOWNSAMPLED_SCAN
- ))
- {
- current_downsample /= 2;
- }
-
-
-
-// create downsampled images.
-// Need to keep entire frame to search for rotation.
- int downsampled_prev_w = previous_frame_arg->get_w() / current_downsample;
- int downsampled_prev_h = previous_frame_arg->get_h() / current_downsample;
- int downsampled_current_w = current_frame_arg->get_w() / current_downsample;
- int downsampled_current_h = current_frame_arg->get_h() / current_downsample;
-
-// printf("MotionScan::pixel_search %d current_downsample=%d current_frame_arg->get_w()=%d downsampled_current_w=%d\n",
-// __LINE__,
-// current_downsample,
-// current_frame_arg->get_w(),
-// downsampled_current_w);
-
- x_steps = (scan_x2 - scan_x1) / current_downsample;
- y_steps = (scan_y2 - scan_y1) / current_downsample;
-
-// in rads
- double test_angle1 = atan2((double)downsampled_current_h / 2 - 1, (double)downsampled_current_w / 2);
- double test_angle2 = atan2((double)downsampled_current_h / 2, (double)downsampled_current_w / 2 - 1);
-
-// in deg
- angle_step = 360.0f * fabs(test_angle1 - test_angle2) / 2 / M_PI;
-
-// printf("MotionScan::pixel_search %d test_angle1=%f test_angle2=%f angle_step=%f\n",
-// __LINE__,
-// 360.0f * test_angle1 / 2 / M_PI,
-// 360.0f * test_angle2 / 2 / M_PI,
-// angle_step);
-
-
- if(do_rotate && angle_step < rotation_range)
- {
- angle_steps = 1 + (int)((scan_angle2 - scan_angle1) / angle_step + 0.5);
- }
- else
- {
- angle_steps = 1;
- }
-
-
- if(current_downsample > 1)
- {
- if(!downsampled_previous ||
- downsampled_previous->get_w() != downsampled_prev_w ||
- downsampled_previous->get_h() != downsampled_prev_h)
- {
- delete downsampled_previous;
- downsampled_previous = new VFrame();
- downsampled_previous->set_use_shm(0);
- downsampled_previous->reallocate(0,
- -1,
- 0,
- 0,
- 0,
- downsampled_prev_w + 1,
- downsampled_prev_h + 1,
- previous_frame_arg->get_color_model(),
- -1);
- }
-
- if(!downsampled_current ||
- downsampled_current->get_w() != downsampled_current_w ||
- downsampled_current->get_h() != downsampled_current_h)
- {
- delete downsampled_current;
- downsampled_current = new VFrame();
- downsampled_current->set_use_shm(0);
- downsampled_current->reallocate(0,
- -1,
- 0,
- 0,
- 0,
- downsampled_current_w + 1,
- downsampled_current_h + 1,
- current_frame_arg->get_color_model(),
- -1);
- }
-
-
- downsample_frame(downsampled_previous,
- previous_frame_arg,
- current_downsample);
- downsample_frame(downsampled_current,
- current_frame_arg,
- current_downsample);
- previous_frame = downsampled_previous;
- current_frame = downsampled_current;
-
- }
- else
- {
- previous_frame = previous_frame_arg;
- current_frame = current_frame_arg;
- }
-
-
-
-// printf("MotionScan::pixel_search %d x_steps=%d y_steps=%d angle_steps=%d total_steps=%d\n",
-// __LINE__,
-// x_steps,
-// y_steps,
-// angle_steps,
-// total_steps);
-
-
-
-// test variance of constant macroblock
- int color_model = current_frame->get_color_model();
- int pixel_size = BC_CModels::calculate_pixelsize(color_model);
- int row_bytes = current_frame->get_bytes_per_line();
- int block_w = block_x2 - block_x1;
- int block_h = block_y2 - block_y1;
-
- unsigned char *current_ptr =
- current_frame->get_rows()[block_y1 / current_downsample] +
- (block_x1 / current_downsample) * pixel_size;
- unsigned char *previous_ptr =
- previous_frame->get_rows()[scan_y1 / current_downsample] +
- (scan_x1 / current_downsample) * pixel_size;
-
-
-
-// test detail in prev & current frame
- double range1 = calculate_range(current_ptr,
- row_bytes,
- block_w / current_downsample,
- block_h / current_downsample,
- color_model);
-
- if(range1 < 1)
- {
-printf("MotionScan::pixel_search %d range fail range1=%f\n", __LINE__, range1);
- failed = 1;
- return;
- }
-
- double range2 = calculate_range(previous_ptr,
- row_bytes,
- block_w / current_downsample,
- block_h / current_downsample,
- color_model);
-
- if(range2 < 1)
- {
-printf("MotionScan::pixel_search %d range fail range2=%f\n", __LINE__, range2);
- failed = 1;
- return;
- }
-
-
-// create rotated images
- if(rotated_current &&
- (total_rotated != angle_steps ||
- rotated_current[0]->get_w() != downsampled_current_w ||
- rotated_current[0]->get_h() != downsampled_current_h))
- {
- for(int i = 0; i < total_rotated; i++)
- {
- delete rotated_current[i];
- }
-
- delete [] rotated_current;
- rotated_current = 0;
- total_rotated = 0;
- }
-
- if(do_rotate)
- {
- total_rotated = angle_steps;
-
-
- if(!rotated_current)
- {
- rotated_current = new VFrame*[total_rotated];
- bzero(rotated_current, sizeof(VFrame*) * total_rotated);
- }
-
-// printf("MotionScan::pixel_search %d total_rotated=%d w=%d h=%d block_w=%d block_h=%d\n",
-// __LINE__,
-// total_rotated,
-// downsampled_current_w,
-// downsampled_current_h,
-// (block_x2 - block_x1) / current_downsample,
-// (block_y2 - block_y1) / current_downsample);
- for(int i = 0; i < angle_steps; i++)
- {
-
-// printf("MotionScan::pixel_search %d w=%d h=%d x=%d y=%d angle=%f\n",
-// __LINE__,
-// downsampled_current_w,
-// downsampled_current_h,
-// (block_x1 + block_x2) / 2 / current_downsample,
-// (block_y1 + block_y2) / 2 / current_downsample,
-// step_to_angle(i, r_result));
-
-// printf("MotionScan::pixel_search %d i=%d rotated_current[i]=%p\n",
-// __LINE__,
-// i,
-// rotated_current[i]);
- if(!rotated_current[i])