dct_image_denoising.cpp 6.54 KB
Newer Older
Bellaktris's avatar
Bellaktris committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

#include "opencv2/xphoto.hpp"

#include "opencv2/imgproc.hpp"

#include "opencv2/core.hpp"
#include "opencv2/core/core_c.h"

#include "opencv2/core/types.hpp"
#include "opencv2/core/types_c.h"

namespace cv
{
57 58 59
namespace xphoto
{

Bellaktris's avatar
Bellaktris committed
60 61 62 63 64
    void grayDctDenoising(const Mat &, Mat &, const double, const int);
    void rgbDctDenoising(const Mat &, Mat &, const double, const int);
    void dctDenoising(const Mat &, Mat &, const double, const int);


65 66 67
    struct grayDctDenoisingInvoker : public ParallelLoopBody
    {
    public:
68
        grayDctDenoisingInvoker(const Mat &src, std::vector <Mat> &patches, const double sigma, const int psize);
Bellaktris's avatar
Bellaktris committed
69
        ~grayDctDenoisingInvoker(){};
70

71
        void operator() (const Range &range) const CV_OVERRIDE;
72

73
    protected:
74 75
        const Mat &src;
        std::vector <Mat> &patches; // image decomposition into sliding patches
76 77 78 79

        const int psize; // size of block to compute dct
        const double sigma; // expected noise standard deviation
        const double thresh; // thresholding estimate
Bellaktris's avatar
Bellaktris committed
80 81

        void operator =(const grayDctDenoisingInvoker&) const {};
82 83
    };

Bellaktris's avatar
Bellaktris committed
84 85
    grayDctDenoisingInvoker::grayDctDenoisingInvoker(const Mat &_src, std::vector <Mat> &_patches,
                                                     const double _sigma, const int _psize)
Bellaktris's avatar
Bellaktris committed
86
        : src(_src), patches(_patches), psize(_psize), sigma(_sigma), thresh(3*_sigma) {}
87 88 89 90 91 92 93 94 95 96

    void grayDctDenoisingInvoker::operator() (const Range &range) const
    {
        for (int i = range.start; i <= range.end - 1; ++i)
        {
            int y = i / (src.cols - psize);
            int x = i % (src.cols - psize);

            Rect patchNum( x, y, psize, psize );

97
            Mat patch(psize, psize, CV_32FC1);
98 99 100 101 102 103 104 105 106 107
            src(patchNum).copyTo( patch );

            dct(patch, patch);
            float *data = (float *) patch.data;
            for (int k = 0; k < psize*psize; ++k)
                data[k] *= fabs(data[k]) > thresh;
            idct(patch, patches[i]);
        }
    }

108
    void grayDctDenoising(const Mat &src, Mat &dst, const double sigma, const int psize)
Bellaktris's avatar
Bellaktris committed
109
    {
110
        CV_Assert( src.type() == CV_MAKE_TYPE(CV_32F, 1) );
111 112 113

        int npixels = (src.rows - psize)*(src.cols - psize);

114
        std::vector <Mat> patches;
115
        for (int i = 0; i < npixels; ++i)
116
            patches.push_back( Mat(psize, psize, CV_32FC1) );
117 118 119
        parallel_for_( cv::Range(0, npixels),
            grayDctDenoisingInvoker(src, patches, sigma, psize) );

120 121
        Mat res( src.size(), CV_32FC1, 0.0f ),
            num( src.size(), CV_32FC1, 0.0f );
Bellaktris's avatar
Bellaktris committed
122

123 124 125 126
        for (int k = 0; k < npixels; ++k)
        {
            int i = k / (src.cols - psize);
            int j = k % (src.cols - psize);
Bellaktris's avatar
Bellaktris committed
127

128
            res( Rect(j, i, psize, psize) ) += patches[k];
129
            num( Rect(j, i, psize, psize) ) += Mat::ones(psize, psize, CV_32FC1);
130
        }
Bellaktris's avatar
Bellaktris committed
131 132 133 134 135
        res /= num;

        res.convertTo( dst, src.type() );
    }

136
    void rgbDctDenoising(const Mat &src, Mat &dst, const double sigma, const int psize)
Bellaktris's avatar
Bellaktris committed
137
    {
138
        CV_Assert( src.type() == CV_MAKE_TYPE(CV_32F, 3) );
Bellaktris's avatar
Bellaktris committed
139

140 141 142
        cv::Matx33f mt(cvInvSqrt(3.0f),  cvInvSqrt(3.0f),       cvInvSqrt(3.0f),
                       cvInvSqrt(2.0f),  0.0f,                 -cvInvSqrt(2.0f),
                       cvInvSqrt(6.0f), -2.0f*cvInvSqrt(6.0f),  cvInvSqrt(6.0f));
Bellaktris's avatar
Bellaktris committed
143

Bellaktris's avatar
Bellaktris committed
144
        cv::transform(src, dst, mt);
Bellaktris's avatar
Bellaktris committed
145

146
        std::vector <Mat> mv;
Bellaktris's avatar
Bellaktris committed
147 148
        split(dst, mv);

Bellaktris's avatar
Bellaktris committed
149
        for (size_t i = 0; i < mv.size(); ++i)
150
            grayDctDenoising(mv[i], mv[i], sigma, psize);
Bellaktris's avatar
Bellaktris committed
151 152 153

        merge(mv, dst);

Bellaktris's avatar
Bellaktris committed
154
        cv::transform( dst, dst, mt.inv() );
Bellaktris's avatar
Bellaktris committed
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
    }

    /*! This function implements simple dct-based image denoising,
	 *	link: http://www.ipol.im/pub/art/2011/ys-dct/
     *
	 *  \param src : source image (rgb, or gray)
     *  \param dst : destination image
     *  \param sigma : expected noise standard deviation
     *  \param psize : size of block side where dct is computed
     */
    void dctDenoising(const Mat &src, Mat &dst, const double sigma, const int psize)
    {
        CV_Assert( src.channels() == 3 || src.channels() == 1 );

        int xtype = CV_MAKE_TYPE( CV_32F, src.channels() );
        Mat img( src.size(), xtype );
        src.convertTo(img, xtype);

        if ( img.type() == CV_32FC3 )
174
            rgbDctDenoising( img, img, sigma, psize );
Bellaktris's avatar
Bellaktris committed
175
        else if ( img.type() == CV_32FC1 )
176
            grayDctDenoising( img, img, sigma, psize );
Bellaktris's avatar
Bellaktris committed
177
        else
178 179
            CV_Error_( CV_StsNotImplemented,
            ("Unsupported source image format (=%d)", img.type()) );
Bellaktris's avatar
Bellaktris committed
180 181 182 183

        img.convertTo( dst, src.type() );
    }

Bellaktris's avatar
Bellaktris committed
184
}
185
}