blob: c373f45400c519c172f9199d296c974bf5e4a30a [file] [log] [blame]
Neil Birkbecked25a612017-12-21 13:18:32 -08001/*
2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12#ifndef AOM_DSP_NOISE_MODEL_H_
13#define AOM_DSP_NOISE_MODEL_H_
14
15#ifdef __cplusplus
16extern "C" {
17#endif // __cplusplus
18
19#include <stdint.h>
20
21/*!\brief Wrapper of data required to represent linear system of eqns and soln.
22 */
23typedef struct {
24 double *A;
25 double *b;
26 double *x;
27 int n;
28} aom_equation_system_t;
29
30/*!\brief Representation of a piecewise linear curve
31 *
32 * Holds n points as (x, y) pairs, that store the curve.
33 */
34typedef struct {
35 double (*points)[2];
36 int num_points;
37} aom_noise_strength_lut_t;
38
39/*!\brief Init the noise strength lut with the given number of points*/
40int aom_noise_strength_lut_init(aom_noise_strength_lut_t *lut, int num_points);
41
42/*!\brief Frees the noise strength lut. */
43void aom_noise_strength_lut_free(aom_noise_strength_lut_t *lut);
44
45/*!\brief Evaluate the lut at the point x.
46 *
47 * \param[in] lut The lut data.
48 * \param[in] x The coordinate to evaluate the lut.
49 */
50double aom_noise_strength_lut_eval(const aom_noise_strength_lut_t *lut,
51 double x);
52
53/*!\brief Helper struct to model noise strength as a function of intensity.
54 *
55 * Internally, this structure holds a representation of a linear system
56 * of equations that models noise strength (standard deviation) as a
57 * function of intensity. The mapping is initially stored using a
58 * piecewise representation with evenly spaced bins that cover the entire
59 * domain from [min_intensity, max_intensity]. Each observation (x,y) gives a
60 * constraint of the form:
61 * y_{i} (1 - a) + y_{i+1} a = y
62 * where y_{i} is the value of bin i and x_{i} <= x <= x_{i+1} and
63 * a = x/(x_{i+1} - x{i}). The equation system holds the corresponding
64 * normal equations.
65 *
66 * As there may be missing data, the solution is regularized to get a
67 * complete set of values for the bins. A reduced representation after
68 * solving can be obtained by getting the corresponding noise_strength_lut_t.
69 */
70typedef struct {
71 aom_equation_system_t eqns;
72 double min_intensity;
73 double max_intensity;
74 int num_bins;
75 int num_equations;
76 double total;
77} aom_noise_strength_solver_t;
78
79/*!\brief Initializes the noise solver with the given number of bins.
80 *
81 * Returns 0 if initialization fails.
82 *
83 * \param[in] solver The noise solver to be initialized.
84 * \param[in] num_bins Number of bins to use in the internal representation.
85 */
86int aom_noise_strength_solver_init(aom_noise_strength_solver_t *solver,
87 int num_bins);
88void aom_noise_strength_solver_free(aom_noise_strength_solver_t *solver);
89
90/*!\brief Gets the x coordinate of bin i.
91 *
92 * \param[in] i The bin whose coordinate to query.
93 */
94double aom_noise_strength_solver_get_center(
95 const aom_noise_strength_solver_t *solver, int i);
96
97/*!\brief Add an observation of the block mean intensity to its noise strength.
98 *
99 * \param[in] block_mean The average block intensity,
100 * \param[in] noise_std The observed noise strength.
101 */
102void aom_noise_strength_solver_add_measurement(
103 aom_noise_strength_solver_t *solver, double block_mean, double noise_std);
104
105/*!\brief Solves the current set of equations for the noise strength. */
106int aom_noise_strength_solver_solve(aom_noise_strength_solver_t *solver);
107
108/*!\brief Fits a reduced piecewise linear lut to the internal solution
109 *
110 * \param[out] lut The output piecewise linear lut.
111 */
112int aom_noise_strength_solver_fit_piecewise(
113 const aom_noise_strength_solver_t *solver, aom_noise_strength_lut_t *lut);
114
115/*!\brief Helper for holding precomputed data for finding flat blocks.
116 *
117 * Internally a block is modeled with a low-order polynomial model. A
118 * planar model would be a bunch of equations like:
119 * <[y_i x_i 1], [a_1, a_2, a_3]> = b_i
120 * for each point in the block. The system matrix A with row i as [y_i x_i 1]
121 * is maintained as is the inverse, inv(A'*A), so that the plane parameters
122 * can be fit for each block.
123 */
124typedef struct {
125 double *AtA_inv;
126 double *A;
127 int num_params; // The number of parameters used for internal low-order model
128 int block_size; // The block size the finder was initialized with
129} aom_flat_block_finder_t;
130
131/*!\brief Init the block_finder with the given block size */
132int aom_flat_block_finder_init(aom_flat_block_finder_t *block_finder,
133 int block_size);
134void aom_flat_block_finder_free(aom_flat_block_finder_t *block_finder);
135
136/*!\brief Helper to extract a block and low order "planar" model. */
137void aom_flat_block_finder_extract_block(
138 const aom_flat_block_finder_t *block_finder, const uint8_t *const data,
139 int w, int h, int stride, int offsx, int offsy, double *plane,
140 double *block);
141
142int aom_flat_block_finder_run(const aom_flat_block_finder_t *block_finder,
143 const uint8_t *const data, int w, int h,
144 int stride, uint8_t *flat_blocks);
145
146// The noise shape indicates the allowed coefficients in the AR model.
147typedef enum {
148 AOM_NOISE_SHAPE_DIAMOND = 0,
149 AOM_NOISE_SHAPE_SQUARE = 1
150} aom_noise_shape;
151
152// The parameters of the noise model include the shape type and the lag.
153typedef struct {
154 aom_noise_shape shape;
155 int lag;
156} aom_noise_model_params_t;
157
158/*!\brief State of a noise model estimate for a single channel.
159 *
160 * This contains a system of equations that can be used to solve
161 * for the auto-regressive coefficients as well as a noise strength
162 * solver that can be used to model noise strength as a function of
163 * intensity.
164 */
165typedef struct {
166 aom_equation_system_t eqns;
167 aom_noise_strength_solver_t strength_solver;
168} aom_noise_state_t;
169
170/*!\brief Complete model of noise for a planar video
171 *
172 * This includes a noise model for the latest frame and an aggregated
173 * estimate over all previous frames that had similar parameters.
174 */
175typedef struct {
176 aom_noise_model_params_t params;
177 aom_noise_state_t combined_state[3]; // Combined state per channel
178 aom_noise_state_t latest_state[3]; // Latest state per channel
179 int (*coords)[2]; // Offsets (x,y) of the coefficient samples
180 int n; // Number of parameters (size of coords)
181} aom_noise_model_t;
182
183/*!\brief Result of a noise model update. */
184typedef enum {
185 AOM_NOISE_STATUS_OK = 0,
186 AOM_NOISE_STATUS_INVALID_ARGUMENT,
187 AOM_NOISE_STATUS_INSUFFICIENT_FLAT_BLOCKS,
188 AOM_NOISE_STATUS_DIFFERENT_NOISE_TYPE,
189 AOM_NOISE_STATUS_INTERNAL_ERROR,
190} aom_noise_status_t;
191
192/*!\brief Initializes a noise model with the given parameters.
193 *
194 * Returns 0 on failure.
195 */
196int aom_noise_model_init(aom_noise_model_t *model,
197 const aom_noise_model_params_t params);
198void aom_noise_model_free(aom_noise_model_t *model);
199
200/*!\brief Updates the noise model with a new frame observation.
201 *
202 * Updates the noise model with measurements from the given input frame and a
203 * denoised variant of it. Noise is sampled from flat blocks using the flat
204 * block map.
205 *
206 * Returns a noise_status indicating if the update was successful. If the
207 * Update was successful, the combined_state is updated with measurements from
208 * the provided frame. If status is OK or DIFFERENT_NOISE_TYPE, the latest noise
209 * state will be updated with measurements from the provided frame.
210 *
211 * \param[in,out] noise_model The noise model to be updated
212 * \param[in] data Raw frame data
213 * \param[in] denoised Denoised frame data.
214 * \param[in] w Frame width
215 * \param[in] h Frame height
216 * \param[in] strides Stride of the planes
217 * \param[in] chroma_sub_log2 Chroma subsampling for planes != 0.
218 * \param[in] flat_blocks A map to blocks that have been determined flat
219 * \param[in] block_size The size of blocks.
220 */
221aom_noise_status_t aom_noise_model_update(
222 aom_noise_model_t *const noise_model, const uint8_t *const data[3],
223 const uint8_t *const denoised[3], int w, int h, int strides[3],
224 int chroma_sub_log2[2], const uint8_t *const flat_blocks, int block_size);
225
226#ifdef __cplusplus
227} // extern "C"
228#endif // __cplusplus
229#endif // AOM_DSP_NOISE_MODEL_H_