From: Sarah Parker Date: Thu, 21 Jul 2016 00:11:39 +0000 (-0700) Subject: Add affine model to global motion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e9bd26b826a39d560859a0c641f6dae7aa9827f6;p=libvpx Add affine model to global motion Change-Id: I9cd355a3ea344ef66a61028efa25d94f54e7e2bd --- diff --git a/vp10/common/entropymv.c b/vp10/common/entropymv.c index ae6209d00..925cc1e18 100644 --- a/vp10/common/entropymv.c +++ b/vp10/common/entropymv.c @@ -124,11 +124,12 @@ static const uint8_t log_in_base_2[] = { const vpx_tree_index vp10_global_motion_types_tree [TREE_SIZE(GLOBAL_MOTION_TYPES)] = { -GLOBAL_ZERO, 2, - -GLOBAL_TRANSLATION, -GLOBAL_ROTZOOM + -GLOBAL_TRANSLATION, 4, + -GLOBAL_ROTZOOM, -GLOBAL_AFFINE }; static const vpx_prob default_global_motion_types_prob - [GLOBAL_MOTION_TYPES - 1] = {224, 128}; + [GLOBAL_MOTION_TYPES - 1] = {224, 128, 128}; #endif // CONFIG_GLOBAL_MOTION static INLINE int mv_class_base(MV_CLASS_TYPE c) { diff --git a/vp10/common/mv.h b/vp10/common/mv.h index 255a7243c..f45f2ab49 100644 --- a/vp10/common/mv.h +++ b/vp10/common/mv.h @@ -41,6 +41,10 @@ typedef struct mv32 { // | a b| // |-b a| // +// and a, b, c, d in affine model: +// | a b| +// | c d| +// // Anything ending in PREC_BITS is the number of bits of precision // to maintain when converting from double to integer. // @@ -76,6 +80,7 @@ typedef enum { GLOBAL_ZERO = 0, GLOBAL_TRANSLATION = 1, GLOBAL_ROTZOOM = 2, + GLOBAL_AFFINE = 3, GLOBAL_MOTION_TYPES } GLOBAL_MOTION_TYPE; @@ -84,12 +89,36 @@ typedef struct { WarpedMotionParams motion_params; } Global_Motion_Params; +static INLINE TransformationType gm_to_trans_type(GLOBAL_MOTION_TYPE gmtype) { + switch (gmtype) { + case GLOBAL_ZERO: + return UNKNOWN_TRANSFORM; + break; + case GLOBAL_TRANSLATION: + return TRANSLATION; + break; + case GLOBAL_ROTZOOM: + return ROTZOOM; + break; + case GLOBAL_AFFINE: + return AFFINE; + break; + default: + assert(0); + } + return UNKNOWN_TRANSFORM; +} + static INLINE GLOBAL_MOTION_TYPE get_gmtype(const Global_Motion_Params *gm) { - if (gm->motion_params.wmmat[2] == 0 && gm->motion_params.wmmat[3] == 0) { - return ((gm->motion_params.wmmat[0] | gm->motion_params.wmmat[1]) ? - GLOBAL_TRANSLATION : GLOBAL_ZERO); + if (gm->motion_params.wmmat[4] == 0 && gm->motion_params.wmmat[5] == 0) { + if (gm->motion_params.wmmat[2] == 0 && gm->motion_params.wmmat[3] == 0) { + return ((gm->motion_params.wmmat[0] | gm->motion_params.wmmat[1]) ? + GLOBAL_TRANSLATION : GLOBAL_ZERO); + } else { + return GLOBAL_ROTZOOM; + } } else { - return GLOBAL_ROTZOOM; + return GLOBAL_AFFINE; } } #endif // CONFIG_GLOBAL_MOTION diff --git a/vp10/common/warped_motion.h b/vp10/common/warped_motion.h index 1d2568853..11d6124eb 100644 --- a/vp10/common/warped_motion.h +++ b/vp10/common/warped_motion.h @@ -42,9 +42,13 @@ typedef enum { HOMOGRAPHY, // homography, 8-parameter AFFINE, // affine, 6-parameter ROTZOOM, // simplified affine with rotation and zoom only, 4-parameter - TRANSLATION // translational motion 2-parameter + TRANSLATION, // translational motion 2-parameter + TRANS_TYPES } TransformationType; +// number of parameters used by each transformation in TransformationTypes +static const int n_trans_model_params[TRANS_TYPES] = {9, 6, 4, 2}; + typedef struct { TransformationType wmtype; int wmmat[8]; // For homography wmmat[9] is assumed to be 1 diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 06b3e07b0..76fe17dff 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -3450,32 +3450,31 @@ static void read_global_motion_params(Global_Motion_Params *params, GLOBAL_MOTION_TYPE gmtype = vp10_read_tree(r, vp10_global_motion_types_tree, probs); params->gmtype = gmtype; + params->motion_params.wmtype = gm_to_trans_type(gmtype); switch (gmtype) { case GLOBAL_ZERO: break; - case GLOBAL_TRANSLATION: - params->motion_params.wmtype = TRANSLATION; - params->motion_params.wmmat[0] = - vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) * - GM_TRANS_DECODE_FACTOR; - params->motion_params.wmmat[1] = - vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) * - GM_TRANS_DECODE_FACTOR; - break; + case GLOBAL_AFFINE: + params->motion_params.wmmat[4] = + (vp10_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) * + GM_ALPHA_DECODE_FACTOR) + (1 << WARPEDMODEL_PREC_BITS); + params->motion_params.wmmat[5] = + vp10_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) * + GM_ALPHA_DECODE_FACTOR; case GLOBAL_ROTZOOM: - params->motion_params.wmtype = ROTZOOM; - params->motion_params.wmmat[0] = - vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) * - GM_TRANS_DECODE_FACTOR; - params->motion_params.wmmat[1] = - vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) * - GM_TRANS_DECODE_FACTOR; params->motion_params.wmmat[2] = (vp10_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) * GM_ALPHA_DECODE_FACTOR) + (1 << WARPEDMODEL_PREC_BITS); params->motion_params.wmmat[3] = vp10_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) * GM_ALPHA_DECODE_FACTOR; + case GLOBAL_TRANSLATION: + params->motion_params.wmmat[0] = + vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) * + GM_TRANS_DECODE_FACTOR; + params->motion_params.wmmat[1] = + vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) * + GM_TRANS_DECODE_FACTOR; break; default: assert(0); diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 6430a7104..1adc47087 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -3187,6 +3187,7 @@ static void write_uncompressed_header(VP10_COMP *cpi, write_tile_info(cm, wb); } + #if CONFIG_GLOBAL_MOTION static void write_global_motion_params(Global_Motion_Params *params, vpx_prob *probs, @@ -3197,21 +3198,21 @@ static void write_global_motion_params(Global_Motion_Params *params, switch (gmtype) { case GLOBAL_ZERO: break; - case GLOBAL_TRANSLATION: - vp10_write_primitive_symmetric(w, params->motion_params.wmmat[0], - GM_ABS_TRANS_BITS); - vp10_write_primitive_symmetric(w, params->motion_params.wmmat[1], - GM_ABS_TRANS_BITS); - break; + case GLOBAL_AFFINE: + vp10_write_primitive_symmetric(w, params->motion_params.wmmat[4], + GM_ABS_ALPHA_BITS); + vp10_write_primitive_symmetric(w, params->motion_params.wmmat[5], + GM_ABS_ALPHA_BITS); case GLOBAL_ROTZOOM: - vp10_write_primitive_symmetric(w, params->motion_params.wmmat[0], - GM_ABS_TRANS_BITS); - vp10_write_primitive_symmetric(w, params->motion_params.wmmat[1], - GM_ABS_TRANS_BITS); vp10_write_primitive_symmetric(w, params->motion_params.wmmat[2], GM_ABS_ALPHA_BITS); vp10_write_primitive_symmetric(w, params->motion_params.wmmat[3], GM_ABS_ALPHA_BITS); + case GLOBAL_TRANSLATION: + vp10_write_primitive_symmetric(w, params->motion_params.wmmat[0], + GM_ABS_TRANS_BITS); + vp10_write_primitive_symmetric(w, params->motion_params.wmmat[1], + GM_ABS_TRANS_BITS); break; default: assert(0); diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index b91615bf3..6bebfe637 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -4538,28 +4538,11 @@ static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats, #if CONFIG_GLOBAL_MOTION #define MIN_TRANS_THRESH 8 - -static void convert_translation_to_params( - double *H, Global_Motion_Params *model) { - model->motion_params.wmmat[0] = (int) floor(H[0] * - (1 << GM_TRANS_PREC_BITS) + 0.5); - model->motion_params.wmmat[1] = (int) floor(H[1] * - (1 << GM_TRANS_PREC_BITS) + 0.5); - if (abs(model->motion_params.wmmat[0]) < MIN_TRANS_THRESH && - abs(model->motion_params.wmmat[1]) < MIN_TRANS_THRESH) { - model->motion_params.wmmat[0] = 0; - model->motion_params.wmmat[1] = 0; - } else { - model->motion_params.wmmat[0] = - clamp(model->motion_params.wmmat[0], - GM_TRANS_MIN, GM_TRANS_MAX); - model->motion_params.wmmat[1] = - clamp(model->motion_params.wmmat[1], - GM_TRANS_MIN, GM_TRANS_MAX); - } -} - -static void convert_rotzoom_to_params(double *H, Global_Motion_Params *model) { +static void convert_to_params(double *H, TransformationType type, + Global_Motion_Params *model) { + int i; + int alpha_present = 0; + int n_params = n_trans_model_params[type]; model->motion_params.wmmat[0] = (int) floor(H[0] * (1 << GM_TRANS_PREC_BITS) + 0.5); model->motion_params.wmmat[1] = (int) floor(H[1] * @@ -4571,19 +4554,17 @@ static void convert_rotzoom_to_params(double *H, Global_Motion_Params *model) { clamp(model->motion_params.wmmat[1], GM_TRANS_MIN, GM_TRANS_MAX); - model->motion_params.wmmat[2] = (int) floor(H[2] * - (1 << GM_ALPHA_PREC_BITS) + 0.5) - - (1 << GM_ALPHA_PREC_BITS); - model->motion_params.wmmat[3] = (int) floor(H[3] * - (1 << GM_ALPHA_PREC_BITS) + 0.5); - - model->motion_params.wmmat[2] = clamp(model->motion_params.wmmat[2], - GM_ALPHA_MIN, GM_ALPHA_MAX); - model->motion_params.wmmat[3] = clamp(model->motion_params.wmmat[3], - GM_ALPHA_MIN, GM_ALPHA_MAX); + for (i = 2; i < n_params; ++i) { + model->motion_params.wmmat[i] = + (int) floor(H[i] * + (1 << GM_ALPHA_PREC_BITS) + 0.5) - + (!(i & 1) * (1 << GM_ALPHA_PREC_BITS)); + model->motion_params.wmmat[i] = clamp(model->motion_params.wmmat[i], + GM_ALPHA_MIN, GM_ALPHA_MAX); + alpha_present |= (model->motion_params.wmmat[i] != 0); + } - if (model->motion_params.wmmat[2] == 0 && - model->motion_params.wmmat[3] == 0) { + if (!alpha_present) { if (abs(model->motion_params.wmmat[0]) < MIN_TRANS_THRESH && abs(model->motion_params.wmmat[1]) < MIN_TRANS_THRESH) { model->motion_params.wmmat[0] = 0; @@ -4594,16 +4575,9 @@ static void convert_rotzoom_to_params(double *H, Global_Motion_Params *model) { static void convert_model_to_params(double *H, TransformationType type, Global_Motion_Params *model) { - switch (type) { - case ROTZOOM: - convert_rotzoom_to_params(H, model); - break; - case TRANSLATION: - convert_translation_to_params(H, model); - break; - default: - break; - } + // TODO(sarahparker) implement for homography + if (type > HOMOGRAPHY) + convert_to_params(H, type, model); model->gmtype = get_gmtype(model); } #endif // CONFIG_GLOBAL_MOTION