// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. #ifndef OPENCV_QUALITY_QUALITYPSNR_HPP #define OPENCV_QUALITY_QUALITYPSNR_HPP #include // numeric_limits #include "qualitybase.hpp" #include "qualitymse.hpp" namespace cv { namespace quality { /** @brief Full reference peak signal to noise ratio (PSNR) algorithm https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio */ class CV_EXPORTS_W QualityPSNR : public QualityBase { public: /** @brief Default maximum pixel value */ #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900/*MSVS 2015*/) static constexpr double MAX_PIXEL_VALUE_DEFAULT = 255.; #else // support MSVS 2013 static const int MAX_PIXEL_VALUE_DEFAULT = 255; #endif /** @brief Create an object which calculates quality @param ref input image to use as the source for comparison @param maxPixelValue maximum per-channel value for any individual pixel; eg 255 for uint8 image */ CV_WRAP static Ptr create( InputArray ref, double maxPixelValue = QualityPSNR::MAX_PIXEL_VALUE_DEFAULT ) { return Ptr(new QualityPSNR(QualityMSE::create(ref), maxPixelValue)); } /** @brief Compute the PSNR @param cmp Comparison image @returns Per-channel PSNR value, or std::numeric_limits::infinity() if the MSE between the two images == 0 */ CV_WRAP cv::Scalar compute( InputArray cmp ) CV_OVERRIDE { auto result = _qualityMSE->compute( cmp ); _qualityMSE->getQualityMap(_qualityMap); // copy from internal obj to this obj return _mse_to_psnr( result , _maxPixelValue ); } /** @brief Implements Algorithm::empty() */ CV_WRAP bool empty() const CV_OVERRIDE { return _qualityMSE->empty() && QualityBase::empty(); } /** @brief Implements Algorithm::clear() */ CV_WRAP void clear() CV_OVERRIDE { _qualityMSE->clear(); QualityBase::clear(); } /** @brief static method for computing quality @param ref reference image @param cmp comparison image @param qualityMap output quality map, or cv::noArray() @param maxPixelValue maximum per-channel value for any individual pixel; eg 255 for uint8 image @returns PSNR value, or std::numeric_limits::infinity() if the MSE between the two images == 0 */ CV_WRAP static cv::Scalar compute( InputArray ref, InputArray cmp, OutputArray qualityMap, double maxPixelValue = QualityPSNR::MAX_PIXEL_VALUE_DEFAULT) { return _mse_to_psnr( QualityMSE::compute(ref, cmp, qualityMap) , maxPixelValue ); } /** @brief return the maximum pixel value used for PSNR computation */ CV_WRAP double getMaxPixelValue() const { return _maxPixelValue; } /** @brief sets the maximum pixel value used for PSNR computation @param val Maximum pixel value */ CV_WRAP void setMaxPixelValue(double val) { this->_maxPixelValue = val; } protected: Ptr _qualityMSE; double _maxPixelValue = QualityPSNR::MAX_PIXEL_VALUE_DEFAULT; /** @brief Constructor */ QualityPSNR( Ptr qualityMSE, double maxPixelValue ) : _qualityMSE(std::move(qualityMSE)) , _maxPixelValue(maxPixelValue) {} // convert mse to psnr static double _mse_to_psnr(double mse, double max_pixel_value) { return (mse == 0.) ? std::numeric_limits::infinity() : 10. * std::log10((max_pixel_value * max_pixel_value) / mse) ; } // convert scalar of mses to psnrs static cv::Scalar _mse_to_psnr(cv::Scalar mse, double max_pixel_value) { for (int i = 0; i < mse.rows; ++i) mse(i) = _mse_to_psnr(mse(i), max_pixel_value); return mse; } }; // QualityPSNR } // quality } // cv #endif