blob: 8876615c27e475b1c6486e0a88d7ba33d249780b [file] [log] [blame] [edit]
/*
* Copyright (c) 2022, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* aomedia.org/license/patent-license/.
*/
#ifndef AOM_FLOW_ESTIMATION_H_
#define AOM_FLOW_ESTIMATION_H_
#include "aom_dsp/rect.h"
#include "aom_ports/mem.h"
#include "aom_scale/yv12config.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_PARAMDIM 9
#define MAX_CORNERS 4096
#define MIN_INLIER_PROB 0.1
/* clang-format off */
enum {
IDENTITY = 0, // identity transformation, 0-parameter
TRANSLATION = 1, // translational motion 2-parameter
ROTATION = 2, // rotation about some point, 3-parameter
ZOOM = 3, // zoom in/out on some point, 3-parameter
VERTSHEAR = 4, // translation + vertical shear, 3-parameter
HORZSHEAR = 5, // translation + horizontal shear, 3-parameter
UZOOM = 6, // unequal zoom, 4-parameter
ROTZOOM = 7, // equal zoom, then rotate, 4-parameter
ROTUZOOM = 8, // unequal zoom, then rotate, 5-parameter
AFFINE = 9, // general affine, 6-parameter
VERTRAPEZOID = 10, // vertical-only perspective, 6-parameter
HORTRAPEZOID = 11, // horizontal-only perspective, 6-parameter
HOMOGRAPHY = 12, // general perspective transformation, 8-parameter
TRANS_TYPES,
} UENUM1BYTE(TransformationType);
/* clang-format on */
// number of parameters used by each transformation in TransformationTypes
static const int trans_model_params[TRANS_TYPES] = { 0, 2, 3, 3, 3, 3, 4,
4, 5, 6, 6, 6, 8 };
typedef enum {
GLOBAL_MOTION_FEATURE_BASED,
GLOBAL_MOTION_DISFLOW_BASED,
} GlobalMotionEstimationType;
typedef struct {
double params[MAX_PARAMDIM - 1];
int *inliers;
int num_inliers;
} MotionModel;
typedef struct {
double x, y;
double rx, ry;
} Correspondence;
typedef struct {
int num_correspondences;
Correspondence *correspondences;
} CorrespondenceList;
typedef struct {
// x and y directions of flow, per patch
double *u;
double *v;
// Sizes of the above arrays
size_t width;
size_t height;
size_t stride;
} FlowField;
// We want to present external code with a generic type, which holds whatever
// data is needed for the desired motion estimation method.
// As different methods use different data, we store this in a tagged union,
// with the selected motion estimation type as the tag.
typedef struct {
GlobalMotionEstimationType method;
union {
CorrespondenceList *corrs;
FlowField *flow;
};
} FlowData;
FlowData *aom_compute_flow_data(YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *ref, int bit_depth,
GlobalMotionEstimationType gm_estimation_type);
/*
Computes "num_motions" candidate global motion parameters between two frames.
The array "params_by_motion" should be length 8 * "num_motions". The ordering
of each set of parameters is best described by the homography:
[x' (m2 m3 m0 [x
z . y' = m4 m5 m1 * y
1] m6 m7 1) 1]
where m{i} represents the ith value in any given set of parameters.
"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.
*/
// Fit one or several models of a given type to the specified flow data.
// This function fits models to the entire frame, using the RANSAC method
// to fit models in a noise-resilient way, and returns the list of inliers
// for each model found
// TODO: Cleanup this comment
bool aom_fit_global_motion_model(FlowData *flow_data, TransformationType type,
YV12_BUFFER_CONFIG *src, int bit_depth,
MotionModel *params_by_motion,
int num_motions);
// Fit a model of a given type to a subset of the specified flow data.
// This does not used the RANSAC method, so is more noise-sensitive than
// aom_fit_global_motion_model(), but in the context of fitting models
// to single blocks this is not an issue.
bool aom_fit_local_motion_model(FlowData *flow_data, PixelRect *rect,
TransformationType type, double *mat);
void aom_free_flow_data(FlowData *flow_data);
#ifdef __cplusplus
}
#endif
#endif // AOM_FLOW_ESTIMATION_H_