OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "denoising.h" | 11 #include "denoising.h" |
12 | 12 |
13 #include "vp8/common/reconinter.h" | 13 #include "vp8/common/reconinter.h" |
14 #include "vpx/vpx_integer.h" | 14 #include "vpx/vpx_integer.h" |
15 #include "vpx_mem/vpx_mem.h" | 15 #include "vpx_mem/vpx_mem.h" |
16 #include "vp8_rtcd.h" | 16 #include "vp8_rtcd.h" |
17 | 17 |
18 static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25; | 18 static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25; |
19 /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming | 19 /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming |
20 * var(noise) ~= 100. | 20 * var(noise) ~= 100. |
21 */ | 21 */ |
22 static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20; | 22 static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20; |
23 static const unsigned int SSE_THRESHOLD = 16 * 16 * 40; | 23 static const unsigned int SSE_THRESHOLD = 16 * 16 * 40; |
| 24 static const unsigned int SSE_THRESHOLD_HIGH = 16 * 16 * 60; |
24 | 25 |
25 /* | 26 /* |
26 * The filter function was modified to reduce the computational complexity. | 27 * The filter function was modified to reduce the computational complexity. |
27 * Step 1: | 28 * Step 1: |
28 * Instead of applying tap coefficients for each pixel, we calculated the | 29 * Instead of applying tap coefficients for each pixel, we calculated the |
29 * pixel adjustments vs. pixel diff value ahead of time. | 30 * pixel adjustments vs. pixel diff value ahead of time. |
30 * adjustment = filtered_value - current_raw | 31 * adjustment = filtered_value - current_raw |
31 * = (filter_coefficient * diff + 128) >> 8 | 32 * = (filter_coefficient * diff + 128) >> 8 |
32 * where | 33 * where |
33 * filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3)); | 34 * filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3)); |
(...skipping 13 matching lines...) Expand all Loading... |
47 * [-7, -4] -3 -4 | 48 * [-7, -4] -3 -4 |
48 * [-3, 3] diff diff | 49 * [-3, 3] diff diff |
49 * [4, 7] 3 4 | 50 * [4, 7] 3 4 |
50 * [8, 15] 4 5 | 51 * [8, 15] 4 5 |
51 * [16, 255] 6 7 | 52 * [16, 255] 6 7 |
52 */ | 53 */ |
53 | 54 |
54 int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride, | 55 int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride, |
55 unsigned char *running_avg_y, int avg_y_stride, | 56 unsigned char *running_avg_y, int avg_y_stride, |
56 unsigned char *sig, int sig_stride, | 57 unsigned char *sig, int sig_stride, |
57 unsigned int motion_magnitude) | 58 unsigned int motion_magnitude, |
| 59 int increase_denoising) |
58 { | 60 { |
59 unsigned char *running_avg_y_start = running_avg_y; | 61 unsigned char *running_avg_y_start = running_avg_y; |
60 unsigned char *sig_start = sig; | 62 unsigned char *sig_start = sig; |
61 int r, c, i; | 63 int sum_diff_thresh; |
| 64 int r, c; |
62 int sum_diff = 0; | 65 int sum_diff = 0; |
63 int adj_val[3] = {3, 4, 6}; | 66 int adj_val[3] = {3, 4, 6}; |
64 | 67 int shift_inc1 = 0; |
| 68 int shift_inc2 = 1; |
65 /* If motion_magnitude is small, making the denoiser more aggressive by | 69 /* If motion_magnitude is small, making the denoiser more aggressive by |
66 * increasing the adjustment for each level. */ | 70 * increasing the adjustment for each level. Add another increment for |
| 71 * blocks that are labeled for increase denoising. */ |
67 if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) | 72 if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) |
68 { | 73 { |
69 for (i = 0; i < 3; i++) | 74 if (increase_denoising) { |
70 adj_val[i] += 1; | 75 shift_inc1 = 1; |
| 76 shift_inc2 = 2; |
| 77 } |
| 78 adj_val[0] += shift_inc2; |
| 79 adj_val[1] += shift_inc2; |
| 80 adj_val[2] += shift_inc2; |
71 } | 81 } |
72 | 82 |
73 for (r = 0; r < 16; ++r) | 83 for (r = 0; r < 16; ++r) |
74 { | 84 { |
75 for (c = 0; c < 16; ++c) | 85 for (c = 0; c < 16; ++c) |
76 { | 86 { |
77 int diff = 0; | 87 int diff = 0; |
78 int adjustment = 0; | 88 int adjustment = 0; |
79 int absdiff = 0; | 89 int absdiff = 0; |
80 | 90 |
81 diff = mc_running_avg_y[c] - sig[c]; | 91 diff = mc_running_avg_y[c] - sig[c]; |
82 absdiff = abs(diff); | 92 absdiff = abs(diff); |
83 | 93 |
84 /* When |diff| < 4, use pixel value from last denoised raw. */ | 94 // When |diff| <= |3 + shift_inc1|, use pixel value from |
85 if (absdiff <= 3) | 95 // last denoised raw. |
| 96 if (absdiff <= 3 + shift_inc1) |
86 { | 97 { |
87 running_avg_y[c] = mc_running_avg_y[c]; | 98 running_avg_y[c] = mc_running_avg_y[c]; |
88 sum_diff += diff; | 99 sum_diff += diff; |
89 } | 100 } |
90 else | 101 else |
91 { | 102 { |
92 if (absdiff >= 4 && absdiff <= 7) | 103 if (absdiff >= 4 && absdiff <= 7) |
93 adjustment = adj_val[0]; | 104 adjustment = adj_val[0]; |
94 else if (absdiff >= 8 && absdiff <= 15) | 105 else if (absdiff >= 8 && absdiff <= 15) |
95 adjustment = adj_val[1]; | 106 adjustment = adj_val[1]; |
(...skipping 20 matching lines...) Expand all Loading... |
116 } | 127 } |
117 } | 128 } |
118 } | 129 } |
119 | 130 |
120 /* Update pointers for next iteration. */ | 131 /* Update pointers for next iteration. */ |
121 sig += sig_stride; | 132 sig += sig_stride; |
122 mc_running_avg_y += mc_avg_y_stride; | 133 mc_running_avg_y += mc_avg_y_stride; |
123 running_avg_y += avg_y_stride; | 134 running_avg_y += avg_y_stride; |
124 } | 135 } |
125 | 136 |
126 if (abs(sum_diff) > SUM_DIFF_THRESHOLD) | 137 sum_diff_thresh= SUM_DIFF_THRESHOLD; |
| 138 if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH; |
| 139 if (abs(sum_diff) > sum_diff_thresh) |
127 return COPY_BLOCK; | 140 return COPY_BLOCK; |
128 | 141 |
129 vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride); | 142 vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride); |
130 return FILTER_BLOCK; | 143 return FILTER_BLOCK; |
131 } | 144 } |
132 | 145 |
133 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) | 146 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) |
134 { | 147 { |
135 int i; | 148 int i; |
136 assert(denoiser); | 149 assert(denoiser); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, | 193 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, |
181 MACROBLOCK *x, | 194 MACROBLOCK *x, |
182 unsigned int best_sse, | 195 unsigned int best_sse, |
183 unsigned int zero_mv_sse, | 196 unsigned int zero_mv_sse, |
184 int recon_yoffset, | 197 int recon_yoffset, |
185 int recon_uvoffset) | 198 int recon_uvoffset) |
186 { | 199 { |
187 int mv_row; | 200 int mv_row; |
188 int mv_col; | 201 int mv_col; |
189 unsigned int motion_magnitude2; | 202 unsigned int motion_magnitude2; |
190 | 203 unsigned int sse_thresh; |
191 MV_REFERENCE_FRAME frame = x->best_reference_frame; | 204 MV_REFERENCE_FRAME frame = x->best_reference_frame; |
192 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; | 205 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; |
193 | 206 |
194 enum vp8_denoiser_decision decision = FILTER_BLOCK; | 207 enum vp8_denoiser_decision decision = FILTER_BLOCK; |
195 | 208 |
196 if (zero_frame) | 209 if (zero_frame) |
197 { | 210 { |
198 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; | 211 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; |
199 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; | 212 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; |
200 YV12_BUFFER_CONFIG saved_pre,saved_dst; | 213 YV12_BUFFER_CONFIG saved_pre,saved_dst; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 } | 278 } |
266 filter_xd->pre = saved_pre; | 279 filter_xd->pre = saved_pre; |
267 filter_xd->dst = saved_dst; | 280 filter_xd->dst = saved_dst; |
268 *mbmi = saved_mbmi; | 281 *mbmi = saved_mbmi; |
269 | 282 |
270 } | 283 } |
271 | 284 |
272 mv_row = x->best_sse_mv.as_mv.row; | 285 mv_row = x->best_sse_mv.as_mv.row; |
273 mv_col = x->best_sse_mv.as_mv.col; | 286 mv_col = x->best_sse_mv.as_mv.col; |
274 motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; | 287 motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; |
275 if (best_sse > SSE_THRESHOLD || motion_magnitude2 | 288 sse_thresh = SSE_THRESHOLD; |
| 289 if (x->increase_denoising) sse_thresh = SSE_THRESHOLD_HIGH; |
| 290 |
| 291 if (best_sse > sse_thresh || motion_magnitude2 |
276 > 8 * NOISE_MOTION_THRESHOLD) | 292 > 8 * NOISE_MOTION_THRESHOLD) |
277 { | 293 { |
278 decision = COPY_BLOCK; | 294 decision = COPY_BLOCK; |
279 } | 295 } |
280 | 296 |
281 if (decision == FILTER_BLOCK) | 297 if (decision == FILTER_BLOCK) |
282 { | 298 { |
283 unsigned char *mc_running_avg_y = | 299 unsigned char *mc_running_avg_y = |
284 denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset; | 300 denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset; |
285 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; | 301 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; |
286 unsigned char *running_avg_y = | 302 unsigned char *running_avg_y = |
287 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; | 303 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; |
288 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; | 304 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; |
289 | 305 |
290 /* Filter. */ | 306 /* Filter. */ |
291 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, | 307 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, |
292 running_avg_y, avg_y_stride, | 308 running_avg_y, avg_y_stride, |
293 x->thismb, 16, motion_magnitude2); | 309 x->thismb, 16, motion_magnitude2, |
| 310 x->increase_denoising); |
294 } | 311 } |
295 if (decision == COPY_BLOCK) | 312 if (decision == COPY_BLOCK) |
296 { | 313 { |
297 /* No filtering of this block; it differs too much from the predictor, | 314 /* No filtering of this block; it differs too much from the predictor, |
298 * or the motion vector magnitude is considered too big. | 315 * or the motion vector magnitude is considered too big. |
299 */ | 316 */ |
300 vp8_copy_mem16x16( | 317 vp8_copy_mem16x16( |
301 x->thismb, 16, | 318 x->thismb, 16, |
302 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset
, | 319 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset
, |
303 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); | 320 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); |
304 } | 321 } |
305 } | 322 } |
OLD | NEW |