Compute multiple global motions and pick best by error adv. Modify ransac to keep the N best global motions by num_inliers and variance rather than a single one. Compute the error advantage for each in encode_frame_internal(), and use the best as the global motion for that pair of <target, reference> frames. Improvements for different values of N: N %PSNR gain on lowres 1 (current impl) 1.287 2 1.328 4 1.370 8 1.419 16 1.427 32 1.439 Change-Id: Ic0c9066a3f175a5ea0a78828cd244104e70144ba
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 6ab7c02..55a0a91 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -26,6 +26,7 @@ #include "av1/common/entropy.h" #include "av1/common/entropymode.h" #include "av1/common/idct.h" +#include "av1/common/mv.h" #include "av1/common/mvref_common.h" #include "av1/common/pred_common.h" #include "av1/common/quant_common.h" @@ -5041,23 +5042,45 @@ !cpi->global_motion_search_done) { YV12_BUFFER_CONFIG *ref_buf; int frame; - double erroradvantage = 0; - double params[8] = { 0, 0, 1, 0, 0, 1, 0, 0 }; + double params_by_motion[RANSAC_NUM_MOTIONS * (MAX_PARAMDIM - 1)]; + const double *params_this_motion; + int inliers_by_motion[RANSAC_NUM_MOTIONS]; + WarpedMotionParams tmp_wm_params; + static const double kInfiniteErrAdv = 1e12; + static const double kIdentityParams[MAX_PARAMDIM - 1] = { + 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 + }; + for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) { ref_buf = get_ref_frame_buffer(cpi, frame); if (ref_buf) { TransformationType model; aom_clear_system_state(); for (model = ROTZOOM; model < GLOBAL_TRANS_TYPES; ++model) { - if (compute_global_motion_feature_based(model, cpi->Source, ref_buf, + double best_erroradvantage = kInfiniteErrAdv; + + // Initially set all params to identity. + for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) { + memcpy(params_by_motion + (MAX_PARAMDIM - 1) * i, kIdentityParams, + (MAX_PARAMDIM - 1) * sizeof(*params_by_motion)); + } + + compute_global_motion_feature_based( + model, cpi->Source, ref_buf, #if CONFIG_AOM_HIGHBITDEPTH - cpi->common.bit_depth, + cpi->common.bit_depth, #endif // CONFIG_AOM_HIGHBITDEPTH - params)) { - convert_model_to_params(params, &cm->global_motion[frame]); - if (cm->global_motion[frame].wmtype != IDENTITY) { - erroradvantage = refine_integerized_param( - &cm->global_motion[frame], cm->global_motion[frame].wmtype, + inliers_by_motion, params_by_motion, RANSAC_NUM_MOTIONS); + + for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) { + if (inliers_by_motion[i] == 0) continue; + + params_this_motion = params_by_motion + (MAX_PARAMDIM - 1) * i; + convert_model_to_params(params_this_motion, &tmp_wm_params); + + if (tmp_wm_params.wmtype != IDENTITY) { + const double erroradv_this_motion = refine_integerized_param( + &tmp_wm_params, tmp_wm_params.wmtype, #if CONFIG_AOM_HIGHBITDEPTH xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd, #endif // CONFIG_AOM_HIGHBITDEPTH @@ -5065,12 +5088,23 @@ ref_buf->y_stride, cpi->Source->y_buffer, cpi->Source->y_width, cpi->Source->y_height, cpi->Source->y_stride, 3); - if (erroradvantage > - gm_advantage_thresh[cm->global_motion[frame].wmtype]) { - set_default_gmparams(&cm->global_motion[frame]); + if (erroradv_this_motion < best_erroradvantage) { + best_erroradvantage = erroradv_this_motion; + // Save the wm_params modified by refine_integerized_param() + // rather than motion index to avoid rerunning refine() below. + memcpy(&(cm->global_motion[frame]), &tmp_wm_params, + sizeof(WarpedMotionParams)); } } } + + // If the best error advantage found doesn't meet the threshold for + // this motion type, revert to IDENTITY. + if (best_erroradvantage > + gm_advantage_thresh[cm->global_motion[frame].wmtype]) { + set_default_gmparams(&cm->global_motion[frame]); + } + if (cm->global_motion[frame].wmtype != IDENTITY) break; } aom_clear_system_state();
diff --git a/av1/encoder/global_motion.c b/av1/encoder/global_motion.c index 5a5e352..7471bfc 100644 --- a/av1/encoder/global_motion.c +++ b/av1/encoder/global_motion.c
@@ -238,24 +238,6 @@ } } -// computes global motion parameters by fitting a model using RANSAC -static int compute_global_motion_params(TransformationType type, - int *correspondences, - int num_correspondences, - double *params) { - int result; - int num_inliers = 0; - RansacFunc ransac = get_ransac_type(type); - if (ransac == NULL) return 0; - - result = ransac(correspondences, num_correspondences, &num_inliers, params); - if (!result && num_inliers < MIN_INLIER_PROB * num_correspondences) { - result = 1; - num_inliers = 0; - } - return num_inliers; -} - #if CONFIG_AOM_HIGHBITDEPTH unsigned char *downconvert_frame(YV12_BUFFER_CONFIG *frm, int bit_depth) { int i, j; @@ -271,20 +253,20 @@ } #endif -int compute_global_motion_feature_based(TransformationType type, - YV12_BUFFER_CONFIG *frm, - YV12_BUFFER_CONFIG *ref, +int compute_global_motion_feature_based( + TransformationType type, YV12_BUFFER_CONFIG *frm, YV12_BUFFER_CONFIG *ref, #if CONFIG_AOM_HIGHBITDEPTH - int bit_depth, + int bit_depth, #endif - double *params) { + int *num_inliers_by_motion, double *params_by_motion, int num_motions) { + int i; int num_frm_corners, num_ref_corners; int num_correspondences; int *correspondences; - int num_inliers; int frm_corners[2 * MAX_CORNERS], ref_corners[2 * MAX_CORNERS]; unsigned char *frm_buffer = frm->y_buffer; unsigned char *ref_buffer = ref->y_buffer; + RansacFunc ransac = get_ransac_type(type); #if CONFIG_AOM_HIGHBITDEPTH if (frm->flags & YV12_FLAG_HIGHBITDEPTH) { @@ -317,8 +299,21 @@ (int *)ref_corners, num_ref_corners, frm->y_width, frm->y_height, frm->y_stride, ref->y_stride, correspondences); - num_inliers = compute_global_motion_params(type, correspondences, - num_correspondences, params); + ransac(correspondences, num_correspondences, num_inliers_by_motion, + params_by_motion, num_motions); + free(correspondences); - return (num_inliers > 0); + + // Set num_inliers = 0 for motions with too few inliers so they are ignored. + for (i = 0; i < num_motions; ++i) { + if (num_inliers_by_motion[i] < MIN_INLIER_PROB * num_correspondences) { + num_inliers_by_motion[i] = 0; + } + } + + // Return true if any one of the motions has inliers. + for (i = 0; i < num_motions; ++i) { + if (num_inliers_by_motion[i] > 0) return 1; + } + return 0; }
diff --git a/av1/encoder/global_motion.h b/av1/encoder/global_motion.h index 141a16e..232489f 100644 --- a/av1/encoder/global_motion.h +++ b/av1/encoder/global_motion.h
@@ -20,6 +20,8 @@ extern "C" { #endif +#define RANSAC_NUM_MOTIONS 1 + extern const double gm_advantage_thresh[TRANS_TYPES]; void convert_to_params(const double *params, int32_t *model); @@ -43,23 +45,24 @@ int d_height, int d_stride, int n_refinements); /* - Computes global motion parameters between two frames. The array - "params" should be length 9, where the first 2 slots are translation - parameters in (row, col) order, and the remaining slots correspond - to values in the transformation matrix of the corresponding motion - model. They are arranged in "params" such that values on the tx-matrix - diagonal have odd numbered indices so the folowing matrix: - A | B - C | D - would produce params = [trans row, trans col, B, A, C, D] + Computes "num_motions" candidate global motion parameters between two frames. + The array "params_by_motion" should be length 8 * "num_motions", where the + first 2 slots in each group of 8 parameters are the translation parameters in + (row, col) order, and the remaining slots correspond to values in the + transformation matrix of the corresponding motion model. They are arranged in + "params" such that values on the tx-matrix diagonal have odd numbered indices + so the folowing matrix: A | B C | D would produce params = [trans row, trans + col, B, A, C, D]. + "num_inliers" should be length "num_motions", and will be populated with the + number of inlier feature points for each motion. Params for which the + num_inliers entry is 0 should be ignored by the caller. */ -int compute_global_motion_feature_based(TransformationType type, - YV12_BUFFER_CONFIG *frm, - YV12_BUFFER_CONFIG *ref, +int compute_global_motion_feature_based( + TransformationType type, YV12_BUFFER_CONFIG *frm, YV12_BUFFER_CONFIG *ref, #if CONFIG_AOM_HIGHBITDEPTH - int bit_depth, + int bit_depth, #endif - double *params); + int *num_inliers_by_motion, double *params_by_motion, int num_motions); #ifdef __cplusplus } // extern "C" #endif
diff --git a/av1/encoder/ransac.c b/av1/encoder/ransac.c index ab0d530..44dc7f5 100644 --- a/av1/encoder/ransac.c +++ b/av1/encoder/ransac.c
@@ -916,8 +916,50 @@ return 1; } -static int ransac(int *matched_points, int npoints, int *number_of_inliers, - double *best_params, const int minpts, +typedef struct { + int num_inliers; + double variance; + int *inlier_indices; +} RANSAC_MOTION; + +// Return -1 if 'a' is a better motion, 1 if 'b' is better, 0 otherwise. +static int compare_motions(const void *arg_a, const void *arg_b) { + const RANSAC_MOTION *motion_a = (RANSAC_MOTION *)arg_a; + const RANSAC_MOTION *motion_b = (RANSAC_MOTION *)arg_b; + + if (motion_a->num_inliers > motion_b->num_inliers) return -1; + if (motion_a->num_inliers < motion_b->num_inliers) return 1; + if (motion_a->variance < motion_b->variance) return -1; + if (motion_a->variance > motion_b->variance) return 1; + return 0; +} + +static int is_better_motion(const RANSAC_MOTION *motion_a, + const RANSAC_MOTION *motion_b) { + return compare_motions(motion_a, motion_b) < 0; +} + +static void copy_points_at_indices(double *dest, const double *src, + const int *indices, int num_points) { + for (int i = 0; i < num_points; ++i) { + const int index = indices[i]; + dest[i * 2] = src[index * 2]; + dest[i * 2 + 1] = src[index * 2 + 1]; + } +} + +static const double kInfiniteVariance = 1e12; + +static void clear_motion(RANSAC_MOTION *motion, int num_points) { + motion->num_inliers = 0; + motion->variance = kInfiniteVariance; + memset(motion->inlier_indices, 0, + sizeof(*motion->inlier_indices * num_points)); +} + +static int ransac(const int *matched_points, int npoints, + int *num_inliers_by_motion, double *params_by_motion, + int num_desired_motions, const int minpts, IsDegenerateFunc is_degenerate, FindTransformationFunc find_transformation, ProjectPointsDoubleFunc projectpoints) { @@ -925,51 +967,61 @@ static const double EPS = 1e-12; int N = 10000, trial_count = 0; - int i; + int i = 0; int ret_val = 0; + unsigned int seed = (unsigned int)npoints; - int max_inliers = 0; - double best_variance = 0.0; - double params[MAX_PARAMDIM]; - WarpedMotionParams wm; - double points1[2 * MAX_MINPTS]; - double points2[2 * MAX_MINPTS]; int indices[MAX_MINPTS] = { 0 }; - double *best_inlier_set1; - double *best_inlier_set2; - double *inlier_set1; - double *inlier_set2; - double *corners1; - double *corners2; + double *points1, *points2; + double *corners1, *corners2; double *image1_coord; + // Store information for the num_desired_motions best transformations found + // and the worst motion among them, as well as the motion currently under + // consideration. + RANSAC_MOTION *motions, *worst_kept_motion = NULL; + RANSAC_MOTION current_motion; + + // Store the parameters and the indices of the inlier points for the motion + // currently under consideration. + double params_this_motion[MAX_PARAMDIM]; + double *cnp1, *cnp2; - *number_of_inliers = 0; if (npoints < minpts * MINPTS_MULTIPLIER || npoints == 0) { return 1; } - memset(&wm, 0, sizeof(wm)); - best_inlier_set1 = - (double *)aom_malloc(sizeof(*best_inlier_set1) * npoints * 2); - best_inlier_set2 = - (double *)aom_malloc(sizeof(*best_inlier_set2) * npoints * 2); - inlier_set1 = (double *)aom_malloc(sizeof(*inlier_set1) * npoints * 2); - inlier_set2 = (double *)aom_malloc(sizeof(*inlier_set2) * npoints * 2); + points1 = (double *)aom_malloc(sizeof(*points1) * npoints * 2); + points2 = (double *)aom_malloc(sizeof(*points2) * npoints * 2); corners1 = (double *)aom_malloc(sizeof(*corners1) * npoints * 2); corners2 = (double *)aom_malloc(sizeof(*corners2) * npoints * 2); image1_coord = (double *)aom_malloc(sizeof(*image1_coord) * npoints * 2); - if (!(best_inlier_set1 && best_inlier_set2 && inlier_set1 && inlier_set2 && - corners1 && corners2 && image1_coord)) { + motions = + (RANSAC_MOTION *)aom_malloc(sizeof(RANSAC_MOTION) * num_desired_motions); + for (i = 0; i < num_desired_motions; ++i) { + motions[i].inlier_indices = + (int *)aom_malloc(sizeof(*motions->inlier_indices) * npoints); + clear_motion(motions + i, npoints); + } + current_motion.inlier_indices = + (int *)aom_malloc(sizeof(*current_motion.inlier_indices) * npoints); + clear_motion(¤t_motion, npoints); + + worst_kept_motion = motions; + + if (!(points1 && points2 && corners1 && corners2 && image1_coord && motions && + current_motion.inlier_indices)) { ret_val = 1; goto finish_ransac; } - for (cnp1 = corners1, cnp2 = corners2, i = 0; i < npoints; ++i) { + cnp1 = corners1; + cnp2 = corners2; + for (i = 0; i < npoints; ++i) { *(cnp1++) = *(matched_points++); *(cnp1++) = *(matched_points++); *(cnp2++) = *(matched_points++); @@ -978,28 +1030,24 @@ matched_points -= 4 * npoints; while (N > trial_count) { - int num_inliers = 0; double sum_distance = 0.0; double sum_distance_squared = 0.0; + clear_motion(¤t_motion, npoints); + int degenerate = 1; int num_degenerate_iter = 0; + while (degenerate) { num_degenerate_iter++; if (!get_rand_indices(npoints, minpts, indices, &seed)) { ret_val = 1; goto finish_ransac; } - i = 0; - while (i < minpts) { - int index = indices[i]; - // add to list - points1[i * 2] = corners1[index * 2]; - points1[i * 2 + 1] = corners1[index * 2 + 1]; - points2[i * 2] = corners2[index * 2]; - points2[i * 2 + 1] = corners2[index * 2 + 1]; - i++; - } + + copy_points_at_indices(points1, corners1, indices, minpts); + copy_points_at_indices(points2, corners2, indices, minpts); + degenerate = is_degenerate(points1); if (num_degenerate_iter > MAX_DEGENERATE_ITER) { ret_val = 1; @@ -1007,12 +1055,12 @@ } } - if (find_transformation(minpts, points1, points2, params)) { + if (find_transformation(minpts, points1, points2, params_this_motion)) { trial_count++; continue; } - projectpoints(params, corners1, image1_coord, npoints, 2, 2); + projectpoints(params_this_motion, corners1, image1_coord, npoints, 2, 2); for (i = 0; i < npoints; ++i) { double dx = image1_coord[i * 2] - corners2[i * 2]; @@ -1020,60 +1068,79 @@ double distance = sqrt(dx * dx + dy * dy); if (distance < INLIER_THRESHOLD) { - inlier_set1[num_inliers * 2] = corners1[i * 2]; - inlier_set1[num_inliers * 2 + 1] = corners1[i * 2 + 1]; - inlier_set2[num_inliers * 2] = corners2[i * 2]; - inlier_set2[num_inliers * 2 + 1] = corners2[i * 2 + 1]; - num_inliers++; + current_motion.inlier_indices[current_motion.num_inliers++] = i; sum_distance += distance; sum_distance_squared += distance * distance; } } - if (num_inliers >= max_inliers && num_inliers > 1) { + if (current_motion.num_inliers >= worst_kept_motion->num_inliers && + current_motion.num_inliers > 1) { int temp; - double fracinliers, pNoOutliers, mean_distance, variance; - - mean_distance = sum_distance / ((double)num_inliers); - variance = sum_distance_squared / ((double)num_inliers - 1.0) - - mean_distance * mean_distance * ((double)num_inliers) / - ((double)num_inliers - 1.0); - if ((num_inliers > max_inliers) || - (num_inliers == max_inliers && variance < best_variance)) { - best_variance = variance; - max_inliers = num_inliers; - // Save parameters, excluding the implicit '1' in the bottom-right - // entry of the parameter matrix - memcpy(best_params, params, (MAX_PARAMDIM - 1) * sizeof(*best_params)); - memcpy(best_inlier_set1, inlier_set1, - num_inliers * 2 * sizeof(*best_inlier_set1)); - memcpy(best_inlier_set2, inlier_set2, - num_inliers * 2 * sizeof(*best_inlier_set2)); + double fracinliers, pNoOutliers, mean_distance; + mean_distance = sum_distance / ((double)current_motion.num_inliers); + current_motion.variance = + sum_distance_squared / ((double)current_motion.num_inliers - 1.0) - + mean_distance * mean_distance * ((double)current_motion.num_inliers) / + ((double)current_motion.num_inliers - 1.0); + if (is_better_motion(¤t_motion, worst_kept_motion)) { + // This motion is better than the worst currently kept motion. Remember + // the inlier points and variance. The parameters for each kept motion + // will be recomputed later using only the inliers. + worst_kept_motion->num_inliers = current_motion.num_inliers; + worst_kept_motion->variance = current_motion.variance; + memcpy(worst_kept_motion->inlier_indices, current_motion.inlier_indices, + sizeof(*current_motion.inlier_indices) * npoints); assert(npoints > 0); - fracinliers = (double)num_inliers / (double)npoints; + fracinliers = (double)current_motion.num_inliers / (double)npoints; pNoOutliers = 1 - pow(fracinliers, minpts); pNoOutliers = fmax(EPS, pNoOutliers); pNoOutliers = fmin(1 - EPS, pNoOutliers); temp = (int)(log(1.0 - PROBABILITY_REQUIRED) / log(pNoOutliers)); + if (temp > 0 && temp < N) { N = AOMMAX(temp, MIN_TRIALS); } + + // Determine the new worst kept motion and its num_inliers and variance. + for (i = 0; i < num_desired_motions; ++i) { + if (is_better_motion(worst_kept_motion, &motions[i])) { + worst_kept_motion = &motions[i]; + } + } } } trial_count++; } - find_transformation(max_inliers, best_inlier_set1, best_inlier_set2, - best_params); - *number_of_inliers = max_inliers; + + // Sort the motions, best first. + qsort(motions, num_desired_motions, sizeof(RANSAC_MOTION), compare_motions); + + // Recompute the motions using only the inliers. + for (i = 0; i < num_desired_motions; ++i) { + copy_points_at_indices(points1, corners1, motions[i].inlier_indices, + motions[i].num_inliers); + copy_points_at_indices(points2, corners2, motions[i].inlier_indices, + motions[i].num_inliers); + + find_transformation(motions[i].num_inliers, points1, points2, + params_by_motion + (MAX_PARAMDIM - 1) * i); + num_inliers_by_motion[i] = motions[i].num_inliers; + } + finish_ransac: - aom_free(best_inlier_set1); - aom_free(best_inlier_set2); - aom_free(inlier_set1); - aom_free(inlier_set2); + aom_free(points1); + aom_free(points2); aom_free(corners1); aom_free(corners2); aom_free(image1_coord); + aom_free(current_motion.inlier_indices); + for (i = 0; i < num_desired_motions; ++i) { + aom_free(motions[i].inlier_indices); + } + aom_free(motions); + return ret_val; } @@ -1097,44 +1164,52 @@ is_collinear3(p, p + 4, p + 6) || is_collinear3(p + 2, p + 4, p + 6); } -int ransac_translation(int *matched_points, int npoints, int *number_of_inliers, - double *best_params) { - return ransac(matched_points, npoints, number_of_inliers, best_params, 3, +int ransac_translation(int *matched_points, int npoints, + int *num_inliers_by_motion, double *params_by_motion, + int num_desired_motions) { + return ransac(matched_points, npoints, num_inliers_by_motion, + params_by_motion, num_desired_motions, 3, is_degenerate_translation, find_translation, project_points_double_translation); } -int ransac_rotzoom(int *matched_points, int npoints, int *number_of_inliers, - double *best_params) { - return ransac(matched_points, npoints, number_of_inliers, best_params, 3, - is_degenerate_affine, find_rotzoom, - project_points_double_rotzoom); +int ransac_rotzoom(int *matched_points, int npoints, int *num_inliers_by_motion, + double *params_by_motion, int num_desired_motions) { + return ransac(matched_points, npoints, num_inliers_by_motion, + params_by_motion, num_desired_motions, 3, is_degenerate_affine, + find_rotzoom, project_points_double_rotzoom); } -int ransac_affine(int *matched_points, int npoints, int *number_of_inliers, - double *best_params) { - return ransac(matched_points, npoints, number_of_inliers, best_params, 3, - is_degenerate_affine, find_affine, - project_points_double_affine); +int ransac_affine(int *matched_points, int npoints, int *num_inliers_by_motion, + double *params_by_motion, int num_desired_motions) { + return ransac(matched_points, npoints, num_inliers_by_motion, + params_by_motion, num_desired_motions, 3, is_degenerate_affine, + find_affine, project_points_double_affine); } -int ransac_homography(int *matched_points, int npoints, int *number_of_inliers, - double *best_params) { - return ransac(matched_points, npoints, number_of_inliers, best_params, 4, +int ransac_homography(int *matched_points, int npoints, + int *num_inliers_by_motion, double *params_by_motion, + int num_desired_motions) { + return ransac(matched_points, npoints, num_inliers_by_motion, + params_by_motion, num_desired_motions, 4, is_degenerate_homography, find_homography, project_points_double_homography); } int ransac_hortrapezoid(int *matched_points, int npoints, - int *number_of_inliers, double *best_params) { - return ransac(matched_points, npoints, number_of_inliers, best_params, 4, + int *num_inliers_by_motion, double *params_by_motion, + int num_desired_motions) { + return ransac(matched_points, npoints, num_inliers_by_motion, + params_by_motion, num_desired_motions, 4, is_degenerate_homography, find_hortrapezoid, project_points_double_hortrapezoid); } int ransac_vertrapezoid(int *matched_points, int npoints, - int *number_of_inliers, double *best_params) { - return ransac(matched_points, npoints, number_of_inliers, best_params, 4, + int *num_inliers_by_motion, double *params_by_motion, + int num_desired_motions) { + return ransac(matched_points, npoints, num_inliers_by_motion, + params_by_motion, num_desired_motions, 4, is_degenerate_homography, find_vertrapezoid, project_points_double_vertrapezoid); }
diff --git a/av1/encoder/ransac.h b/av1/encoder/ransac.h index 1eeb105..f611add 100644 --- a/av1/encoder/ransac.h +++ b/av1/encoder/ransac.h
@@ -20,20 +20,25 @@ #include "av1/common/warped_motion.h" typedef int (*RansacFunc)(int *matched_points, int npoints, - int *number_of_inliers, double *best_params); + int *num_inliers_by_motion, double *params_by_motion, + int num_motions); /* Each of these functions fits a motion model from a set of corresponding points in 2 frames using RANSAC. */ -int ransac_homography(int *matched_points, int npoints, int *number_of_inliers, - double *best_params); -int ransac_affine(int *matched_points, int npoints, int *number_of_inliers, - double *best_params); +int ransac_homography(int *matched_points, int npoints, + int *num_inliers_by_motion, double *params_by_motion, + int num_motions); +int ransac_affine(int *matched_points, int npoints, int *num_inliers_by_motion, + double *params_by_motion, int num_motions); int ransac_hortrapezoid(int *matched_points, int npoints, - int *number_of_inliers, double *best_params); + int *num_inliers_by_motion, double *params_by_motion, + int num_motions); int ransac_vertrapezoid(int *matched_points, int npoints, - int *number_of_inliers, double *best_params); -int ransac_rotzoom(int *matched_points, int npoints, int *number_of_inliers, - double *best_params); -int ransac_translation(int *matched_points, int npoints, int *number_of_inliers, - double *best_params); + int *num_inliers_by_motion, double *params_by_motion, + int num_motions); +int ransac_rotzoom(int *matched_points, int npoints, int *num_inliers_by_motion, + double *params_by_motion, int num_motions); +int ransac_translation(int *matched_points, int npoints, + int *num_inliers_by_motion, double *params_by_motion, + int num_motions); #endif // AV1_ENCODER_RANSAC_H_