Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/photo/src/denoising.cpp
16354 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective icvers.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
//M*/
41
42
#include "precomp.hpp"
43
44
#include "fast_nlmeans_denoising_invoker.hpp"
45
#include "fast_nlmeans_multi_denoising_invoker.hpp"
46
#include "fast_nlmeans_denoising_opencl.hpp"
47
48
template<typename ST, typename IT, typename UIT, typename D>
49
static void fastNlMeansDenoising_( const Mat& src, Mat& dst, const std::vector<float>& h,
50
int templateWindowSize, int searchWindowSize)
51
{
52
int hn = (int)h.size();
53
double granularity = (double)std::max(1., (double)dst.total()/(1 << 17));
54
55
switch (CV_MAT_CN(src.type())) {
56
case 1:
57
parallel_for_(cv::Range(0, src.rows),
58
FastNlMeansDenoisingInvoker<ST, IT, UIT, D, int>(
59
src, dst, templateWindowSize, searchWindowSize, &h[0]),
60
granularity);
61
break;
62
case 2:
63
if (hn == 1)
64
parallel_for_(cv::Range(0, src.rows),
65
FastNlMeansDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, int>(
66
src, dst, templateWindowSize, searchWindowSize, &h[0]),
67
granularity);
68
else
69
parallel_for_(cv::Range(0, src.rows),
70
FastNlMeansDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, Vec2i>(
71
src, dst, templateWindowSize, searchWindowSize, &h[0]),
72
granularity);
73
break;
74
case 3:
75
if (hn == 1)
76
parallel_for_(cv::Range(0, src.rows),
77
FastNlMeansDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, int>(
78
src, dst, templateWindowSize, searchWindowSize, &h[0]),
79
granularity);
80
else
81
parallel_for_(cv::Range(0, src.rows),
82
FastNlMeansDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, Vec3i>(
83
src, dst, templateWindowSize, searchWindowSize, &h[0]),
84
granularity);
85
break;
86
case 4:
87
if (hn == 1)
88
parallel_for_(cv::Range(0, src.rows),
89
FastNlMeansDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, int>(
90
src, dst, templateWindowSize, searchWindowSize, &h[0]),
91
granularity);
92
else
93
parallel_for_(cv::Range(0, src.rows),
94
FastNlMeansDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, Vec4i>(
95
src, dst, templateWindowSize, searchWindowSize, &h[0]),
96
granularity);
97
break;
98
default:
99
CV_Error(Error::StsBadArg,
100
"Unsupported number of channels! Only 1, 2, 3, and 4 are supported");
101
}
102
}
103
104
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h,
105
int templateWindowSize, int searchWindowSize)
106
{
107
CV_INSTRUMENT_REGION();
108
109
fastNlMeansDenoising(_src, _dst, std::vector<float>(1, h),
110
templateWindowSize, searchWindowSize);
111
}
112
113
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, const std::vector<float>& h,
114
int templateWindowSize, int searchWindowSize, int normType)
115
{
116
CV_INSTRUMENT_REGION();
117
118
int hn = (int)h.size(), type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
119
CV_Assert(!_src.empty());
120
CV_Assert(hn == 1 || hn == cn);
121
122
Size src_size = _src.size();
123
CV_OCL_RUN(_src.dims() <= 2 && (_src.isUMat() || _dst.isUMat()) &&
124
src_size.width > 5 && src_size.height > 5, // low accuracy on small sizes
125
ocl_fastNlMeansDenoising(_src, _dst, &h[0], hn,
126
templateWindowSize, searchWindowSize, normType))
127
128
Mat src = _src.getMat();
129
_dst.create(src_size, src.type());
130
Mat dst = _dst.getMat();
131
132
switch (normType) {
133
case NORM_L2:
134
switch (depth) {
135
case CV_8U:
136
fastNlMeansDenoising_<uchar, int, unsigned, DistSquared>(src, dst, h,
137
templateWindowSize,
138
searchWindowSize);
139
break;
140
default:
141
CV_Error(Error::StsBadArg,
142
"Unsupported depth! Only CV_8U is supported for NORM_L2");
143
}
144
break;
145
case NORM_L1:
146
switch (depth) {
147
case CV_8U:
148
fastNlMeansDenoising_<uchar, int, unsigned, DistAbs>(src, dst, h,
149
templateWindowSize,
150
searchWindowSize);
151
break;
152
case CV_16U:
153
fastNlMeansDenoising_<ushort, int64, uint64, DistAbs>(src, dst, h,
154
templateWindowSize,
155
searchWindowSize);
156
break;
157
default:
158
CV_Error(Error::StsBadArg,
159
"Unsupported depth! Only CV_8U and CV_16U are supported for NORM_L1");
160
}
161
break;
162
default:
163
CV_Error(Error::StsBadArg,
164
"Unsupported norm type! Only NORM_L2 and NORM_L1 are supported");
165
}
166
}
167
168
void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
169
float h, float hForColorComponents,
170
int templateWindowSize, int searchWindowSize)
171
{
172
CV_INSTRUMENT_REGION();
173
174
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
175
Size src_size = _src.size();
176
if (type != CV_8UC3 && type != CV_8UC4)
177
{
178
CV_Error(Error::StsBadArg, "Type of input image should be CV_8UC3 or CV_8UC4!");
179
return;
180
}
181
182
CV_OCL_RUN(_src.dims() <= 2 && (_dst.isUMat() || _src.isUMat()) &&
183
src_size.width > 5 && src_size.height > 5, // low accuracy on small sizes
184
ocl_fastNlMeansDenoisingColored(_src, _dst, h, hForColorComponents,
185
templateWindowSize, searchWindowSize))
186
187
Mat src = _src.getMat();
188
_dst.create(src_size, type);
189
Mat dst = _dst.getMat();
190
191
Mat src_lab;
192
cvtColor(src, src_lab, COLOR_LBGR2Lab);
193
194
Mat l(src_size, CV_MAKE_TYPE(depth, 1));
195
Mat ab(src_size, CV_MAKE_TYPE(depth, 2));
196
Mat l_ab[] = { l, ab };
197
int from_to[] = { 0,0, 1,1, 2,2 };
198
mixChannels(&src_lab, 1, l_ab, 2, from_to, 3);
199
200
fastNlMeansDenoising(l, l, h, templateWindowSize, searchWindowSize);
201
fastNlMeansDenoising(ab, ab, hForColorComponents, templateWindowSize, searchWindowSize);
202
203
Mat l_ab_denoised[] = { l, ab };
204
Mat dst_lab(src_size, CV_MAKE_TYPE(depth, 3));
205
mixChannels(l_ab_denoised, 2, &dst_lab, 1, from_to, 3);
206
207
cvtColor(dst_lab, dst, COLOR_Lab2LBGR, cn);
208
}
209
210
static void fastNlMeansDenoisingMultiCheckPreconditions(
211
const std::vector<Mat>& srcImgs,
212
int imgToDenoiseIndex, int temporalWindowSize,
213
int templateWindowSize, int searchWindowSize)
214
{
215
int src_imgs_size = static_cast<int>(srcImgs.size());
216
if (src_imgs_size == 0)
217
{
218
CV_Error(Error::StsBadArg, "Input images vector should not be empty!");
219
}
220
221
if (temporalWindowSize % 2 == 0 ||
222
searchWindowSize % 2 == 0 ||
223
templateWindowSize % 2 == 0) {
224
CV_Error(Error::StsBadArg, "All windows sizes should be odd!");
225
}
226
227
int temporalWindowHalfSize = temporalWindowSize / 2;
228
if (imgToDenoiseIndex - temporalWindowHalfSize < 0 ||
229
imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size)
230
{
231
CV_Error(Error::StsBadArg,
232
"imgToDenoiseIndex and temporalWindowSize "
233
"should be chosen corresponding srcImgs size!");
234
}
235
236
for (int i = 1; i < src_imgs_size; i++)
237
if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type())
238
{
239
CV_Error(Error::StsBadArg, "Input images should have the same size and type!");
240
}
241
}
242
243
template<typename ST, typename IT, typename UIT, typename D>
244
static void fastNlMeansDenoisingMulti_( const std::vector<Mat>& srcImgs, Mat& dst,
245
int imgToDenoiseIndex, int temporalWindowSize,
246
const std::vector<float>& h,
247
int templateWindowSize, int searchWindowSize)
248
{
249
int hn = (int)h.size();
250
double granularity = (double)std::max(1., (double)dst.total()/(1 << 16));
251
252
switch (srcImgs[0].type())
253
{
254
case CV_8U:
255
parallel_for_(cv::Range(0, srcImgs[0].rows),
256
FastNlMeansMultiDenoisingInvoker<uchar, IT, UIT, D, int>(
257
srcImgs, imgToDenoiseIndex, temporalWindowSize,
258
dst, templateWindowSize, searchWindowSize, &h[0]),
259
granularity);
260
break;
261
case CV_8UC2:
262
if (hn == 1)
263
parallel_for_(cv::Range(0, srcImgs[0].rows),
264
FastNlMeansMultiDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, int>(
265
srcImgs, imgToDenoiseIndex, temporalWindowSize,
266
dst, templateWindowSize, searchWindowSize, &h[0]),
267
granularity);
268
else
269
parallel_for_(cv::Range(0, srcImgs[0].rows),
270
FastNlMeansMultiDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, Vec2i>(
271
srcImgs, imgToDenoiseIndex, temporalWindowSize,
272
dst, templateWindowSize, searchWindowSize, &h[0]),
273
granularity);
274
break;
275
case CV_8UC3:
276
if (hn == 1)
277
parallel_for_(cv::Range(0, srcImgs[0].rows),
278
FastNlMeansMultiDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, int>(
279
srcImgs, imgToDenoiseIndex, temporalWindowSize,
280
dst, templateWindowSize, searchWindowSize, &h[0]),
281
granularity);
282
else
283
parallel_for_(cv::Range(0, srcImgs[0].rows),
284
FastNlMeansMultiDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, Vec3i>(
285
srcImgs, imgToDenoiseIndex, temporalWindowSize,
286
dst, templateWindowSize, searchWindowSize, &h[0]),
287
granularity);
288
break;
289
case CV_8UC4:
290
if (hn == 1)
291
parallel_for_(cv::Range(0, srcImgs[0].rows),
292
FastNlMeansMultiDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, int>(
293
srcImgs, imgToDenoiseIndex, temporalWindowSize,
294
dst, templateWindowSize, searchWindowSize, &h[0]),
295
granularity);
296
else
297
parallel_for_(cv::Range(0, srcImgs[0].rows),
298
FastNlMeansMultiDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, Vec4i>(
299
srcImgs, imgToDenoiseIndex, temporalWindowSize,
300
dst, templateWindowSize, searchWindowSize, &h[0]),
301
granularity);
302
break;
303
default:
304
CV_Error(Error::StsBadArg,
305
"Unsupported image format! Only CV_8U, CV_8UC2, CV_8UC3 and CV_8UC4 are supported");
306
}
307
}
308
309
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
310
int imgToDenoiseIndex, int temporalWindowSize,
311
float h, int templateWindowSize, int searchWindowSize)
312
{
313
CV_INSTRUMENT_REGION();
314
315
fastNlMeansDenoisingMulti(_srcImgs, _dst, imgToDenoiseIndex, temporalWindowSize,
316
std::vector<float>(1, h), templateWindowSize, searchWindowSize);
317
}
318
319
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
320
int imgToDenoiseIndex, int temporalWindowSize,
321
const std::vector<float>& h,
322
int templateWindowSize, int searchWindowSize, int normType)
323
{
324
CV_INSTRUMENT_REGION();
325
326
std::vector<Mat> srcImgs;
327
_srcImgs.getMatVector(srcImgs);
328
329
fastNlMeansDenoisingMultiCheckPreconditions(
330
srcImgs, imgToDenoiseIndex,
331
temporalWindowSize, templateWindowSize, searchWindowSize);
332
333
int hn = (int)h.size();
334
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
335
CV_Assert(hn == 1 || hn == cn);
336
337
_dst.create(srcImgs[0].size(), srcImgs[0].type());
338
Mat dst = _dst.getMat();
339
340
switch (normType) {
341
case NORM_L2:
342
switch (depth) {
343
case CV_8U:
344
fastNlMeansDenoisingMulti_<uchar, int, unsigned,
345
DistSquared>(srcImgs, dst,
346
imgToDenoiseIndex, temporalWindowSize,
347
h,
348
templateWindowSize, searchWindowSize);
349
break;
350
default:
351
CV_Error(Error::StsBadArg,
352
"Unsupported depth! Only CV_8U is supported for NORM_L2");
353
}
354
break;
355
case NORM_L1:
356
switch (depth) {
357
case CV_8U:
358
fastNlMeansDenoisingMulti_<uchar, int, unsigned,
359
DistAbs>(srcImgs, dst,
360
imgToDenoiseIndex, temporalWindowSize,
361
h,
362
templateWindowSize, searchWindowSize);
363
break;
364
case CV_16U:
365
fastNlMeansDenoisingMulti_<ushort, int64, uint64,
366
DistAbs>(srcImgs, dst,
367
imgToDenoiseIndex, temporalWindowSize,
368
h,
369
templateWindowSize, searchWindowSize);
370
break;
371
default:
372
CV_Error(Error::StsBadArg,
373
"Unsupported depth! Only CV_8U and CV_16U are supported for NORM_L1");
374
}
375
break;
376
default:
377
CV_Error(Error::StsBadArg,
378
"Unsupported norm type! Only NORM_L2 and NORM_L1 are supported");
379
}
380
}
381
382
void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
383
int imgToDenoiseIndex, int temporalWindowSize,
384
float h, float hForColorComponents,
385
int templateWindowSize, int searchWindowSize)
386
{
387
CV_INSTRUMENT_REGION();
388
389
std::vector<Mat> srcImgs;
390
_srcImgs.getMatVector(srcImgs);
391
392
fastNlMeansDenoisingMultiCheckPreconditions(
393
srcImgs, imgToDenoiseIndex,
394
temporalWindowSize, templateWindowSize, searchWindowSize);
395
396
_dst.create(srcImgs[0].size(), srcImgs[0].type());
397
Mat dst = _dst.getMat();
398
399
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type);
400
int src_imgs_size = static_cast<int>(srcImgs.size());
401
402
if (type != CV_8UC3)
403
{
404
CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!");
405
return;
406
}
407
408
int from_to[] = { 0,0, 1,1, 2,2 };
409
410
// TODO convert only required images
411
std::vector<Mat> src_lab(src_imgs_size);
412
std::vector<Mat> l(src_imgs_size);
413
std::vector<Mat> ab(src_imgs_size);
414
for (int i = 0; i < src_imgs_size; i++)
415
{
416
src_lab[i] = Mat::zeros(srcImgs[0].size(), type);
417
l[i] = Mat::zeros(srcImgs[0].size(), CV_MAKE_TYPE(depth, 1));
418
ab[i] = Mat::zeros(srcImgs[0].size(), CV_MAKE_TYPE(depth, 2));
419
cvtColor(srcImgs[i], src_lab[i], COLOR_LBGR2Lab);
420
421
Mat l_ab[] = { l[i], ab[i] };
422
mixChannels(&src_lab[i], 1, l_ab, 2, from_to, 3);
423
}
424
425
Mat dst_l;
426
Mat dst_ab;
427
428
fastNlMeansDenoisingMulti(
429
l, dst_l, imgToDenoiseIndex, temporalWindowSize,
430
h, templateWindowSize, searchWindowSize);
431
432
fastNlMeansDenoisingMulti(
433
ab, dst_ab, imgToDenoiseIndex, temporalWindowSize,
434
hForColorComponents, templateWindowSize, searchWindowSize);
435
436
Mat l_ab_denoised[] = { dst_l, dst_ab };
437
Mat dst_lab(srcImgs[0].size(), srcImgs[0].type());
438
mixChannels(l_ab_denoised, 2, &dst_lab, 1, from_to, 3);
439
440
cvtColor(dst_lab, dst, COLOR_Lab2LBGR);
441
}
442
443