|
|
|
@ -54,28 +54,93 @@ |
|
|
|
|
|
|
|
|
|
namespace cv |
|
|
|
|
{ |
|
|
|
|
void grayDctDenoising(const Mat_<float> &src, Mat_<float> &dst, const double sigma, const int psize) |
|
|
|
|
struct grayDctDenoisingInvoker : public ParallelLoopBody |
|
|
|
|
{ |
|
|
|
|
CV_Assert( src.channels() == 1 ); |
|
|
|
|
public: |
|
|
|
|
grayDctDenoisingInvoker(const Mat_<float> &src, std::vector < Mat_<float> > &patches, const double sigma, const int psize); |
|
|
|
|
~grayDctDenoisingInvoker(); |
|
|
|
|
|
|
|
|
|
Mat_<float> res( src.size(), 0.0f ), |
|
|
|
|
num( src.size(), 0.0f ); |
|
|
|
|
void operator() (const Range &range) const; |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
const Mat_<float> &src; |
|
|
|
|
std::vector < Mat_<float> > &patches; // image decomposition into sliding patches
|
|
|
|
|
|
|
|
|
|
double threshold = 2.0*log(psize)*sigma; |
|
|
|
|
const int psize; // size of block to compute dct
|
|
|
|
|
const double sigma; // expected noise standard deviation
|
|
|
|
|
const double thresh; // thresholding estimate
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i <= src.rows - psize; ++i) |
|
|
|
|
for (int j = 0; j <= src.cols - psize; ++j) |
|
|
|
|
grayDctDenoisingInvoker::grayDctDenoisingInvoker(const Mat_<float> &src, std::vector < Mat_<float> > &patches, |
|
|
|
|
const double sigma, const int psize) |
|
|
|
|
: src(src), patches(patches), sigma(sigma), thresh(3*sigma), psize(psize) {} |
|
|
|
|
grayDctDenoisingInvoker::~grayDctDenoisingInvoker(){} |
|
|
|
|
|
|
|
|
|
void grayDctDenoisingInvoker::operator() (const Range &range) const |
|
|
|
|
{ |
|
|
|
|
for (int i = range.start; i <= range.end - 1; ++i) |
|
|
|
|
{ |
|
|
|
|
Mat_<float> patch = src( Rect(j, i, psize, psize) ).clone(); |
|
|
|
|
int y = i / (src.cols - psize); |
|
|
|
|
int x = i % (src.cols - psize); |
|
|
|
|
|
|
|
|
|
Rect patchNum( x, y, psize, psize ); |
|
|
|
|
|
|
|
|
|
Mat_<float> patch(psize, psize); |
|
|
|
|
src(patchNum).copyTo( patch ); |
|
|
|
|
|
|
|
|
|
dct(patch, patch); |
|
|
|
|
float * ptr = (float *) patch.data; |
|
|
|
|
float *data = (float *) patch.data; |
|
|
|
|
for (int k = 0; k < psize*psize; ++k) |
|
|
|
|
if (fabs(ptr[k]) < threshold) |
|
|
|
|
ptr[k] = 0.0f; |
|
|
|
|
idct(patch, patch); |
|
|
|
|
data[k] *= fabs(data[k]) > thresh; |
|
|
|
|
idct(patch, patches[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grayDctDenoising(const Mat_<float> &src, Mat_<float> &dst, const double sigma, const int psize) |
|
|
|
|
{ |
|
|
|
|
CV_Assert( src.channels() == 1 ); |
|
|
|
|
|
|
|
|
|
//Mat_<float> res( src.size(), 0.0f ),
|
|
|
|
|
// num( src.size(), 0.0f );
|
|
|
|
|
//
|
|
|
|
|
//double threshold = 3*sigma;
|
|
|
|
|
//
|
|
|
|
|
//for (int i = 0; i <= src.rows - psize; ++i)
|
|
|
|
|
// for (int j = 0; j <= src.cols - psize; ++j)
|
|
|
|
|
// {
|
|
|
|
|
// Mat_<float> patch = src( Rect(j, i, psize, psize) ).clone();
|
|
|
|
|
//
|
|
|
|
|
// dct(patch, patch);
|
|
|
|
|
// float * ptr = (float *) patch.data;
|
|
|
|
|
// for (int k = 0; k < psize*psize; ++k)
|
|
|
|
|
// if (fabs(ptr[k]) < threshold)
|
|
|
|
|
// ptr[k] = 0.0f;
|
|
|
|
|
// idct(patch, patch);
|
|
|
|
|
//
|
|
|
|
|
// res( Rect(j, i, psize, psize) ) += patch;
|
|
|
|
|
// num( Rect(j, i, psize, psize) ) += Mat_<float>::ones(psize, psize);
|
|
|
|
|
// }
|
|
|
|
|
//res /= num;
|
|
|
|
|
//
|
|
|
|
|
//res.convertTo( dst, src.type() );
|
|
|
|
|
|
|
|
|
|
int npixels = (src.rows - psize)*(src.cols - psize); |
|
|
|
|
|
|
|
|
|
std::vector < Mat_<float> > patches; |
|
|
|
|
for (int i = 0; i < npixels; ++i) |
|
|
|
|
patches.push_back( Mat_<float>(psize, psize) ); |
|
|
|
|
parallel_for_( cv::Range(0, npixels), |
|
|
|
|
grayDctDenoisingInvoker(src, patches, sigma, psize) ); |
|
|
|
|
|
|
|
|
|
Mat_<float> res( src.size(), 0.0f ), |
|
|
|
|
num( src.size(), 0.0f ); |
|
|
|
|
|
|
|
|
|
for (int k = 0; k < npixels; ++k) |
|
|
|
|
{ |
|
|
|
|
int i = k / (src.cols - psize); |
|
|
|
|
int j = k % (src.cols - psize); |
|
|
|
|
|
|
|
|
|
res( Rect(j, i, psize, psize) ) += patch; |
|
|
|
|
res( Rect(j, i, psize, psize) ) += patches[k]; |
|
|
|
|
num( Rect(j, i, psize, psize) ) += Mat_<float>::ones(psize, psize); |
|
|
|
|
} |
|
|
|
|
res /= num; |
|
|
|
@ -96,9 +161,9 @@ namespace cv |
|
|
|
|
for (Mat_<Vec3f>::const_iterator it = src.begin(); it != src.end(); ++it, ++outIt) |
|
|
|
|
{ |
|
|
|
|
Vec3f rgb = *it; |
|
|
|
|
*outIt = Vec3f(M[0]*rgb[0] + M[3]*rgb[1] + M[6]*rgb[2], |
|
|
|
|
M[1]*rgb[0] + M[4]*rgb[1] + M[7]*rgb[2], |
|
|
|
|
M[2]*rgb[0] + M[5]*rgb[1] + M[8]*rgb[2]); |
|
|
|
|
*outIt = Vec3f(M[0]*rgb[0] + M[1]*rgb[1] + M[2]*rgb[2], |
|
|
|
|
M[3]*rgb[0] + M[4]*rgb[1] + M[5]*rgb[2], |
|
|
|
|
M[6]*rgb[0] + M[7]*rgb[1] + M[8]*rgb[2]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*************************************/ |
|
|
|
@ -106,7 +171,7 @@ namespace cv |
|
|
|
|
split(dst, mv); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < mv.size(); ++i) |
|
|
|
|
grayDctDenoising(mv[0], mv[0], sigma, psize); |
|
|
|
|
grayDctDenoising(mv[i], mv[i], sigma, psize); |
|
|
|
|
|
|
|
|
|
merge(mv, dst); |
|
|
|
|
/*************************************/ |
|
|
|
@ -114,9 +179,9 @@ namespace cv |
|
|
|
|
for (Mat_<Vec3f>::iterator it = dst.begin(); it != dst.end(); ++it) |
|
|
|
|
{ |
|
|
|
|
Vec3f rgb = *it; |
|
|
|
|
*it = Vec3f(M[0]*rgb[0] + M[1]*rgb[1] + M[2]*rgb[2], |
|
|
|
|
M[3]*rgb[0] + M[4]*rgb[1] + M[5]*rgb[2], |
|
|
|
|
M[6]*rgb[0] + M[7]*rgb[1] + M[8]*rgb[2]); |
|
|
|
|
*it = Vec3f(M[0]*rgb[0] + M[3]*rgb[1] + M[6]*rgb[2], |
|
|
|
|
M[1]*rgb[0] + M[4]*rgb[1] + M[7]*rgb[2], |
|
|
|
|
M[2]*rgb[0] + M[5]*rgb[1] + M[8]*rgb[2]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|