blob: d1a0ccf904bccb2658da7b505763d40f16d5b1f7 [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#include <math.h>
13
14#include <stdio.h>
15#include <stdlib.h>
16
17#include "aom_dsp/noise_util.h"
18#include "aom_mem/aom_mem.h"
19
20// Return normally distrbuted values with standard deviation of sigma.
21double aom_randn(double sigma) {
22 while (1) {
23 const double u = 2.0 * ((double)rand()) / RAND_MAX - 1.0;
24 const double v = 2.0 * ((double)rand()) / RAND_MAX - 1.0;
25 const double s = u * u + v * v;
26 if (s > 0 && s < 1) {
27 return sigma * (u * sqrt(-2.0 * log(s) / s));
28 }
29 }
30 return 0;
31}
32
33double aom_normalized_cross_correlation(const double *a, const double *b,
34 int n) {
35 double c = 0;
36 double a_len = 0;
37 double b_len = 0;
38 for (int i = 0; i < n; ++i) {
39 a_len += a[i] * a[i];
40 b_len += b[i] * b[i];
41 c += a[i] * b[i];
42 }
43 return c / (sqrt(a_len) * sqrt(b_len));
44}
45
46void aom_noise_synth(int lag, int n, const int (*coords)[2],
47 const double *coeffs, double *data, int w, int h) {
48 const int pad_size = 3 * lag;
49 const int padded_w = w + pad_size;
50 const int padded_h = h + pad_size;
51 int x = 0, y = 0;
52 double *padded = (double *)aom_malloc(padded_w * padded_h * sizeof(*padded));
53
54 for (y = 0; y < padded_h; ++y) {
55 for (x = 0; x < padded_w; ++x) {
56 padded[y * padded_w + x] = aom_randn(1.0);
57 }
58 }
59 for (y = lag; y < padded_h; ++y) {
60 for (x = lag; x < padded_w; ++x) {
61 double sum = 0;
62 int i = 0;
63 for (i = 0; i < n; ++i) {
64 const int dx = coords[i][0];
65 const int dy = coords[i][1];
66 sum += padded[(y + dy) * padded_w + (x + dx)] * coeffs[i];
67 }
68 padded[y * padded_w + x] += sum;
69 }
70 }
71 // Copy over the padded rows to the output
72 for (y = 0; y < h; ++y) {
73 memcpy(data + y * w, padded + y * padded_w, sizeof(*data) * w);
74 }
75 aom_free(padded);
76}
77
78int aom_noise_data_validate(const double *data, int w, int h) {
79 const double kVarianceThreshold = 2;
80 const double kMeanThreshold = 2;
81
82 int x = 0, y = 0;
83 int ret_value = 1;
84 double var = 0, mean = 0;
85 double *mean_x, *mean_y, *var_x, *var_y;
86
87 // Check that noise variance is not increasing in x or y
88 // and that the data is zero mean.
89 mean_x = (double *)aom_malloc(sizeof(*mean_x) * w);
90 var_x = (double *)aom_malloc(sizeof(*var_x) * w);
91 mean_y = (double *)aom_malloc(sizeof(*mean_x) * h);
92 var_y = (double *)aom_malloc(sizeof(*var_y) * h);
93
94 memset(mean_x, 0, sizeof(*mean_x) * w);
95 memset(var_x, 0, sizeof(*var_x) * w);
96 memset(mean_y, 0, sizeof(*mean_y) * h);
97 memset(var_y, 0, sizeof(*var_y) * h);
98
99 for (y = 0; y < h; ++y) {
100 for (x = 0; x < w; ++x) {
101 const double d = data[y * w + x];
102 var_x[x] += d * d;
103 var_y[y] += d * d;
104 mean_x[x] += d;
105 mean_y[y] += d;
106 var += d * d;
107 mean += d;
108 }
109 }
110 mean /= (w * h);
111 var = var / (w * h) - mean * mean;
112
113 for (y = 0; y < h; ++y) {
114 mean_y[y] /= h;
115 var_y[y] = var_y[y] / h - mean_y[y] * mean_y[y];
116 if (fabs(var_y[y] - var) >= kVarianceThreshold) {
117 fprintf(stderr, "Variance distance too large %f %f\n", var_y[y], var);
118 ret_value = 0;
119 break;
120 }
121 if (fabs(mean_y[y] - mean) >= kMeanThreshold) {
122 fprintf(stderr, "Mean distance too large %f %f\n", mean_y[y], mean);
123 ret_value = 0;
124 break;
125 }
126 }
127
128 for (x = 0; x < w; ++x) {
129 mean_x[x] /= w;
130 var_x[x] = var_x[x] / w - mean_x[x] * mean_x[x];
131 if (fabs(var_x[x] - var) >= kVarianceThreshold) {
132 fprintf(stderr, "Variance distance too large %f %f\n", var_x[x], var);
133 ret_value = 0;
134 break;
135 }
136 if (fabs(mean_x[x] - mean) >= kMeanThreshold) {
137 fprintf(stderr, "Mean distance too large %f %f\n", mean_x[x], mean);
138 ret_value = 0;
139 break;
140 }
141 }
142
143 aom_free(mean_x);
144 aom_free(mean_y);
145 aom_free(var_x);
146 aom_free(var_y);
147
148 return ret_value;
149}