Skip to content

Commit 33ffe33

Browse files
committed
Fixed a stupid mistake that the order of applying DCT and IDCT is reversed
Fixed a stupid mistake that the order of applying DCT and IDCT is reversed (it should be DCT->filter->IDCT), which leads to over-filtering in fine structures and produces artifacts such as blocking, ringing and desaturation. Now it acctually filters as expected. Adjust hard-thresholding table to fit the unnormalized DCT, to be equivalent to filtering in orthogonal transform Default value of hard_thr changed from 2.3 to 2.8 for profile="vn", from 2.2 to 2.7 for other profiles Some function arguments changed to const reference Some read-only references in function arguments changed to const Some read-only member functions changed to const Cosmetics
1 parent 26796d7 commit 33ffe33

17 files changed

+228
-194
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ bm3d.Basic(clip input[, clip ref=input, string profile="fast", float[] sigma=[10
104104

105105
- sigma:<br />
106106
The strength of denoising, valid range [0, +inf), default [10,10,10].<br />
107+
This denoising algorithm is very sensitive to the sigma, so adjust it carefully according to the source.<br />
107108
Technically, this is the standard deviation of i.i.d. zero mean additive white Gaussian noise in 8 bit scale. BM3D denoising filter is designed based on this noise model, and best fit for attenuating it.<br />
108109
An array up to 3 elements can be assigned to set different sigma for Y,U,V channels. If less than 3 elements assigned, the last element's value will be assigned to the undefined elements.<br />
109110
0 will disable the processing for corresponding channel.
@@ -141,7 +142,7 @@ bm3d.Basic(clip input[, clip ref=input, string profile="fast", float[] sigma=[10
141142

142143
- hard_thr:<br />
143144
The threshold parameter for the hard-thresholding in 3D transformed domain, in 8 bit scale, valid range (0, +inf).<br />
144-
Larger results in stronger hard-threshold filtering in frequency domain.<br />
145+
Larger value results in stronger hard-threshold filtering in frequency domain.<br />
145146
Usually, to tweak denoising strength, it's better to adjust "sigma" rather than "hard_thr".
146147

147148
- matrix:<br />
@@ -296,7 +297,7 @@ bm3d.Basic / bm3d.Final / bm3d.VBasic / bm3d.VFinal
296297
bm3d.VBasic / bm3d.VFinal
297298
---------------------------------------------------
298299
| profile || radius | ps_num | ps_range | ps_step |
299-
--------------------------------------------------
300+
---------------------------------------------------
300301
| "fast" || 1/1 | 2/2 | 4/5 | 1/1/1/1 |
301302
| "lc" || 2/2 | 2/2 | 4/5 | 1/1/1/1 |
302303
| "np" || 3/3 | 2/2 | 5/6 | 1/1/1/1 |
@@ -310,11 +311,11 @@ bm3d.Basic & bm3d.VBasic / bm3d.Final & bm3d.VFinal
310311
--------------------------------------------------------------
311312
| profile || th_mse | hard_thr |
312313
--------------------------------------------------------------
313-
| "fast" || sigma[0]*80+400 / sigma[0]*10+200 | 2.2 / NUL |
314-
| "lc" || sigma[0]*80+400 / sigma[0]*10+200 | 2.2 / NUL |
315-
| "np" || sigma[0]*80+400 / sigma[0]*10+200 | 2.2 / NUL |
316-
| "high" || sigma[0]*80+400 / sigma[0]*10+200 | 2.2 / NUL |
317-
| "vn" || sigma[0]*150+1000 / sigma[0]*40+400 | 2.3 / NUL |
314+
| "fast" || sigma[0]*80+400 / sigma[0]*10+200 | 2.7 / NUL |
315+
| "lc" || sigma[0]*80+400 / sigma[0]*10+200 | 2.7 / NUL |
316+
| "np" || sigma[0]*80+400 / sigma[0]*10+200 | 2.7 / NUL |
317+
| "high" || sigma[0]*80+400 / sigma[0]*10+200 | 2.7 / NUL |
318+
| "vn" || sigma[0]*150+1000 / sigma[0]*40+400 | 2.8 / NUL |
318319
--------------------------------------------------------------
319320
```
320321

include/BM3D_Base.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,18 +230,18 @@ class BM3D_Process_Base
230230
_NewFrame(width, height, dfi == fi);
231231
}
232232

233-
void Kernel(FLType *dst, const FLType *src, const FLType *ref);
233+
void Kernel(FLType *dst, const FLType *src, const FLType *ref) const;
234234

235235
void Kernel(FLType *dstY, FLType *dstU, FLType *dstV,
236236
const FLType *srcY, const FLType *srcU, const FLType *srcV,
237-
const FLType *refY, const FLType *refU, const FLType *refV);
237+
const FLType *refY, const FLType *refU, const FLType *refV) const;
238238

239-
PosPairCode BlockMatching(const FLType *ref, PCType j, PCType i);
239+
PosPairCode BlockMatching(const FLType *ref, PCType j, PCType i) const;
240240

241241
virtual void CollaborativeFilter(int plane,
242242
FLType *ResNum, FLType *ResDen,
243243
const FLType *src, const FLType *ref,
244-
const PosPairCode &code) = 0;
244+
const PosPairCode &code) const = 0;
245245
};
246246

247247

include/BM3D_Basic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class BM3D_Basic_Process
8585
virtual void CollaborativeFilter(int plane,
8686
FLType *ResNum, FLType *ResDen,
8787
const FLType *src, const FLType *ref,
88-
const PosPairCode &code) override;
88+
const PosPairCode &code) const override;
8989
};
9090

9191

include/BM3D_Final.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class BM3D_Final_Process
8585
virtual void CollaborativeFilter(int plane,
8686
FLType *ResNum, FLType *ResDen,
8787
const FLType *src, const FLType *ref,
88-
const PosPairCode &code) override;
88+
const PosPairCode &code) const override;
8989
};
9090

9191

include/Block.h

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ class Block
7676
}
7777

7878
template < typename _St2, typename _Fn1 >
79-
void for_each(_St2 &right, _Fn1 _Func)
79+
void for_each(_St2 &data2, _Fn1 _Func)
8080
{
81-
Block_For_each(*this, right, _Func);
81+
Block_For_each(*this, data2, _Func);
8282
}
8383

8484
template < typename _St2, typename _Fn1 >
85-
void for_each(_St2 &right, _Fn1 _Func) const
85+
void for_each(_St2 &data2, _Fn1 _Func) const
8686
{
87-
Block_For_each(*this, right, _Func);
87+
Block_For_each(*this, data2, _Func);
8888
}
8989

9090
template < typename _Fn1 >
@@ -103,7 +103,7 @@ class Block
103103
// Default constructor
104104
Block() {}
105105

106-
Block(PCType _Height, PCType _Width, PosType pos, bool Init = true, value_type Value = 0)
106+
Block(PCType _Height, PCType _Width, const PosType &pos, bool Init = true, value_type Value = 0)
107107
: Height_(_Height), Width_(_Width), PixelCount_(Height_ * Width_), pos_(pos)
108108
{
109109
AlignedMalloc(Data_, size());
@@ -113,13 +113,13 @@ class Block
113113

114114
// Constructor from plane pointer and PosType
115115
template < typename _St1 >
116-
Block(const _St1 *src, PCType src_stride, PCType _Height, PCType _Width, PosType pos)
116+
Block(const _St1 *src, PCType src_stride, PCType _Height, PCType _Width, const PosType &pos)
117117
: Block(_Height, _Width, pos, false)
118118
{
119119
From(src, src_stride);
120120
}
121121

122-
// Constructor from src
122+
// Constructor from src Block
123123
Block(const _Myt &src, bool Init, value_type Value = 0)
124124
: Block(src.Height_, src.Width_, src.pos_, Init, Value)
125125
{}
@@ -275,10 +275,9 @@ class Block
275275
}
276276

277277
template < typename _St1 >
278-
void From(const _St1 *src, PCType src_stride, PosType pos)
278+
void From(const _St1 *src, PCType src_stride, const PosType &pos)
279279
{
280280
pos_ = pos;
281-
282281
From(src, src_stride);
283282
}
284283

@@ -303,7 +302,7 @@ class Block
303302
// Accumulate functions
304303

305304
template < typename _St1 >
306-
void AddFrom(const _St1 *src, PCType src_stride, PosType pos)
305+
void AddFrom(const _St1 *src, PCType src_stride, const PosType &pos)
307306
{
308307
auto dstp = data();
309308
auto srcp = src + pos.y * src_stride + pos.x;
@@ -320,7 +319,7 @@ class Block
320319
}
321320

322321
template < typename _St1, typename _Gt1 >
323-
void AddFrom(const _St1 *src, PCType src_stride, PosType pos, _Gt1 gain)
322+
void AddFrom(const _St1 *src, PCType src_stride, const PosType &pos, _Gt1 gain)
324323
{
325324
auto dstp = data();
326325
auto srcp = src + pos.y * src_stride + pos.x;
@@ -403,7 +402,7 @@ class Block
403402
}
404403

405404
////////////////////////////////////////////////////////////////
406-
// Block matching functions
405+
// Single block-matching functions
407406

408407
template < typename _St1 >
409408
PosPair BlockMatching(const _St1 *src, PCType src_height, PCType src_width, PCType src_stride, _St1 src_range,
@@ -474,6 +473,9 @@ class Block
474473
return PosPair(static_cast<KeyType>(distMin * distMul), pos);
475474
}
476475

476+
////////////////////////////////////////////////////////////////
477+
// Multiple block-matching functions
478+
477479
template < typename _St1 >
478480
void BlockMatchingMulti(PosPairCode &match_code, const _St1 *src, PCType src_stride, _St1 src_range,
479481
const PosCode &search_pos, double thMSE) const
@@ -798,7 +800,7 @@ class BlockGroup
798800

799801
// Constructor from plane pointer and Pos3PairCode
800802
template < typename _St1 >
801-
BlockGroup(std::vector<const _St1 *> src, PCType src_stride, const Pos3PairCode &code,
803+
BlockGroup(const std::vector<const _St1 *> &src, PCType src_stride, const Pos3PairCode &code,
802804
PCType _GroupSize = -1, PCType _Height = 16, PCType _Width = 16)
803805
: Height_(_Height), Width_(_Width)
804806
{
@@ -984,7 +986,7 @@ class BlockGroup
984986
// Read/Store functions
985987

986988
template < typename _St1 >
987-
_Myt &From(const _St1 *src, PCType src_stride)
989+
void From(const _St1 *src, PCType src_stride)
988990
{
989991
auto dstp = data();
990992

@@ -1002,12 +1004,10 @@ class BlockGroup
10021004
}
10031005
}
10041006
}
1005-
1006-
return *this;
10071007
}
10081008

10091009
template < typename _St1 >
1010-
_Myt &From(std::vector<const _St1 *> src, PCType src_stride)
1010+
void From(const std::vector<const _St1 *> &src, PCType src_stride)
10111011
{
10121012
auto dstp = data();
10131013

@@ -1025,8 +1025,6 @@ class BlockGroup
10251025
}
10261026
}
10271027
}
1028-
1029-
return *this;
10301028
}
10311029

10321030
template < typename _Dt1 >
@@ -1051,7 +1049,7 @@ class BlockGroup
10511049
}
10521050

10531051
template < typename _Dt1 >
1054-
void To(std::vector<_Dt1 *> dst, PCType dst_stride) const
1052+
void To(const std::vector<_Dt1 *> &dst, PCType dst_stride) const
10551053
{
10561054
auto srcp = data();
10571055

@@ -1117,7 +1115,7 @@ class BlockGroup
11171115
}
11181116

11191117
template < typename _Dt1 >
1120-
void AddTo(std::vector<_Dt1 *> dst, PCType dst_stride) const
1118+
void AddTo(const std::vector<_Dt1 *> &dst, PCType dst_stride) const
11211119
{
11221120
auto srcp = data();
11231121

@@ -1138,7 +1136,7 @@ class BlockGroup
11381136
}
11391137

11401138
template < typename _Dt1, typename _Gt1 >
1141-
void AddTo(std::vector<_Dt1 *> dst, PCType dst_stride, _Gt1 gain) const
1139+
void AddTo(const std::vector<_Dt1 *> &dst, PCType dst_stride, _Gt1 gain) const
11421140
{
11431141
auto srcp = data();
11441142

@@ -1197,7 +1195,7 @@ class BlockGroup
11971195
}
11981196

11991197
template < typename _Dt1 >
1200-
void CountTo(std::vector<_Dt1 *> dst, PCType dst_stride) const
1198+
void CountTo(const std::vector<_Dt1 *> &dst, PCType dst_stride) const
12011199
{
12021200
for (PCType z = 0; z < GroupSize(); ++z)
12031201
{
@@ -1216,7 +1214,7 @@ class BlockGroup
12161214
}
12171215

12181216
template < typename _Dt1 >
1219-
void CountTo(std::vector<_Dt1 *> dst, PCType dst_stride, _Dt1 value) const
1217+
void CountTo(const std::vector<_Dt1 *> &dst, PCType dst_stride, _Dt1 value) const
12201218
{
12211219
for (PCType z = 0; z < GroupSize(); ++z)
12221220
{
@@ -1239,7 +1237,7 @@ class BlockGroup
12391237
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12401238

12411239

1242-
template < typename _St1, typename _Fn1 > inline
1240+
template < typename _St1, typename _Fn1 >
12431241
void Block_For_each(_St1 &data, _Fn1 &&_Func)
12441242
{
12451243
auto datap = data.data();
@@ -1250,26 +1248,24 @@ void Block_For_each(_St1 &data, _Fn1 &&_Func)
12501248
}
12511249
}
12521250

1253-
template < typename _St1, typename _St2, typename _Fn1 > inline
1254-
void Block_For_each(_St1 &left, _St2 &right, _Fn1 &&_Func)
1251+
template < typename _St1, typename _St2, typename _Fn1 >
1252+
void Block_For_each(_St1 &data1, _St2 &data2, _Fn1 &&_Func)
12551253
{
1256-
const char *FunctionName = "Block_For_each";
1257-
if (left.size() != right.size())
1254+
if (data1.size() != data2.size())
12581255
{
1259-
std::cerr << FunctionName << ": size() of left and right must be the same.\n";
1260-
exit(EXIT_FAILURE);
1256+
DEBUG_FAIL("Block_For_each: size() of data1 and data2 must be the same.");
12611257
}
12621258

1263-
auto leftp = left.data();
1264-
auto rightp = right.data();
1259+
auto data1p = data1.data();
1260+
auto data2p = data2.data();
12651261

1266-
for (auto upper = leftp + left.size(); leftp != upper; ++leftp, ++rightp)
1262+
for (auto upper = data1p + data1.size(); data1p != upper; ++data1p, ++data2p)
12671263
{
1268-
_Func(*leftp, *rightp);
1264+
_Func(*data1p, *data2p);
12691265
}
12701266
}
12711267

1272-
template < typename _St1, typename _Fn1 > inline
1268+
template < typename _St1, typename _Fn1 >
12731269
void Block_Transform(_St1 &data, _Fn1 &&_Func)
12741270
{
12751271
auto datap = data.data();
@@ -1280,14 +1276,12 @@ void Block_Transform(_St1 &data, _Fn1 &&_Func)
12801276
}
12811277
}
12821278

1283-
template < typename _Dt1, typename _St1, typename _Fn1 > inline
1279+
template < typename _Dt1, typename _St1, typename _Fn1 >
12841280
void Block_Transform(_Dt1 &dst, const _St1 &src, _Fn1 &&_Func)
12851281
{
1286-
const char *FunctionName = "Block_Transform";
12871282
if (dst.size() != src.size())
12881283
{
1289-
std::cerr << FunctionName << ": size() of dst and src must be the same.\n";
1290-
exit(EXIT_FAILURE);
1284+
DEBUG_FAIL("Block_Transform: size() of dst and src must be the same.");
12911285
}
12921286

12931287
auto dstp = dst.data();

0 commit comments

Comments
 (0)