Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(732)

Side by Side Diff: webrtc/modules/video_processing/test/denoiser_test.cc

Issue 1822333003: External denoiser based on noise estimation and moving object detection. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC 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 <string.h> 11 #include <string.h>
12 12
13 #include <memory> 13 #include <memory>
14 14
15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
16 #include "webrtc/modules/video_processing/include/video_processing.h" 16 #include "webrtc/modules/video_processing/include/video_processing.h"
17 #include "webrtc/modules/video_processing/test/video_processing_unittest.h" 17 #include "webrtc/modules/video_processing/test/video_processing_unittest.h"
18 #include "webrtc/modules/video_processing/video_denoiser.h" 18 #include "webrtc/modules/video_processing/video_denoiser.h"
19 #include "webrtc/test/frame_utils.h" 19 #include "webrtc/test/frame_utils.h"
20 20
21 namespace webrtc { 21 namespace webrtc {
22 22
23 TEST_F(VideoProcessingTest, CopyMem) { 23 TEST_F(VideoProcessingTest, CopyMem) {
24 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false)); 24 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false, nullptr));
25 std::unique_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true)); 25 std::unique_ptr<DenoiserFilter> df_sse_neon(
26 DenoiserFilter::Create(true, nullptr));
26 uint8_t src[16 * 16], dst[16 * 16]; 27 uint8_t src[16 * 16], dst[16 * 16];
27 for (int i = 0; i < 16; ++i) { 28 for (int i = 0; i < 16; ++i) {
28 for (int j = 0; j < 16; ++j) { 29 for (int j = 0; j < 16; ++j) {
29 src[i * 16 + j] = i * 16 + j; 30 src[i * 16 + j] = i * 16 + j;
30 } 31 }
31 } 32 }
32 33
33 memset(dst, 0, 8 * 8); 34 memset(dst, 0, 8 * 8);
34 df_c->CopyMem8x8(src, 8, dst, 8); 35 df_c->CopyMem8x8(src, 8, dst, 8);
35 EXPECT_EQ(0, memcmp(src, dst, 8 * 8)); 36 EXPECT_EQ(0, memcmp(src, dst, 8 * 8));
36 37
37 memset(dst, 0, 16 * 16); 38 memset(dst, 0, 16 * 16);
38 df_c->CopyMem16x16(src, 16, dst, 16); 39 df_c->CopyMem16x16(src, 16, dst, 16);
39 EXPECT_EQ(0, memcmp(src, dst, 16 * 16)); 40 EXPECT_EQ(0, memcmp(src, dst, 16 * 16));
40 41
41 memset(dst, 0, 8 * 8); 42 memset(dst, 0, 8 * 8);
42 df_sse_neon->CopyMem16x16(src, 8, dst, 8); 43 df_sse_neon->CopyMem16x16(src, 8, dst, 8);
43 EXPECT_EQ(0, memcmp(src, dst, 8 * 8)); 44 EXPECT_EQ(0, memcmp(src, dst, 8 * 8));
44 45
45 memset(dst, 0, 16 * 16); 46 memset(dst, 0, 16 * 16);
46 df_sse_neon->CopyMem16x16(src, 16, dst, 16); 47 df_sse_neon->CopyMem16x16(src, 16, dst, 16);
47 EXPECT_EQ(0, memcmp(src, dst, 16 * 16)); 48 EXPECT_EQ(0, memcmp(src, dst, 16 * 16));
48 } 49 }
49 50
50 TEST_F(VideoProcessingTest, Variance) { 51 TEST_F(VideoProcessingTest, Variance) {
51 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false)); 52 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false, nullptr));
52 std::unique_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true)); 53 std::unique_ptr<DenoiserFilter> df_sse_neon(
54 DenoiserFilter::Create(true, nullptr));
53 uint8_t src[16 * 16], dst[16 * 16]; 55 uint8_t src[16 * 16], dst[16 * 16];
54 uint32_t sum = 0, sse = 0, var; 56 uint32_t sum = 0, sse = 0, var;
55 for (int i = 0; i < 16; ++i) { 57 for (int i = 0; i < 16; ++i) {
56 for (int j = 0; j < 16; ++j) { 58 for (int j = 0; j < 16; ++j) {
57 src[i * 16 + j] = i * 16 + j; 59 src[i * 16 + j] = i * 16 + j;
58 } 60 }
59 } 61 }
60 // Compute the 16x8 variance of the 16x16 block. 62 // Compute the 16x8 variance of the 16x16 block.
61 for (int i = 0; i < 8; ++i) { 63 for (int i = 0; i < 8; ++i) {
62 for (int j = 0; j < 16; ++j) { 64 for (int j = 0; j < 16; ++j) {
63 sum += (i * 32 + j); 65 sum += (i * 32 + j);
64 sse += (i * 32 + j) * (i * 32 + j); 66 sse += (i * 32 + j) * (i * 32 + j);
65 } 67 }
66 } 68 }
67 var = sse - ((sum * sum) >> 7); 69 var = sse - ((sum * sum) >> 7);
68 memset(dst, 0, 16 * 16); 70 memset(dst, 0, 16 * 16);
69 EXPECT_EQ(var, df_c->Variance16x8(src, 16, dst, 16, &sse)); 71 EXPECT_EQ(var, df_c->Variance16x8(src, 16, dst, 16, &sse));
70 EXPECT_EQ(var, df_sse_neon->Variance16x8(src, 16, dst, 16, &sse)); 72 EXPECT_EQ(var, df_sse_neon->Variance16x8(src, 16, dst, 16, &sse));
71 } 73 }
72 74
73 TEST_F(VideoProcessingTest, MbDenoise) { 75 TEST_F(VideoProcessingTest, MbDenoise) {
74 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false)); 76 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false, nullptr));
75 std::unique_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true)); 77 std::unique_ptr<DenoiserFilter> df_sse_neon(
76 uint8_t running_src[16 * 16], src[16 * 16], dst[16 * 16], dst_ref[16 * 16]; 78 DenoiserFilter::Create(true, nullptr));
79 uint8_t running_src[16 * 16], src[16 * 16];
80 uint8_t dst[16 * 16], dst_sse_neon[16 * 16];
77 81
78 // Test case: |diff| <= |3 + shift_inc1| 82 // Test case: |diff| <= |3 + shift_inc1|
79 for (int i = 0; i < 16; ++i) { 83 for (int i = 0; i < 16; ++i) {
80 for (int j = 0; j < 16; ++j) { 84 for (int j = 0; j < 16; ++j) {
81 running_src[i * 16 + j] = i * 11 + j; 85 running_src[i * 16 + j] = i * 11 + j;
82 src[i * 16 + j] = i * 11 + j + 2; 86 src[i * 16 + j] = i * 11 + j + 2;
83 dst_ref[i * 16 + j] = running_src[i * 16 + j];
84 } 87 }
85 } 88 }
86 memset(dst, 0, 16 * 16); 89 memset(dst, 0, 16 * 16);
87 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 90 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1, false);
88 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16)); 91 memset(dst_sse_neon, 0, 16 * 16);
92 df_sse_neon->MbDenoise(running_src, 16, dst_sse_neon, 16, src, 16, 0, 1,
93 false);
94 EXPECT_EQ(0, memcmp(dst, dst_sse_neon, 16 * 16));
89 95
90 // Test case: |diff| >= |4 + shift_inc1| 96 // Test case: |diff| >= |4 + shift_inc1|
91 for (int i = 0; i < 16; ++i) { 97 for (int i = 0; i < 16; ++i) {
92 for (int j = 0; j < 16; ++j) { 98 for (int j = 0; j < 16; ++j) {
93 running_src[i * 16 + j] = i * 11 + j; 99 running_src[i * 16 + j] = i * 11 + j;
94 src[i * 16 + j] = i * 11 + j + 5; 100 src[i * 16 + j] = i * 11 + j + 5;
95 dst_ref[i * 16 + j] = src[i * 16 + j] - 2;
96 } 101 }
97 } 102 }
98 memset(dst, 0, 16 * 16); 103 memset(dst, 0, 16 * 16);
99 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 104 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1, false);
100 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16)); 105 memset(dst_sse_neon, 0, 16 * 16);
101 memset(dst, 0, 16 * 16); 106 df_sse_neon->MbDenoise(running_src, 16, dst_sse_neon, 16, src, 16, 0, 1,
102 df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 107 false);
103 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16)); 108 EXPECT_EQ(0, memcmp(dst, dst_sse_neon, 16 * 16));
104 109
105 // Test case: |diff| >= 8 110 // Test case: |diff| >= 8
106 for (int i = 0; i < 16; ++i) { 111 for (int i = 0; i < 16; ++i) {
107 for (int j = 0; j < 16; ++j) { 112 for (int j = 0; j < 16; ++j) {
108 running_src[i * 16 + j] = i * 11 + j; 113 running_src[i * 16 + j] = i * 11 + j;
109 src[i * 16 + j] = i * 11 + j + 8; 114 src[i * 16 + j] = i * 11 + j + 8;
110 dst_ref[i * 16 + j] = src[i * 16 + j] - 6;
111 } 115 }
112 } 116 }
113 memset(dst, 0, 16 * 16); 117 memset(dst, 0, 16 * 16);
114 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 118 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1, false);
115 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16)); 119 memset(dst_sse_neon, 0, 16 * 16);
116 memset(dst, 0, 16 * 16); 120 df_sse_neon->MbDenoise(running_src, 16, dst_sse_neon, 16, src, 16, 0, 1,
117 df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 121 false);
118 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16)); 122 EXPECT_EQ(0, memcmp(dst, dst_sse_neon, 16 * 16));
119 123
120 // Test case: |diff| > 15 124 // Test case: |diff| > 15
121 for (int i = 0; i < 16; ++i) { 125 for (int i = 0; i < 16; ++i) {
122 for (int j = 0; j < 16; ++j) { 126 for (int j = 0; j < 16; ++j) {
123 running_src[i * 16 + j] = i * 11 + j; 127 running_src[i * 16 + j] = i * 11 + j;
124 src[i * 16 + j] = i * 11 + j + 16; 128 src[i * 16 + j] = i * 11 + j + 16;
125 } 129 }
126 } 130 }
127 memset(dst, 0, 16 * 16); 131 memset(dst, 0, 16 * 16);
128 DenoiserDecision decision = 132 DenoiserDecision decision =
129 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 133 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1, false);
130 EXPECT_EQ(COPY_BLOCK, decision); 134 EXPECT_EQ(COPY_BLOCK, decision);
131 decision = df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1); 135 decision =
136 df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1, false);
132 EXPECT_EQ(COPY_BLOCK, decision); 137 EXPECT_EQ(COPY_BLOCK, decision);
133 } 138 }
134 139
135 TEST_F(VideoProcessingTest, Denoiser) { 140 TEST_F(VideoProcessingTest, Denoiser) {
136 // Create pure C denoiser. 141 // Create pure C denoiser.
137 VideoDenoiser denoiser_c(false); 142 VideoDenoiser denoiser_c(false);
138 // Create SSE or NEON denoiser. 143 // Create SSE or NEON denoiser.
139 VideoDenoiser denoiser_sse_neon(true); 144 VideoDenoiser denoiser_sse_neon(true);
140 VideoFrame denoised_frame_c; 145 VideoFrame denoised_frame_c;
146 VideoFrame denoised_frame_track_c;
141 VideoFrame denoised_frame_sse_neon; 147 VideoFrame denoised_frame_sse_neon;
148 VideoFrame denoised_frame_track_sse_neon;
142 149
143 std::unique_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]); 150 std::unique_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
144 while (fread(video_buffer.get(), 1, frame_length_, source_file_) == 151 while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
145 frame_length_) { 152 frame_length_) {
146 // Using ConvertToI420 to add stride to the image. 153 // Using ConvertToI420 to add stride to the image.
147 EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_, 154 EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
148 0, kVideoRotation_0, &video_frame_)); 155 0, kVideoRotation_0, &video_frame_));
149 156
150 denoiser_c.DenoiseFrame(video_frame_, &denoised_frame_c); 157 denoiser_c.DenoiseFrame(video_frame_, &denoised_frame_c,
151 denoiser_sse_neon.DenoiseFrame(video_frame_, &denoised_frame_sse_neon); 158 &denoised_frame_track_c, -1);
159 denoiser_sse_neon.DenoiseFrame(video_frame_, &denoised_frame_sse_neon,
160 &denoised_frame_track_sse_neon, -1);
152 161
153 // Denoising results should be the same for C and SSE/NEON denoiser. 162 // Denoising results should be the same for C and SSE/NEON denoiser.
154 ASSERT_TRUE(test::FramesEqual(denoised_frame_c, denoised_frame_sse_neon)); 163 ASSERT_TRUE(test::FramesEqual(denoised_frame_c, denoised_frame_sse_neon));
155 } 164 }
156 ASSERT_NE(0, feof(source_file_)) << "Error reading source file"; 165 ASSERT_NE(0, feof(source_file_)) << "Error reading source file";
157 } 166 }
158 167
159 } // namespace webrtc 168 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_processing/frame_preprocessor.cc ('k') | webrtc/modules/video_processing/util/denoiser_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698