feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake
1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试 2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程 3.重整权利声明文件,重整代码工程,确保最小化侵权风险 Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
7
3rdparty/opencv-4.5.4/modules/photo/CMakeLists.txt
vendored
Normal file
7
3rdparty/opencv-4.5.4/modules/photo/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
set(the_description "Computational Photography")
|
||||
|
||||
if(HAVE_CUDA)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations -Wshadow)
|
||||
endif()
|
||||
|
||||
ocv_define_module(photo opencv_imgproc OPTIONAL opencv_cudaarithm opencv_cudaimgproc WRAP java objc python js)
|
||||
858
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo.hpp
vendored
Normal file
858
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo.hpp
vendored
Normal file
@ -0,0 +1,858 @@
|
||||
/*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) 2008-2012, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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*/
|
||||
|
||||
#ifndef OPENCV_PHOTO_HPP
|
||||
#define OPENCV_PHOTO_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
/**
|
||||
@defgroup photo Computational Photography
|
||||
|
||||
This module includes photo processing algorithms
|
||||
@{
|
||||
@defgroup photo_inpaint Inpainting
|
||||
@defgroup photo_denoise Denoising
|
||||
@defgroup photo_hdr HDR imaging
|
||||
|
||||
This section describes high dynamic range imaging algorithms namely tonemapping, exposure alignment,
|
||||
camera calibration with multiple exposures and exposure fusion.
|
||||
|
||||
@defgroup photo_decolor Contrast Preserving Decolorization
|
||||
|
||||
Useful links:
|
||||
|
||||
http://www.cse.cuhk.edu.hk/leojia/projects/color2gray/index.html
|
||||
|
||||
@defgroup photo_clone Seamless Cloning
|
||||
|
||||
Useful links:
|
||||
|
||||
https://www.learnopencv.com/seamless-cloning-using-opencv-python-cpp
|
||||
|
||||
@defgroup photo_render Non-Photorealistic Rendering
|
||||
|
||||
Useful links:
|
||||
|
||||
http://www.inf.ufrgs.br/~eslgastal/DomainTransform
|
||||
|
||||
https://www.learnopencv.com/non-photorealistic-rendering-using-opencv-python-c/
|
||||
|
||||
@defgroup photo_c C API
|
||||
@}
|
||||
*/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup photo
|
||||
//! @{
|
||||
|
||||
//! @addtogroup photo_inpaint
|
||||
//! @{
|
||||
//! the inpainting algorithm
|
||||
enum
|
||||
{
|
||||
INPAINT_NS = 0, //!< Use Navier-Stokes based method
|
||||
INPAINT_TELEA = 1 //!< Use the algorithm proposed by Alexandru Telea @cite Telea04
|
||||
};
|
||||
|
||||
/** @brief Restores the selected region in an image using the region neighborhood.
|
||||
|
||||
@param src Input 8-bit, 16-bit unsigned or 32-bit float 1-channel or 8-bit 3-channel image.
|
||||
@param inpaintMask Inpainting mask, 8-bit 1-channel image. Non-zero pixels indicate the area that
|
||||
needs to be inpainted.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param inpaintRadius Radius of a circular neighborhood of each point inpainted that is considered
|
||||
by the algorithm.
|
||||
@param flags Inpainting method that could be cv::INPAINT_NS or cv::INPAINT_TELEA
|
||||
|
||||
The function reconstructs the selected image area from the pixel near the area boundary. The
|
||||
function may be used to remove dust and scratches from a scanned photo, or to remove undesirable
|
||||
objects from still images or video. See <http://en.wikipedia.org/wiki/Inpainting> for more details.
|
||||
|
||||
@note
|
||||
- An example using the inpainting technique can be found at
|
||||
opencv_source_code/samples/cpp/inpaint.cpp
|
||||
- (Python) An example using the inpainting technique can be found at
|
||||
opencv_source_code/samples/python/inpaint.py
|
||||
*/
|
||||
CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask,
|
||||
OutputArray dst, double inpaintRadius, int flags );
|
||||
|
||||
//! @} photo_inpaint
|
||||
|
||||
//! @addtogroup photo_denoise
|
||||
//! @{
|
||||
|
||||
/** @brief Perform image denoising using Non-local Means Denoising algorithm
|
||||
<http://www.ipol.im/pub/algo/bcm_non_local_means_denoising/> with several computational
|
||||
optimizations. Noise expected to be a gaussian white noise
|
||||
|
||||
@param src Input 8-bit 1-channel, 2-channel, 3-channel or 4-channel image.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
|
||||
Should be odd. Recommended value 7 pixels
|
||||
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param h Parameter regulating filter strength. Big h value perfectly removes noise but also
|
||||
removes image details, smaller h value preserves details but also preserves some noise
|
||||
|
||||
This function expected to be applied to grayscale images. For colored images look at
|
||||
fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored
|
||||
image in different colorspaces. Such approach is used in fastNlMeansDenoisingColored by converting
|
||||
image to CIELAB colorspace and then separately denoise L and AB components with different h
|
||||
parameter.
|
||||
*/
|
||||
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
/** @brief Perform image denoising using Non-local Means Denoising algorithm
|
||||
<http://www.ipol.im/pub/algo/bcm_non_local_means_denoising/> with several computational
|
||||
optimizations. Noise expected to be a gaussian white noise
|
||||
|
||||
@param src Input 8-bit or 16-bit (only with NORM_L1) 1-channel,
|
||||
2-channel, 3-channel or 4-channel image.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
|
||||
Should be odd. Recommended value 7 pixels
|
||||
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param h Array of parameters regulating filter strength, either one
|
||||
parameter applied to all channels or one per channel in dst. Big h value
|
||||
perfectly removes noise but also removes image details, smaller h
|
||||
value preserves details but also preserves some noise
|
||||
@param normType Type of norm used for weight calculation. Can be either NORM_L2 or NORM_L1
|
||||
|
||||
This function expected to be applied to grayscale images. For colored images look at
|
||||
fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored
|
||||
image in different colorspaces. Such approach is used in fastNlMeansDenoisingColored by converting
|
||||
image to CIELAB colorspace and then separately denoise L and AB components with different h
|
||||
parameter.
|
||||
*/
|
||||
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst,
|
||||
const std::vector<float>& h,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21,
|
||||
int normType = NORM_L2);
|
||||
|
||||
/** @brief Modification of fastNlMeansDenoising function for colored images
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
|
||||
Should be odd. Recommended value 7 pixels
|
||||
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param h Parameter regulating filter strength for luminance component. Bigger h value perfectly
|
||||
removes noise but also removes image details, smaller h value preserves details but also preserves
|
||||
some noise
|
||||
@param hColor The same as h but for color components. For most images value equals 10
|
||||
will be enough to remove colored noise and do not distort colors
|
||||
|
||||
The function converts image to CIELAB colorspace and then separately denoise L and AB components
|
||||
with given h parameters using fastNlMeansDenoising function.
|
||||
*/
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst,
|
||||
float h = 3, float hColor = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
/** @brief Modification of fastNlMeansDenoising function for images sequence where consecutive images have been
|
||||
captured in small period of time. For example video. This version of the function is for grayscale
|
||||
images or for manual manipulation with colorspaces. For more details see
|
||||
<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.131.6394>
|
||||
|
||||
@param srcImgs Input 8-bit 1-channel, 2-channel, 3-channel or
|
||||
4-channel images sequence. All images should have the same type and
|
||||
size.
|
||||
@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence
|
||||
@param temporalWindowSize Number of surrounding images to use for target image denoising. Should
|
||||
be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to
|
||||
imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise
|
||||
srcImgs[imgToDenoiseIndex] image.
|
||||
@param dst Output image with the same size and type as srcImgs images.
|
||||
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
|
||||
Should be odd. Recommended value 7 pixels
|
||||
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param h Parameter regulating filter strength. Bigger h value
|
||||
perfectly removes noise but also removes image details, smaller h
|
||||
value preserves details but also preserves some noise
|
||||
*/
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
/** @brief Modification of fastNlMeansDenoising function for images sequence where consecutive images have been
|
||||
captured in small period of time. For example video. This version of the function is for grayscale
|
||||
images or for manual manipulation with colorspaces. For more details see
|
||||
<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.131.6394>
|
||||
|
||||
@param srcImgs Input 8-bit or 16-bit (only with NORM_L1) 1-channel,
|
||||
2-channel, 3-channel or 4-channel images sequence. All images should
|
||||
have the same type and size.
|
||||
@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence
|
||||
@param temporalWindowSize Number of surrounding images to use for target image denoising. Should
|
||||
be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to
|
||||
imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise
|
||||
srcImgs[imgToDenoiseIndex] image.
|
||||
@param dst Output image with the same size and type as srcImgs images.
|
||||
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
|
||||
Should be odd. Recommended value 7 pixels
|
||||
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param h Array of parameters regulating filter strength, either one
|
||||
parameter applied to all channels or one per channel in dst. Big h value
|
||||
perfectly removes noise but also removes image details, smaller h
|
||||
value preserves details but also preserves some noise
|
||||
@param normType Type of norm used for weight calculation. Can be either NORM_L2 or NORM_L1
|
||||
*/
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
const std::vector<float>& h,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21,
|
||||
int normType = NORM_L2);
|
||||
|
||||
/** @brief Modification of fastNlMeansDenoisingMulti function for colored images sequences
|
||||
|
||||
@param srcImgs Input 8-bit 3-channel images sequence. All images should have the same type and
|
||||
size.
|
||||
@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence
|
||||
@param temporalWindowSize Number of surrounding images to use for target image denoising. Should
|
||||
be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to
|
||||
imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise
|
||||
srcImgs[imgToDenoiseIndex] image.
|
||||
@param dst Output image with the same size and type as srcImgs images.
|
||||
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
|
||||
Should be odd. Recommended value 7 pixels
|
||||
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param h Parameter regulating filter strength for luminance component. Bigger h value perfectly
|
||||
removes noise but also removes image details, smaller h value preserves details but also preserves
|
||||
some noise.
|
||||
@param hColor The same as h but for color components.
|
||||
|
||||
The function converts images to CIELAB colorspace and then separately denoise L and AB components
|
||||
with given h parameters using fastNlMeansDenoisingMulti function.
|
||||
*/
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h = 3, float hColor = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
/** @brief Primal-dual algorithm is an algorithm for solving special types of variational problems (that is,
|
||||
finding a function to minimize some functional). As the image denoising, in particular, may be seen
|
||||
as the variational problem, primal-dual algorithm then can be used to perform denoising and this is
|
||||
exactly what is implemented.
|
||||
|
||||
It should be noted, that this implementation was taken from the July 2013 blog entry
|
||||
@cite MA13 , which also contained (slightly more general) ready-to-use source code on Python.
|
||||
Subsequently, that code was rewritten on C++ with the usage of openCV by Vadim Pisarevsky at the end
|
||||
of July 2013 and finally it was slightly adapted by later authors.
|
||||
|
||||
Although the thorough discussion and justification of the algorithm involved may be found in
|
||||
@cite ChambolleEtAl, it might make sense to skim over it here, following @cite MA13 . To begin
|
||||
with, we consider the 1-byte gray-level images as the functions from the rectangular domain of
|
||||
pixels (it may be seen as set
|
||||
\f$\left\{(x,y)\in\mathbb{N}\times\mathbb{N}\mid 1\leq x\leq n,\;1\leq y\leq m\right\}\f$ for some
|
||||
\f$m,\;n\in\mathbb{N}\f$) into \f$\{0,1,\dots,255\}\f$. We shall denote the noised images as \f$f_i\f$ and with
|
||||
this view, given some image \f$x\f$ of the same size, we may measure how bad it is by the formula
|
||||
|
||||
\f[\left\|\left\|\nabla x\right\|\right\| + \lambda\sum_i\left\|\left\|x-f_i\right\|\right\|\f]
|
||||
|
||||
\f$\|\|\cdot\|\|\f$ here denotes \f$L_2\f$-norm and as you see, the first addend states that we want our
|
||||
image to be smooth (ideally, having zero gradient, thus being constant) and the second states that
|
||||
we want our result to be close to the observations we've got. If we treat \f$x\f$ as a function, this is
|
||||
exactly the functional what we seek to minimize and here the Primal-Dual algorithm comes into play.
|
||||
|
||||
@param observations This array should contain one or more noised versions of the image that is to
|
||||
be restored.
|
||||
@param result Here the denoised image will be stored. There is no need to do pre-allocation of
|
||||
storage space, as it will be automatically allocated, if necessary.
|
||||
@param lambda Corresponds to \f$\lambda\f$ in the formulas above. As it is enlarged, the smooth
|
||||
(blurred) images are treated more favorably than detailed (but maybe more noised) ones. Roughly
|
||||
speaking, as it becomes smaller, the result will be more blur but more sever outliers will be
|
||||
removed.
|
||||
@param niters Number of iterations that the algorithm will run. Of course, as more iterations as
|
||||
better, but it is hard to quantitatively refine this statement, so just use the default and
|
||||
increase it if the results are poor.
|
||||
*/
|
||||
CV_EXPORTS_W void denoise_TVL1(const std::vector<Mat>& observations,Mat& result, double lambda=1.0, int niters=30);
|
||||
|
||||
//! @} photo_denoise
|
||||
|
||||
//! @addtogroup photo_hdr
|
||||
//! @{
|
||||
|
||||
enum { LDR_SIZE = 256 };
|
||||
|
||||
/** @brief Base class for tonemapping algorithms - tools that are used to map HDR image to 8-bit range.
|
||||
*/
|
||||
class CV_EXPORTS_W Tonemap : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Tonemaps image
|
||||
|
||||
@param src source image - CV_32FC3 Mat (float 32 bits 3 channels)
|
||||
@param dst destination image - CV_32FC3 Mat with values in [0, 1] range
|
||||
*/
|
||||
CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0;
|
||||
|
||||
CV_WRAP virtual float getGamma() const = 0;
|
||||
CV_WRAP virtual void setGamma(float gamma) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates simple linear mapper with gamma correction
|
||||
|
||||
@param gamma positive value for gamma correction. Gamma value of 1.0 implies no correction, gamma
|
||||
equal to 2.2f is suitable for most displays.
|
||||
Generally gamma \> 1 brightens the image and gamma \< 1 darkens it.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<Tonemap> createTonemap(float gamma = 1.0f);
|
||||
|
||||
/** @brief Adaptive logarithmic mapping is a fast global tonemapping algorithm that scales the image in
|
||||
logarithmic domain.
|
||||
|
||||
Since it's a global operator the same function is applied to all the pixels, it is controlled by the
|
||||
bias parameter.
|
||||
|
||||
Optional saturation enhancement is possible as described in @cite FL02 .
|
||||
|
||||
For more information see @cite DM03 .
|
||||
*/
|
||||
class CV_EXPORTS_W TonemapDrago : public Tonemap
|
||||
{
|
||||
public:
|
||||
|
||||
CV_WRAP virtual float getSaturation() const = 0;
|
||||
CV_WRAP virtual void setSaturation(float saturation) = 0;
|
||||
|
||||
CV_WRAP virtual float getBias() const = 0;
|
||||
CV_WRAP virtual void setBias(float bias) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates TonemapDrago object
|
||||
|
||||
@param gamma gamma value for gamma correction. See createTonemap
|
||||
@param saturation positive saturation enhancement value. 1.0 preserves saturation, values greater
|
||||
than 1 increase saturation and values less than 1 decrease it.
|
||||
@param bias value for bias function in [0, 1] range. Values from 0.7 to 0.9 usually give best
|
||||
results, default value is 0.85.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<TonemapDrago> createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f);
|
||||
|
||||
|
||||
/** @brief This is a global tonemapping operator that models human visual system.
|
||||
|
||||
Mapping function is controlled by adaptation parameter, that is computed using light adaptation and
|
||||
color adaptation.
|
||||
|
||||
For more information see @cite RD05 .
|
||||
*/
|
||||
class CV_EXPORTS_W TonemapReinhard : public Tonemap
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual float getIntensity() const = 0;
|
||||
CV_WRAP virtual void setIntensity(float intensity) = 0;
|
||||
|
||||
CV_WRAP virtual float getLightAdaptation() const = 0;
|
||||
CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0;
|
||||
|
||||
CV_WRAP virtual float getColorAdaptation() const = 0;
|
||||
CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates TonemapReinhard object
|
||||
|
||||
@param gamma gamma value for gamma correction. See createTonemap
|
||||
@param intensity result intensity in [-8, 8] range. Greater intensity produces brighter results.
|
||||
@param light_adapt light adaptation in [0, 1] range. If 1 adaptation is based only on pixel
|
||||
value, if 0 it's global, otherwise it's a weighted mean of this two cases.
|
||||
@param color_adapt chromatic adaptation in [0, 1] range. If 1 channels are treated independently,
|
||||
if 0 adaptation level is the same for each channel.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<TonemapReinhard>
|
||||
createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f);
|
||||
|
||||
/** @brief This algorithm transforms image to contrast using gradients on all levels of gaussian pyramid,
|
||||
transforms contrast values to HVS response and scales the response. After this the image is
|
||||
reconstructed from new contrast values.
|
||||
|
||||
For more information see @cite MM06 .
|
||||
*/
|
||||
class CV_EXPORTS_W TonemapMantiuk : public Tonemap
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual float getScale() const = 0;
|
||||
CV_WRAP virtual void setScale(float scale) = 0;
|
||||
|
||||
CV_WRAP virtual float getSaturation() const = 0;
|
||||
CV_WRAP virtual void setSaturation(float saturation) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates TonemapMantiuk object
|
||||
|
||||
@param gamma gamma value for gamma correction. See createTonemap
|
||||
@param scale contrast scale factor. HVS response is multiplied by this parameter, thus compressing
|
||||
dynamic range. Values from 0.6 to 0.9 produce best results.
|
||||
@param saturation saturation enhancement value. See createTonemapDrago
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<TonemapMantiuk>
|
||||
createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f);
|
||||
|
||||
/** @brief The base class for algorithms that align images of the same scene with different exposures
|
||||
*/
|
||||
class CV_EXPORTS_W AlignExposures : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Aligns images
|
||||
|
||||
@param src vector of input images
|
||||
@param dst vector of aligned images
|
||||
@param times vector of exposure time values for each image
|
||||
@param response 256x1 matrix with inverse camera response function for each pixel value, it should
|
||||
have the same number of channels as images.
|
||||
*/
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, std::vector<Mat>& dst,
|
||||
InputArray times, InputArray response) = 0;
|
||||
};
|
||||
|
||||
/** @brief This algorithm converts images to median threshold bitmaps (1 for pixels brighter than median
|
||||
luminance and 0 otherwise) and than aligns the resulting bitmaps using bit operations.
|
||||
|
||||
It is invariant to exposure, so exposure values and camera response are not necessary.
|
||||
|
||||
In this implementation new image regions are filled with zeros.
|
||||
|
||||
For more information see @cite GW03 .
|
||||
*/
|
||||
class CV_EXPORTS_W AlignMTB : public AlignExposures
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, std::vector<Mat>& dst,
|
||||
InputArray times, InputArray response) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Short version of process, that doesn't take extra arguments.
|
||||
|
||||
@param src vector of input images
|
||||
@param dst vector of aligned images
|
||||
*/
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, std::vector<Mat>& dst) = 0;
|
||||
|
||||
/** @brief Calculates shift between two images, i. e. how to shift the second image to correspond it with the
|
||||
first.
|
||||
|
||||
@param img0 first image
|
||||
@param img1 second image
|
||||
*/
|
||||
CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0;
|
||||
/** @brief Helper function, that shift Mat filling new regions with zeros.
|
||||
|
||||
@param src input image
|
||||
@param dst result image
|
||||
@param shift shift value
|
||||
*/
|
||||
CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0;
|
||||
/** @brief Computes median threshold and exclude bitmaps of given image.
|
||||
|
||||
@param img input image
|
||||
@param tb median threshold bitmap
|
||||
@param eb exclude bitmap
|
||||
*/
|
||||
CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0;
|
||||
|
||||
CV_WRAP virtual int getMaxBits() const = 0;
|
||||
CV_WRAP virtual void setMaxBits(int max_bits) = 0;
|
||||
|
||||
CV_WRAP virtual int getExcludeRange() const = 0;
|
||||
CV_WRAP virtual void setExcludeRange(int exclude_range) = 0;
|
||||
|
||||
CV_WRAP virtual bool getCut() const = 0;
|
||||
CV_WRAP virtual void setCut(bool value) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates AlignMTB object
|
||||
|
||||
@param max_bits logarithm to the base 2 of maximal shift in each dimension. Values of 5 and 6 are
|
||||
usually good enough (31 and 63 pixels shift respectively).
|
||||
@param exclude_range range for exclusion bitmap that is constructed to suppress noise around the
|
||||
median value.
|
||||
@param cut if true cuts images, otherwise fills the new regions with zeros.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<AlignMTB> createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true);
|
||||
|
||||
/** @brief The base class for camera response calibration algorithms.
|
||||
*/
|
||||
class CV_EXPORTS_W CalibrateCRF : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Recovers inverse camera response.
|
||||
|
||||
@param src vector of input images
|
||||
@param dst 256x1 matrix with inverse camera response function
|
||||
@param times vector of exposure time values for each image
|
||||
*/
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0;
|
||||
};
|
||||
|
||||
/** @brief Inverse camera response function is extracted for each brightness value by minimizing an objective
|
||||
function as linear system. Objective function is constructed using pixel values on the same position
|
||||
in all images, extra term is added to make the result smoother.
|
||||
|
||||
For more information see @cite DM97 .
|
||||
*/
|
||||
class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual float getLambda() const = 0;
|
||||
CV_WRAP virtual void setLambda(float lambda) = 0;
|
||||
|
||||
CV_WRAP virtual int getSamples() const = 0;
|
||||
CV_WRAP virtual void setSamples(int samples) = 0;
|
||||
|
||||
CV_WRAP virtual bool getRandom() const = 0;
|
||||
CV_WRAP virtual void setRandom(bool random) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates CalibrateDebevec object
|
||||
|
||||
@param samples number of pixel locations to use
|
||||
@param lambda smoothness term weight. Greater values produce smoother results, but can alter the
|
||||
response.
|
||||
@param random if true sample pixel locations are chosen at random, otherwise they form a
|
||||
rectangular grid.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<CalibrateDebevec> createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false);
|
||||
|
||||
/** @brief Inverse camera response function is extracted for each brightness value by minimizing an objective
|
||||
function as linear system. This algorithm uses all image pixels.
|
||||
|
||||
For more information see @cite RB99 .
|
||||
*/
|
||||
class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual int getMaxIter() const = 0;
|
||||
CV_WRAP virtual void setMaxIter(int max_iter) = 0;
|
||||
|
||||
CV_WRAP virtual float getThreshold() const = 0;
|
||||
CV_WRAP virtual void setThreshold(float threshold) = 0;
|
||||
|
||||
CV_WRAP virtual Mat getRadiance() const = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates CalibrateRobertson object
|
||||
|
||||
@param max_iter maximal number of Gauss-Seidel solver iterations.
|
||||
@param threshold target difference between results of two successive steps of the minimization.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<CalibrateRobertson> createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f);
|
||||
|
||||
/** @brief The base class algorithms that can merge exposure sequence to a single image.
|
||||
*/
|
||||
class CV_EXPORTS_W MergeExposures : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Merges images.
|
||||
|
||||
@param src vector of input images
|
||||
@param dst result image
|
||||
@param times vector of exposure time values for each image
|
||||
@param response 256x1 matrix with inverse camera response function for each pixel value, it should
|
||||
have the same number of channels as images.
|
||||
*/
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst,
|
||||
InputArray times, InputArray response) = 0;
|
||||
};
|
||||
|
||||
/** @brief The resulting HDR image is calculated as weighted average of the exposures considering exposure
|
||||
values and camera response.
|
||||
|
||||
For more information see @cite DM97 .
|
||||
*/
|
||||
class CV_EXPORTS_W MergeDebevec : public MergeExposures
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst,
|
||||
InputArray times, InputArray response) CV_OVERRIDE = 0;
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates MergeDebevec object
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<MergeDebevec> createMergeDebevec();
|
||||
|
||||
/** @brief Pixels are weighted using contrast, saturation and well-exposedness measures, than images are
|
||||
combined using laplacian pyramids.
|
||||
|
||||
The resulting image weight is constructed as weighted average of contrast, saturation and
|
||||
well-exposedness measures.
|
||||
|
||||
The resulting image doesn't require tonemapping and can be converted to 8-bit image by multiplying
|
||||
by 255, but it's recommended to apply gamma correction and/or linear tonemapping.
|
||||
|
||||
For more information see @cite MK07 .
|
||||
*/
|
||||
class CV_EXPORTS_W MergeMertens : public MergeExposures
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst,
|
||||
InputArray times, InputArray response) CV_OVERRIDE = 0;
|
||||
/** @brief Short version of process, that doesn't take extra arguments.
|
||||
|
||||
@param src vector of input images
|
||||
@param dst result image
|
||||
*/
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0;
|
||||
|
||||
CV_WRAP virtual float getContrastWeight() const = 0;
|
||||
CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0;
|
||||
|
||||
CV_WRAP virtual float getSaturationWeight() const = 0;
|
||||
CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0;
|
||||
|
||||
CV_WRAP virtual float getExposureWeight() const = 0;
|
||||
CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates MergeMertens object
|
||||
|
||||
@param contrast_weight contrast measure weight. See MergeMertens.
|
||||
@param saturation_weight saturation measure weight
|
||||
@param exposure_weight well-exposedness measure weight
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<MergeMertens>
|
||||
createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f);
|
||||
|
||||
/** @brief The resulting HDR image is calculated as weighted average of the exposures considering exposure
|
||||
values and camera response.
|
||||
|
||||
For more information see @cite RB99 .
|
||||
*/
|
||||
class CV_EXPORTS_W MergeRobertson : public MergeExposures
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst,
|
||||
InputArray times, InputArray response) CV_OVERRIDE = 0;
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates MergeRobertson object
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<MergeRobertson> createMergeRobertson();
|
||||
|
||||
//! @} photo_hdr
|
||||
|
||||
//! @addtogroup photo_decolor
|
||||
//! @{
|
||||
|
||||
/** @brief Transforms a color image to a grayscale image. It is a basic tool in digital printing, stylized
|
||||
black-and-white photograph rendering, and in many single channel image processing applications
|
||||
@cite CL12 .
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param grayscale Output 8-bit 1-channel image.
|
||||
@param color_boost Output 8-bit 3-channel image.
|
||||
|
||||
This function is to be applied on color images.
|
||||
*/
|
||||
CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost);
|
||||
|
||||
//! @} photo_decolor
|
||||
|
||||
//! @addtogroup photo_clone
|
||||
//! @{
|
||||
|
||||
|
||||
//! seamlessClone algorithm flags
|
||||
enum
|
||||
{
|
||||
/** The power of the method is fully expressed when inserting objects with complex outlines into a new background*/
|
||||
NORMAL_CLONE = 1,
|
||||
/** The classic method, color-based selection and alpha masking might be time consuming and often leaves an undesirable
|
||||
halo. Seamless cloning, even averaged with the original image, is not effective. Mixed seamless cloning based on a loose selection proves effective.*/
|
||||
MIXED_CLONE = 2,
|
||||
/** Monochrome transfer allows the user to easily replace certain features of one object by alternative features.*/
|
||||
MONOCHROME_TRANSFER = 3};
|
||||
|
||||
|
||||
/** @example samples/cpp/tutorial_code/photo/seamless_cloning/cloning_demo.cpp
|
||||
An example using seamlessClone function
|
||||
*/
|
||||
/** @brief Image editing tasks concern either global changes (color/intensity corrections, filters,
|
||||
deformations) or local changes concerned to a selection. Here we are interested in achieving local
|
||||
changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless
|
||||
manner. The extent of the changes ranges from slight distortions to complete replacement by novel
|
||||
content @cite PM03 .
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst Input 8-bit 3-channel image.
|
||||
@param mask Input 8-bit 1 or 3-channel image.
|
||||
@param p Point in dst image where object is placed.
|
||||
@param blend Output image with the same size and type as dst.
|
||||
@param flags Cloning method that could be cv::NORMAL_CLONE, cv::MIXED_CLONE or cv::MONOCHROME_TRANSFER
|
||||
*/
|
||||
CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p,
|
||||
OutputArray blend, int flags);
|
||||
|
||||
/** @brief Given an original color image, two differently colored versions of this image can be mixed
|
||||
seamlessly.
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param mask Input 8-bit 1 or 3-channel image.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param red_mul R-channel multiply factor.
|
||||
@param green_mul G-channel multiply factor.
|
||||
@param blue_mul B-channel multiply factor.
|
||||
|
||||
Multiplication factor is between .5 to 2.5.
|
||||
*/
|
||||
CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0f,
|
||||
float green_mul = 1.0f, float blue_mul = 1.0f);
|
||||
|
||||
/** @brief Applying an appropriate non-linear transformation to the gradient field inside the selection and
|
||||
then integrating back with a Poisson solver, modifies locally the apparent illumination of an image.
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param mask Input 8-bit 1 or 3-channel image.
|
||||
@param dst Output image with the same size and type as src.
|
||||
@param alpha Value ranges between 0-2.
|
||||
@param beta Value ranges between 0-2.
|
||||
|
||||
This is useful to highlight under-exposed foreground objects or to reduce specular reflections.
|
||||
*/
|
||||
CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst,
|
||||
float alpha = 0.2f, float beta = 0.4f);
|
||||
|
||||
/** @brief By retaining only the gradients at edge locations, before integrating with the Poisson solver, one
|
||||
washes out the texture of the selected region, giving its contents a flat aspect. Here Canny Edge %Detector is used.
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param mask Input 8-bit 1 or 3-channel image.
|
||||
@param dst Output image with the same size and type as src.
|
||||
@param low_threshold %Range from 0 to 100.
|
||||
@param high_threshold Value \> 100.
|
||||
@param kernel_size The size of the Sobel kernel to be used.
|
||||
|
||||
@note
|
||||
The algorithm assumes that the color of the source image is close to that of the destination. This
|
||||
assumption means that when the colors don't match, the source image color gets tinted toward the
|
||||
color of the destination image.
|
||||
*/
|
||||
CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst,
|
||||
float low_threshold = 30, float high_threshold = 45,
|
||||
int kernel_size = 3);
|
||||
|
||||
//! @} photo_clone
|
||||
|
||||
//! @addtogroup photo_render
|
||||
//! @{
|
||||
|
||||
//! Edge preserving filters
|
||||
enum
|
||||
{
|
||||
RECURS_FILTER = 1, //!< Recursive Filtering
|
||||
NORMCONV_FILTER = 2 //!< Normalized Convolution Filtering
|
||||
};
|
||||
|
||||
/** @brief Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing
|
||||
filters are used in many different applications @cite EM11 .
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst Output 8-bit 3-channel image.
|
||||
@param flags Edge preserving filters: cv::RECURS_FILTER or cv::NORMCONV_FILTER
|
||||
@param sigma_s %Range between 0 to 200.
|
||||
@param sigma_r %Range between 0 to 1.
|
||||
*/
|
||||
CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1,
|
||||
float sigma_s = 60, float sigma_r = 0.4f);
|
||||
|
||||
/** @brief This filter enhances the details of a particular image.
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst Output image with the same size and type as src.
|
||||
@param sigma_s %Range between 0 to 200.
|
||||
@param sigma_r %Range between 0 to 1.
|
||||
*/
|
||||
CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10,
|
||||
float sigma_r = 0.15f);
|
||||
|
||||
/** @example samples/cpp/tutorial_code/photo/non_photorealistic_rendering/npr_demo.cpp
|
||||
An example using non-photorealistic line drawing functions
|
||||
*/
|
||||
/** @brief Pencil-like non-photorealistic line drawing
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst1 Output 8-bit 1-channel image.
|
||||
@param dst2 Output image with the same size and type as src.
|
||||
@param sigma_s %Range between 0 to 200.
|
||||
@param sigma_r %Range between 0 to 1.
|
||||
@param shade_factor %Range between 0 to 0.1.
|
||||
*/
|
||||
CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2,
|
||||
float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f);
|
||||
|
||||
/** @brief Stylization aims to produce digital imagery with a wide variety of effects not focused on
|
||||
photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low
|
||||
contrast while preserving, or enhancing, high-contrast features.
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst Output image with the same size and type as src.
|
||||
@param sigma_s %Range between 0 to 200.
|
||||
@param sigma_r %Range between 0 to 1.
|
||||
*/
|
||||
CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60,
|
||||
float sigma_r = 0.45f);
|
||||
|
||||
//! @} photo_render
|
||||
|
||||
//! @} photo
|
||||
|
||||
} // cv
|
||||
|
||||
#endif
|
||||
132
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo/cuda.hpp
vendored
Normal file
132
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo/cuda.hpp
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*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) 2008-2012, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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*/
|
||||
|
||||
#ifndef OPENCV_PHOTO_CUDA_HPP
|
||||
#define OPENCV_PHOTO_CUDA_HPP
|
||||
|
||||
#include "opencv2/core/cuda.hpp"
|
||||
|
||||
namespace cv { namespace cuda {
|
||||
|
||||
//! @addtogroup photo_denoise
|
||||
//! @{
|
||||
|
||||
/** @brief Performs pure non local means denoising without any simplification, and thus it is not fast.
|
||||
|
||||
@param src Source image. Supports only CV_8UC1, CV_8UC2 and CV_8UC3.
|
||||
@param dst Destination image.
|
||||
@param h Filter sigma regulating filter strength for color.
|
||||
@param search_window Size of search window.
|
||||
@param block_size Size of block used for computing weights.
|
||||
@param borderMode Border type. See borderInterpolate for details. BORDER_REFLECT101 ,
|
||||
BORDER_REPLICATE , BORDER_CONSTANT , BORDER_REFLECT and BORDER_WRAP are supported for now.
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa
|
||||
fastNlMeansDenoising
|
||||
*/
|
||||
CV_EXPORTS void nonLocalMeans(InputArray src, OutputArray dst,
|
||||
float h,
|
||||
int search_window = 21,
|
||||
int block_size = 7,
|
||||
int borderMode = BORDER_DEFAULT,
|
||||
Stream& stream = Stream::Null());
|
||||
|
||||
/** @brief Perform image denoising using Non-local Means Denoising algorithm
|
||||
<http://www.ipol.im/pub/algo/bcm_non_local_means_denoising> with several computational
|
||||
optimizations. Noise expected to be a gaussian white noise
|
||||
|
||||
@param src Input 8-bit 1-channel, 2-channel or 3-channel image.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param h Parameter regulating filter strength. Big h value perfectly removes noise but also
|
||||
removes image details, smaller h value preserves details but also preserves some noise
|
||||
@param search_window Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater search_window - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param block_size Size in pixels of the template patch that is used to compute weights. Should be
|
||||
odd. Recommended value 7 pixels
|
||||
@param stream Stream for the asynchronous invocations.
|
||||
|
||||
This function expected to be applied to grayscale images. For colored images look at
|
||||
FastNonLocalMeansDenoising::labMethod.
|
||||
|
||||
@sa
|
||||
fastNlMeansDenoising
|
||||
*/
|
||||
CV_EXPORTS void fastNlMeansDenoising(InputArray src, OutputArray dst,
|
||||
float h,
|
||||
int search_window = 21,
|
||||
int block_size = 7,
|
||||
Stream& stream = Stream::Null());
|
||||
|
||||
/** @brief Modification of fastNlMeansDenoising function for colored images
|
||||
|
||||
@param src Input 8-bit 3-channel image.
|
||||
@param dst Output image with the same size and type as src .
|
||||
@param h_luminance Parameter regulating filter strength. Big h value perfectly removes noise but
|
||||
also removes image details, smaller h value preserves details but also preserves some noise
|
||||
@param photo_render float The same as h but for color components. For most images value equals 10 will be
|
||||
enough to remove colored noise and do not distort colors
|
||||
@param search_window Size in pixels of the window that is used to compute weighted average for
|
||||
given pixel. Should be odd. Affect performance linearly: greater search_window - greater
|
||||
denoising time. Recommended value 21 pixels
|
||||
@param block_size Size in pixels of the template patch that is used to compute weights. Should be
|
||||
odd. Recommended value 7 pixels
|
||||
@param stream Stream for the asynchronous invocations.
|
||||
|
||||
The function converts image to CIELAB colorspace and then separately denoise L and AB components
|
||||
with given h parameters using FastNonLocalMeansDenoising::simpleMethod function.
|
||||
|
||||
@sa
|
||||
fastNlMeansDenoisingColored
|
||||
*/
|
||||
CV_EXPORTS void fastNlMeansDenoisingColored(InputArray src, OutputArray dst,
|
||||
float h_luminance, float photo_render,
|
||||
int search_window = 21,
|
||||
int block_size = 7,
|
||||
Stream& stream = Stream::Null());
|
||||
|
||||
//! @} photo
|
||||
|
||||
}} // namespace cv { namespace cuda {
|
||||
|
||||
#endif /* OPENCV_PHOTO_CUDA_HPP */
|
||||
14
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo/legacy/constants_c.h
vendored
Normal file
14
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo/legacy/constants_c.h
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// 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_PHOTO_LEGACY_CONSTANTS_H
|
||||
#define OPENCV_PHOTO_LEGACY_CONSTANTS_H
|
||||
|
||||
enum InpaintingModes
|
||||
{
|
||||
CV_INPAINT_NS =0,
|
||||
CV_INPAINT_TELEA =1
|
||||
};
|
||||
|
||||
#endif // OPENCV_PHOTO_LEGACY_CONSTANTS_H
|
||||
48
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo/photo.hpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/photo/include/opencv2/photo/photo.hpp
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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*/
|
||||
|
||||
#ifdef __OPENCV_BUILD
|
||||
#error this is a compatibility header which should not be used inside the OpenCV library
|
||||
#endif
|
||||
|
||||
#include "opencv2/photo.hpp"
|
||||
22
3rdparty/opencv-4.5.4/modules/photo/misc/java/test/PhotoTest.java
vendored
Normal file
22
3rdparty/opencv-4.5.4/modules/photo/misc/java/test/PhotoTest.java
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
package org.opencv.test.photo;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.photo.Photo;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
public class PhotoTest extends OpenCVTestCase {
|
||||
|
||||
public void testInpaint() {
|
||||
Point p = new Point(matSize / 2, matSize / 2);
|
||||
Imgproc.circle(gray255, p, 2, colorBlack, Imgproc.FILLED);
|
||||
Imgproc.circle(gray0, p, 2, colorWhite, Imgproc.FILLED);
|
||||
|
||||
Photo.inpaint(gray255, gray0, dst, 3, Photo.INPAINT_TELEA);
|
||||
|
||||
assertMatEqual(getMat(CvType.CV_8U, 255), dst);
|
||||
}
|
||||
|
||||
}
|
||||
8
3rdparty/opencv-4.5.4/modules/photo/misc/objc/gen_dict.json
vendored
Normal file
8
3rdparty/opencv-4.5.4/modules/photo/misc/objc/gen_dict.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"func_arg_fix" : {
|
||||
"Photo": {
|
||||
"(void)fastNlMeansDenoising:(Mat*)src dst:(Mat*)dst h:(FloatVector*)h templateWindowSize:(int)templateWindowSize searchWindowSize:(int)searchWindowSize normType:(int)normType" : { "h" : { "name" : "hVector" } },
|
||||
"(void)fastNlMeansDenoisingMulti:(NSArray<Mat*>*)srcImgs dst:(Mat*)dst imgToDenoiseIndex:(int)imgToDenoiseIndex temporalWindowSize:(int)temporalWindowSize h:(FloatVector*)h templateWindowSize:(int)templateWindowSize searchWindowSize:(int)searchWindowSize normType:(int)normType" : { "h" : { "name" : "hVector" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
97
3rdparty/opencv-4.5.4/modules/photo/perf/opencl/perf_denoising.cpp
vendored
Normal file
97
3rdparty/opencv-4.5.4/modules/photo/perf/opencl/perf_denoising.cpp
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
// 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.
|
||||
|
||||
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
OCL_PERF_TEST(Photo, DenoisingGrayscale)
|
||||
{
|
||||
Mat _original = imread(getDataPath("cv/denoising/lena_noised_gaussian_sigma=10.png"), IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(_original.empty()) << "Could not load input image";
|
||||
|
||||
UMat result(_original.size(), _original.type()), original;
|
||||
_original.copyTo(original);
|
||||
|
||||
declare.in(original).out(result).iterations(10);
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
cv::fastNlMeansDenoising(original, result, 10);
|
||||
|
||||
SANITY_CHECK(result, 1);
|
||||
}
|
||||
|
||||
OCL_PERF_TEST(Photo, DenoisingColored)
|
||||
{
|
||||
Mat _original = imread(getDataPath("cv/denoising/lena_noised_gaussian_sigma=10.png"));
|
||||
ASSERT_FALSE(_original.empty()) << "Could not load input image";
|
||||
|
||||
UMat result(_original.size(), _original.type()), original;
|
||||
_original.copyTo(original);
|
||||
|
||||
declare.in(original).out(result).iterations(10);
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
cv::fastNlMeansDenoisingColored(original, result, 10, 10);
|
||||
|
||||
SANITY_CHECK(result, 2);
|
||||
}
|
||||
|
||||
OCL_PERF_TEST(Photo, DISABLED_DenoisingGrayscaleMulti)
|
||||
{
|
||||
const int imgs_count = 3;
|
||||
|
||||
vector<UMat> original(imgs_count);
|
||||
Mat tmp;
|
||||
for (int i = 0; i < imgs_count; i++)
|
||||
{
|
||||
string original_path = format("cv/denoising/lena_noised_gaussian_sigma=20_multi_%d.png", i);
|
||||
tmp = imread(getDataPath(original_path), IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(tmp.empty()) << "Could not load input image " << original_path;
|
||||
tmp.copyTo(original[i]);
|
||||
declare.in(original[i]);
|
||||
}
|
||||
UMat result(tmp.size(), tmp.type());
|
||||
declare.out(result).iterations(10);
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
cv::fastNlMeansDenoisingMulti(original, result, imgs_count / 2, imgs_count, 15);
|
||||
|
||||
SANITY_CHECK(result);
|
||||
}
|
||||
|
||||
OCL_PERF_TEST(Photo, DISABLED_DenoisingColoredMulti)
|
||||
{
|
||||
const int imgs_count = 3;
|
||||
|
||||
vector<UMat> original(imgs_count);
|
||||
Mat tmp;
|
||||
for (int i = 0; i < imgs_count; i++)
|
||||
{
|
||||
string original_path = format("cv/denoising/lena_noised_gaussian_sigma=20_multi_%d.png", i);
|
||||
tmp = imread(getDataPath(original_path), IMREAD_COLOR);
|
||||
ASSERT_FALSE(tmp.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
tmp.copyTo(original[i]);
|
||||
declare.in(original[i]);
|
||||
}
|
||||
UMat result(tmp.size(), tmp.type());
|
||||
declare.out(result).iterations(10);
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
cv::fastNlMeansDenoisingColoredMulti(original, result, imgs_count / 2, imgs_count, 10, 15);
|
||||
|
||||
SANITY_CHECK(result);
|
||||
}
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
189
3rdparty/opencv-4.5.4/modules/photo/perf/perf_cuda.cpp
vendored
Normal file
189
3rdparty/opencv-4.5.4/modules/photo/perf/perf_cuda.cpp
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "perf_precomp.hpp"
|
||||
|
||||
#include "opencv2/photo/cuda.hpp"
|
||||
#include "opencv2/ts/cuda_perf.hpp"
|
||||
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
|
||||
#if defined (HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAIMGPROC)
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
using namespace perf;
|
||||
|
||||
#define CUDA_DENOISING_IMAGE_SIZES testing::Values(perf::szVGA, perf::sz720p)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// nonLocalMeans
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_WinSz_BlockSz, cv::Size, MatDepth, MatCn, int, int);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_WinSz_BlockSz, CUDA_NonLocalMeans,
|
||||
Combine(CUDA_DENOISING_IMAGE_SIZES,
|
||||
Values<MatDepth>(CV_8U),
|
||||
CUDA_CHANNELS_1_3,
|
||||
Values(21),
|
||||
Values(5)))
|
||||
{
|
||||
declare.time(600.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int search_widow_size = GET_PARAM(3);
|
||||
const int block_size = GET_PARAM(4);
|
||||
|
||||
const float h = 10;
|
||||
const int borderMode = cv::BORDER_REFLECT101;
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::nonLocalMeans(d_src, dst, h, search_widow_size, block_size, borderMode);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL_NO_CPU();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// fastNonLocalMeans
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_WinSz_BlockSz, cv::Size, MatDepth, MatCn, int, int);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_WinSz_BlockSz, CUDA_FastNonLocalMeans,
|
||||
Combine(CUDA_DENOISING_IMAGE_SIZES,
|
||||
Values<MatDepth>(CV_8U),
|
||||
CUDA_CHANNELS_1_3,
|
||||
Values(21),
|
||||
Values(7)))
|
||||
{
|
||||
declare.time(60.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int search_widow_size = GET_PARAM(2);
|
||||
const int block_size = GET_PARAM(3);
|
||||
|
||||
const float h = 10;
|
||||
const int type = CV_MAKE_TYPE(depth, 1);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::fastNlMeansDenoising(d_src, dst, h, search_widow_size, block_size);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::fastNlMeansDenoising(src, dst, h, block_size, search_widow_size);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// fastNonLocalMeans (colored)
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_WinSz_BlockSz, cv::Size, MatDepth, int, int);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_WinSz_BlockSz, CUDA_FastNonLocalMeansColored,
|
||||
Combine(CUDA_DENOISING_IMAGE_SIZES,
|
||||
Values<MatDepth>(CV_8U),
|
||||
Values(21),
|
||||
Values(7)))
|
||||
{
|
||||
declare.time(60.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int search_widow_size = GET_PARAM(2);
|
||||
const int block_size = GET_PARAM(3);
|
||||
|
||||
const float h = 10;
|
||||
const int type = CV_MAKE_TYPE(depth, 3);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::fastNlMeansDenoisingColored(d_src, dst, h, h, search_widow_size, block_size);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::fastNlMeansDenoisingColored(src, dst, h, h, block_size, search_widow_size);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
#endif
|
||||
37
3rdparty/opencv-4.5.4/modules/photo/perf/perf_inpaint.cpp
vendored
Normal file
37
3rdparty/opencv-4.5.4/modules/photo/perf/perf_inpaint.cpp
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
CV_ENUM(InpaintingMethod, INPAINT_NS, INPAINT_TELEA)
|
||||
typedef tuple<Size, InpaintingMethod> InpaintArea_InpaintingMethod_t;
|
||||
typedef perf::TestBaseWithParam<InpaintArea_InpaintingMethod_t> InpaintArea_InpaintingMethod;
|
||||
|
||||
|
||||
PERF_TEST_P(InpaintArea_InpaintingMethod, inpaint,
|
||||
testing::Combine(
|
||||
testing::Values(::perf::szSmall24, ::perf::szSmall32, ::perf::szSmall64),
|
||||
InpaintingMethod::all()
|
||||
)
|
||||
)
|
||||
{
|
||||
Mat src = imread(getDataPath("gpu/hog/road.png"));
|
||||
|
||||
Size sz = get<0>(GetParam());
|
||||
int inpaintingMethod = get<1>(GetParam());
|
||||
|
||||
Mat mask(src.size(), CV_8UC1, Scalar(0));
|
||||
Mat result(src.size(), src.type());
|
||||
|
||||
Rect inpaintArea(src.cols/3, src.rows/3, sz.width, sz.height);
|
||||
mask(inpaintArea).setTo(255);
|
||||
|
||||
declare.in(src, mask).out(result).time(120);
|
||||
|
||||
TEST_CYCLE() inpaint(src, mask, result, 10.0, inpaintingMethod);
|
||||
|
||||
Mat inpaintedArea = result(inpaintArea);
|
||||
SANITY_CHECK(inpaintedArea);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
15
3rdparty/opencv-4.5.4/modules/photo/perf/perf_main.cpp
vendored
Normal file
15
3rdparty/opencv-4.5.4/modules/photo/perf/perf_main.cpp
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
#include "perf_precomp.hpp"
|
||||
#include "opencv2/ts/cuda_perf.hpp"
|
||||
|
||||
static const char * impls[] = {
|
||||
#ifdef HAVE_CUDA
|
||||
"cuda",
|
||||
#endif
|
||||
"plain"
|
||||
};
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
CV_PERF_TEST_MAIN_WITH_IMPLS(photo, impls, perf::printCudaInfo())
|
||||
7
3rdparty/opencv-4.5.4/modules/photo/perf/perf_precomp.hpp
vendored
Normal file
7
3rdparty/opencv-4.5.4/modules/photo/perf/perf_precomp.hpp
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __OPENCV_PERF_PRECOMP_HPP__
|
||||
#define __OPENCV_PERF_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
|
||||
#endif
|
||||
281
3rdparty/opencv-4.5.4/modules/photo/src/align.cpp
vendored
Normal file
281
3rdparty/opencv-4.5.4/modules/photo/src/align.cpp
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "hdr_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class AlignMTBImpl CV_FINAL : public AlignMTB
|
||||
{
|
||||
public:
|
||||
AlignMTBImpl(int _max_bits, int _exclude_range, bool _cut) :
|
||||
name("AlignMTB"),
|
||||
max_bits(_max_bits),
|
||||
exclude_range(_exclude_range),
|
||||
cut(_cut)
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, std::vector<Mat>& dst,
|
||||
InputArray, InputArray) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
process(src, dst);
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays _src, std::vector<Mat>& dst) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> src;
|
||||
_src.getMatVector(src);
|
||||
|
||||
checkImageDimensions(src);
|
||||
dst.resize(src.size());
|
||||
|
||||
size_t pivot = src.size() / 2;
|
||||
dst[pivot] = src[pivot];
|
||||
Mat gray_base;
|
||||
cvtColor(src[pivot], gray_base, COLOR_RGB2GRAY);
|
||||
std::vector<Point> shifts;
|
||||
|
||||
for(size_t i = 0; i < src.size(); i++) {
|
||||
if(i == pivot) {
|
||||
shifts.push_back(Point(0, 0));
|
||||
continue;
|
||||
}
|
||||
Mat gray;
|
||||
cvtColor(src[i], gray, COLOR_RGB2GRAY);
|
||||
Point shift = calculateShift(gray_base, gray);
|
||||
shifts.push_back(shift);
|
||||
shiftMat(src[i], dst[i], shift);
|
||||
}
|
||||
if(cut) {
|
||||
Point max(0, 0), min(0, 0);
|
||||
for(size_t i = 0; i < shifts.size(); i++) {
|
||||
if(shifts[i].x > max.x) {
|
||||
max.x = shifts[i].x;
|
||||
}
|
||||
if(shifts[i].y > max.y) {
|
||||
max.y = shifts[i].y;
|
||||
}
|
||||
if(shifts[i].x < min.x) {
|
||||
min.x = shifts[i].x;
|
||||
}
|
||||
if(shifts[i].y < min.y) {
|
||||
min.y = shifts[i].y;
|
||||
}
|
||||
}
|
||||
Point size = dst[0].size();
|
||||
for(size_t i = 0; i < dst.size(); i++) {
|
||||
dst[i] = dst[i](Rect(max, min + size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Point calculateShift(InputArray _img0, InputArray _img1) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat img0 = _img0.getMat();
|
||||
Mat img1 = _img1.getMat();
|
||||
CV_Assert(img0.channels() == 1 && img0.type() == img1.type());
|
||||
CV_Assert(img0.size() == img1.size());
|
||||
|
||||
int maxlevel = static_cast<int>(log((double)max(img0.rows, img0.cols)) / log(2.0)) - 1;
|
||||
maxlevel = min(maxlevel, max_bits - 1);
|
||||
|
||||
std::vector<Mat> pyr0;
|
||||
std::vector<Mat> pyr1;
|
||||
buildPyr(img0, pyr0, maxlevel);
|
||||
buildPyr(img1, pyr1, maxlevel);
|
||||
|
||||
Point shift(0, 0);
|
||||
for(int level = maxlevel; level >= 0; level--) {
|
||||
|
||||
shift *= 2;
|
||||
Mat tb1, tb2, eb1, eb2;
|
||||
computeBitmaps(pyr0[level], tb1, eb1);
|
||||
computeBitmaps(pyr1[level], tb2, eb2);
|
||||
|
||||
int min_err = (int)pyr0[level].total();
|
||||
Point new_shift(shift);
|
||||
for(int i = -1; i <= 1; i++) {
|
||||
for(int j = -1; j <= 1; j++) {
|
||||
Point test_shift = shift + Point(i, j);
|
||||
Mat shifted_tb2, shifted_eb2, diff;
|
||||
shiftMat(tb2, shifted_tb2, test_shift);
|
||||
shiftMat(eb2, shifted_eb2, test_shift);
|
||||
bitwise_xor(tb1, shifted_tb2, diff);
|
||||
bitwise_and(diff, eb1, diff);
|
||||
bitwise_and(diff, shifted_eb2, diff);
|
||||
int err = countNonZero(diff);
|
||||
if(err < min_err) {
|
||||
new_shift = test_shift;
|
||||
min_err = err;
|
||||
}
|
||||
}
|
||||
}
|
||||
shift = new_shift;
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
void shiftMat(InputArray _src, OutputArray _dst, const Point shift) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Mat res = Mat::zeros(src.size(), src.type());
|
||||
int width = src.cols - abs(shift.x);
|
||||
int height = src.rows - abs(shift.y);
|
||||
Rect dst_rect(max(shift.x, 0), max(shift.y, 0), width, height);
|
||||
Rect src_rect(max(-shift.x, 0), max(-shift.y, 0), width, height);
|
||||
src(src_rect).copyTo(res(dst_rect));
|
||||
res.copyTo(dst);
|
||||
}
|
||||
|
||||
int getMaxBits() const CV_OVERRIDE { return max_bits; }
|
||||
void setMaxBits(int val) CV_OVERRIDE { max_bits = val; }
|
||||
|
||||
int getExcludeRange() const CV_OVERRIDE { return exclude_range; }
|
||||
void setExcludeRange(int val) CV_OVERRIDE { exclude_range = val; }
|
||||
|
||||
bool getCut() const CV_OVERRIDE { return cut; }
|
||||
void setCut(bool val) CV_OVERRIDE { cut = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "max_bits" << max_bits
|
||||
<< "exclude_range" << exclude_range
|
||||
<< "cut" << static_cast<int>(cut);
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
max_bits = fn["max_bits"];
|
||||
exclude_range = fn["exclude_range"];
|
||||
int cut_val = fn["cut"];
|
||||
cut = (cut_val != 0);
|
||||
}
|
||||
|
||||
void computeBitmaps(InputArray _img, OutputArray _tb, OutputArray _eb) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat img = _img.getMat();
|
||||
_tb.create(img.size(), CV_8U);
|
||||
_eb.create(img.size(), CV_8U);
|
||||
Mat tb = _tb.getMat(), eb = _eb.getMat();
|
||||
int median = getMedian(img);
|
||||
compare(img, median, tb, CMP_GT);
|
||||
compare(abs(img - median), exclude_range, eb, CMP_GT);
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
int max_bits, exclude_range;
|
||||
bool cut;
|
||||
|
||||
void downsample(Mat& src, Mat& dst)
|
||||
{
|
||||
dst = Mat(src.rows / 2, src.cols / 2, CV_8UC1);
|
||||
|
||||
int offset = src.cols * 2;
|
||||
uchar *src_ptr = src.ptr();
|
||||
uchar *dst_ptr = dst.ptr();
|
||||
for(int y = 0; y < dst.rows; y ++) {
|
||||
uchar *ptr = src_ptr;
|
||||
for(int x = 0; x < dst.cols; x++) {
|
||||
dst_ptr[0] = ptr[0];
|
||||
dst_ptr++;
|
||||
ptr += 2;
|
||||
}
|
||||
src_ptr += offset;
|
||||
}
|
||||
}
|
||||
|
||||
void buildPyr(Mat& img, std::vector<Mat>& pyr, int maxlevel)
|
||||
{
|
||||
pyr.resize(maxlevel + 1);
|
||||
pyr[0] = img.clone();
|
||||
for(int level = 0; level < maxlevel; level++) {
|
||||
downsample(pyr[level], pyr[level + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
int getMedian(Mat& img)
|
||||
{
|
||||
int channels = 0;
|
||||
Mat hist;
|
||||
int hist_size = LDR_SIZE;
|
||||
float range[] = {0, LDR_SIZE} ;
|
||||
const float* ranges[] = {range};
|
||||
calcHist(&img, 1, &channels, Mat(), hist, 1, &hist_size, ranges);
|
||||
float *ptr = hist.ptr<float>();
|
||||
int median = 0, sum = 0;
|
||||
int thresh = (int)img.total() / 2;
|
||||
while(sum < thresh && median < LDR_SIZE) {
|
||||
sum += static_cast<int>(ptr[median]);
|
||||
median++;
|
||||
}
|
||||
return median;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<AlignMTB> createAlignMTB(int max_bits, int exclude_range, bool cut)
|
||||
{
|
||||
return makePtr<AlignMTBImpl>(max_bits, exclude_range, cut);
|
||||
}
|
||||
|
||||
}
|
||||
184
3rdparty/opencv-4.5.4/modules/photo/src/arrays.hpp
vendored
Normal file
184
3rdparty/opencv-4.5.4/modules/photo/src/arrays.hpp
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective icvers.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 "opencv2/core/base.hpp"
|
||||
|
||||
#ifndef __OPENCV_DENOISING_ARRAYS_HPP__
|
||||
#define __OPENCV_DENOISING_ARRAYS_HPP__
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template <class T>
|
||||
struct Array2d
|
||||
{
|
||||
T* a;
|
||||
int n1,n2;
|
||||
bool needToDeallocArray;
|
||||
|
||||
Array2d(const Array2d& array2d):
|
||||
a(array2d.a), n1(array2d.n1), n2(array2d.n2), needToDeallocArray(false)
|
||||
{
|
||||
if (array2d.needToDeallocArray)
|
||||
{
|
||||
CV_Error(Error::BadDataPtr, "Copy constructor for self allocating arrays not supported");
|
||||
}
|
||||
}
|
||||
|
||||
Array2d(T* _a, int _n1, int _n2):
|
||||
a(_a), n1(_n1), n2(_n2), needToDeallocArray(false)
|
||||
{
|
||||
}
|
||||
|
||||
Array2d(int _n1, int _n2):
|
||||
n1(_n1), n2(_n2), needToDeallocArray(true)
|
||||
{
|
||||
a = new T[n1*n2];
|
||||
}
|
||||
|
||||
~Array2d()
|
||||
{
|
||||
if (needToDeallocArray)
|
||||
delete[] a;
|
||||
}
|
||||
|
||||
T* operator [] (int i)
|
||||
{
|
||||
return a + i*n2;
|
||||
}
|
||||
|
||||
inline T* row_ptr(int i)
|
||||
{
|
||||
return (*this)[i];
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Array3d
|
||||
{
|
||||
T* a;
|
||||
int n1,n2,n3;
|
||||
bool needToDeallocArray;
|
||||
|
||||
Array3d(T* _a, int _n1, int _n2, int _n3):
|
||||
a(_a), n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(false)
|
||||
{
|
||||
}
|
||||
|
||||
Array3d(int _n1, int _n2, int _n3):
|
||||
n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(true)
|
||||
{
|
||||
a = new T[n1*n2*n3];
|
||||
}
|
||||
|
||||
~Array3d()
|
||||
{
|
||||
if (needToDeallocArray)
|
||||
delete[] a;
|
||||
}
|
||||
|
||||
Array2d<T> operator [] (int i)
|
||||
{
|
||||
Array2d<T> array2d(a + i*n2*n3, n2, n3);
|
||||
return array2d;
|
||||
}
|
||||
|
||||
inline T* row_ptr(int i1, int i2)
|
||||
{
|
||||
return a + i1*n2*n3 + i2*n3;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Array4d
|
||||
{
|
||||
T* a;
|
||||
int n1,n2,n3,n4;
|
||||
bool needToDeallocArray;
|
||||
int steps[4];
|
||||
|
||||
void init_steps()
|
||||
{
|
||||
steps[0] = n2*n3*n4;
|
||||
steps[1] = n3*n4;
|
||||
steps[2] = n4;
|
||||
steps[3] = 1;
|
||||
}
|
||||
|
||||
Array4d(T* _a, int _n1, int _n2, int _n3, int _n4) :
|
||||
a(_a), n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(false)
|
||||
{
|
||||
init_steps();
|
||||
}
|
||||
|
||||
Array4d(int _n1, int _n2, int _n3, int _n4) :
|
||||
n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(true)
|
||||
{
|
||||
a = new T[n1*n2*n3*n4];
|
||||
init_steps();
|
||||
}
|
||||
|
||||
~Array4d()
|
||||
{
|
||||
if (needToDeallocArray)
|
||||
delete[] a;
|
||||
}
|
||||
|
||||
Array3d<T> operator [] (int i)
|
||||
{
|
||||
Array3d<T> array3d(a + i*n2*n3*n4, n2, n3, n4);
|
||||
return array3d;
|
||||
}
|
||||
|
||||
inline T* row_ptr(int i1, int i2, int i3)
|
||||
{
|
||||
return a + i1*n2*n3*n4 + i2*n3*n4 + i3*n4;
|
||||
}
|
||||
|
||||
inline int step_size(int dimension)
|
||||
{
|
||||
return steps[dimension];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
311
3rdparty/opencv-4.5.4/modules/photo/src/calibrate.cpp
vendored
Normal file
311
3rdparty/opencv-4.5.4/modules/photo/src/calibrate.cpp
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "hdr_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class CalibrateDebevecImpl CV_FINAL : public CalibrateDebevec
|
||||
{
|
||||
public:
|
||||
CalibrateDebevecImpl(int _samples, float _lambda, bool _random) :
|
||||
name("CalibrateDebevec"),
|
||||
samples(_samples),
|
||||
lambda(_lambda),
|
||||
random(_random),
|
||||
w(triangleWeights())
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, InputArray _times) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
// check inputs
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
Mat times = _times.getMat();
|
||||
|
||||
CV_Assert(images.size() == times.total());
|
||||
checkImageDimensions(images);
|
||||
CV_Assert(images[0].depth() == CV_8U);
|
||||
CV_Assert(times.type() == CV_32FC1);
|
||||
|
||||
// create output
|
||||
int channels = images[0].channels();
|
||||
int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
|
||||
int rows = images[0].rows;
|
||||
int cols = images[0].cols;
|
||||
|
||||
dst.create(LDR_SIZE, 1, CV_32FCC);
|
||||
Mat result = dst.getMat();
|
||||
|
||||
// pick pixel locations (either random or in a rectangular grid)
|
||||
std::vector<Point> points;
|
||||
points.reserve(samples);
|
||||
if(random) {
|
||||
for(int i = 0; i < samples; i++) {
|
||||
points.push_back(Point(rand() % cols, rand() % rows));
|
||||
}
|
||||
} else {
|
||||
int x_points = static_cast<int>(sqrt(static_cast<double>(samples) * cols / rows));
|
||||
CV_Assert(0 < x_points && x_points <= cols);
|
||||
int y_points = samples / x_points;
|
||||
CV_Assert(0 < y_points && y_points <= rows);
|
||||
int step_x = cols / x_points;
|
||||
int step_y = rows / y_points;
|
||||
for(int i = 0, x = step_x / 2; i < x_points; i++, x += step_x) {
|
||||
for(int j = 0, y = step_y / 2; j < y_points; j++, y += step_y) {
|
||||
if( 0 <= x && x < cols && 0 <= y && y < rows ) {
|
||||
points.push_back(Point(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
// we can have slightly less grid points than specified
|
||||
//samples = static_cast<int>(points.size());
|
||||
}
|
||||
|
||||
// we need enough equations to ensure a sufficiently overdetermined system
|
||||
// (maybe only as a warning)
|
||||
//CV_Assert(points.size() * (images.size() - 1) >= LDR_SIZE);
|
||||
|
||||
// solve for imaging system response function, over each channel separately
|
||||
std::vector<Mat> result_split(channels);
|
||||
for(int ch = 0; ch < channels; ch++) {
|
||||
// initialize system of linear equations
|
||||
Mat A = Mat::zeros((int)points.size() * (int)images.size() + LDR_SIZE + 1,
|
||||
LDR_SIZE + (int)points.size(), CV_32F);
|
||||
Mat B = Mat::zeros(A.rows, 1, CV_32F);
|
||||
|
||||
// include the data-fitting equations
|
||||
int k = 0;
|
||||
for(size_t i = 0; i < points.size(); i++) {
|
||||
for(size_t j = 0; j < images.size(); j++) {
|
||||
// val = images[j].at<Vec3b>(points[i].y, points[i].x)[ch]
|
||||
int val = images[j].ptr()[channels*(points[i].y * cols + points[i].x) + ch];
|
||||
float wij = w.at<float>(val);
|
||||
A.at<float>(k, val) = wij;
|
||||
A.at<float>(k, LDR_SIZE + (int)i) = -wij;
|
||||
B.at<float>(k, 0) = wij * log(times.at<float>((int)j));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// fix the curve by setting its middle value to 0
|
||||
A.at<float>(k, LDR_SIZE / 2) = 1;
|
||||
k++;
|
||||
|
||||
// include the smoothness equations
|
||||
for(int i = 0; i < (LDR_SIZE - 2); i++) {
|
||||
float wi = w.at<float>(i + 1);
|
||||
A.at<float>(k, i) = lambda * wi;
|
||||
A.at<float>(k, i + 1) = -2 * lambda * wi;
|
||||
A.at<float>(k, i + 2) = lambda * wi;
|
||||
k++;
|
||||
}
|
||||
|
||||
// solve the overdetermined system using SVD (least-squares problem)
|
||||
Mat solution;
|
||||
solve(A, B, solution, DECOMP_SVD);
|
||||
solution.rowRange(0, LDR_SIZE).copyTo(result_split[ch]);
|
||||
}
|
||||
|
||||
// combine log-exposures and take its exponent
|
||||
merge(result_split, result);
|
||||
exp(result, result);
|
||||
}
|
||||
|
||||
int getSamples() const CV_OVERRIDE { return samples; }
|
||||
void setSamples(int val) CV_OVERRIDE { samples = val; }
|
||||
|
||||
float getLambda() const CV_OVERRIDE { return lambda; }
|
||||
void setLambda(float val) CV_OVERRIDE { lambda = val; }
|
||||
|
||||
bool getRandom() const CV_OVERRIDE { return random; }
|
||||
void setRandom(bool val) CV_OVERRIDE { random = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "samples" << samples
|
||||
<< "lambda" << lambda
|
||||
<< "random" << static_cast<int>(random);
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
samples = fn["samples"];
|
||||
lambda = fn["lambda"];
|
||||
int random_val = fn["random"];
|
||||
random = (random_val != 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
String name; // calibration algorithm identifier
|
||||
int samples; // number of pixel locations to sample
|
||||
float lambda; // constant that determines the amount of smoothness
|
||||
bool random; // whether to sample locations randomly or in a grid shape
|
||||
Mat w; // weighting function for corresponding pixel values
|
||||
};
|
||||
|
||||
Ptr<CalibrateDebevec> createCalibrateDebevec(int samples, float lambda, bool random)
|
||||
{
|
||||
return makePtr<CalibrateDebevecImpl>(samples, lambda, random);
|
||||
}
|
||||
|
||||
class CalibrateRobertsonImpl CV_FINAL : public CalibrateRobertson
|
||||
{
|
||||
public:
|
||||
CalibrateRobertsonImpl(int _max_iter, float _threshold) :
|
||||
name("CalibrateRobertson"),
|
||||
max_iter(_max_iter),
|
||||
threshold(_threshold),
|
||||
weight(RobertsonWeights())
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, InputArray _times) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
Mat times = _times.getMat();
|
||||
|
||||
CV_Assert(images.size() == times.total());
|
||||
checkImageDimensions(images);
|
||||
CV_Assert(images[0].depth() == CV_8U);
|
||||
|
||||
int channels = images[0].channels();
|
||||
int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
|
||||
CV_Assert(channels >= 1 && channels <= 3);
|
||||
|
||||
dst.create(LDR_SIZE, 1, CV_32FCC);
|
||||
Mat response = dst.getMat();
|
||||
response = linearResponse(3) / (LDR_SIZE / 2.0f);
|
||||
|
||||
Mat card = Mat::zeros(LDR_SIZE, 1, CV_32FCC);
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
uchar *ptr = images[i].ptr();
|
||||
for(size_t pos = 0; pos < images[i].total(); pos++) {
|
||||
for(int c = 0; c < channels; c++, ptr++) {
|
||||
card.at<Vec3f>(*ptr)[c] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
card = 1.0 / card;
|
||||
|
||||
Ptr<MergeRobertson> merge = createMergeRobertson();
|
||||
for(int iter = 0; iter < max_iter; iter++) {
|
||||
|
||||
radiance = Mat::zeros(images[0].size(), CV_32FCC);
|
||||
merge->process(images, radiance, times, response);
|
||||
|
||||
Mat new_response = Mat::zeros(LDR_SIZE, 1, CV_32FC3);
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
uchar *ptr = images[i].ptr();
|
||||
float* rad_ptr = radiance.ptr<float>();
|
||||
for(size_t pos = 0; pos < images[i].total(); pos++) {
|
||||
for(int c = 0; c < channels; c++, ptr++, rad_ptr++) {
|
||||
new_response.at<Vec3f>(*ptr)[c] += times.at<float>((int)i) * *rad_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
new_response = new_response.mul(card);
|
||||
for(int c = 0; c < 3; c++) {
|
||||
float middle = new_response.at<Vec3f>(LDR_SIZE / 2)[c];
|
||||
for(int i = 0; i < LDR_SIZE; i++) {
|
||||
new_response.at<Vec3f>(i)[c] /= middle;
|
||||
}
|
||||
}
|
||||
float diff = static_cast<float>(sum(sum(abs(new_response - response)))[0] / channels);
|
||||
new_response.copyTo(response);
|
||||
if(diff < threshold) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getMaxIter() const CV_OVERRIDE { return max_iter; }
|
||||
void setMaxIter(int val) CV_OVERRIDE { max_iter = val; }
|
||||
|
||||
float getThreshold() const CV_OVERRIDE { return threshold; }
|
||||
void setThreshold(float val) CV_OVERRIDE { threshold = val; }
|
||||
|
||||
Mat getRadiance() const CV_OVERRIDE { return radiance; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "max_iter" << max_iter
|
||||
<< "threshold" << threshold;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
max_iter = fn["max_iter"];
|
||||
threshold = fn["threshold"];
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
int max_iter;
|
||||
float threshold;
|
||||
Mat weight, radiance;
|
||||
};
|
||||
|
||||
Ptr<CalibrateRobertson> createCalibrateRobertson(int max_iter, float threshold)
|
||||
{
|
||||
return makePtr<CalibrateRobertsonImpl>(max_iter, threshold);
|
||||
}
|
||||
|
||||
}
|
||||
174
3rdparty/opencv-4.5.4/modules/photo/src/contrast_preserve.cpp
vendored
Normal file
174
3rdparty/opencv-4.5.4/modules/photo/src/contrast_preserve.cpp
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include "contrast_preserve.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat I = _src.getMat();
|
||||
_dst.create(I.size(), CV_8UC1);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
_color_boost.create(I.size(), CV_8UC3);
|
||||
Mat color_boost = _color_boost.getMat();
|
||||
|
||||
CV_Assert(!I.empty() && (I.channels()==3));
|
||||
|
||||
// Parameter Setting
|
||||
const int maxIter = 15;
|
||||
const double tol = .0001;
|
||||
int iterCount = 0;
|
||||
double E = 0;
|
||||
double pre_E = std::numeric_limits<double>::infinity();
|
||||
|
||||
Mat img;
|
||||
I.convertTo(img, CV_32FC3, 1.0/255.0);
|
||||
|
||||
// Initialization
|
||||
Decolor obj;
|
||||
|
||||
vector <double> Cg;
|
||||
vector < vector <double> > polyGrad;
|
||||
vector <Vec3i> comb;
|
||||
vector <double> alf;
|
||||
|
||||
obj.grad_system(img,polyGrad,Cg,comb);
|
||||
obj.weak_order(img,alf);
|
||||
|
||||
// Solver
|
||||
Mat Mt = Mat(int(polyGrad.size()),int(polyGrad[0].size()), CV_32FC1);
|
||||
obj.wei_update_matrix(polyGrad,Cg,Mt);
|
||||
|
||||
vector <double> wei;
|
||||
obj.wei_inti(comb,wei);
|
||||
|
||||
//////////////////////////////// main loop starting ////////////////////////////////////////
|
||||
|
||||
vector <double> G_pos(alf.size());
|
||||
vector <double> G_neg(alf.size());
|
||||
vector <double> EXPsum(G_pos.size());
|
||||
vector <double> EXPterm(G_pos.size());
|
||||
vector <double> temp(polyGrad[0].size());
|
||||
vector <double> temp1(polyGrad[0].size());
|
||||
vector <double> temp2(EXPsum.size());
|
||||
vector <double> wei1(polyGrad.size());
|
||||
|
||||
while(sqrt(pow(E-pre_E,2)) > tol)
|
||||
{
|
||||
iterCount +=1;
|
||||
pre_E = E;
|
||||
|
||||
for(size_t i=0; i<polyGrad[0].size(); i++)
|
||||
{
|
||||
double val = 0.0;
|
||||
for(size_t j=0; j<polyGrad.size(); j++)
|
||||
val = val + (polyGrad[j][i] * wei[j]);
|
||||
temp[i] = val - Cg[i];
|
||||
temp1[i] = val + Cg[i];
|
||||
}
|
||||
|
||||
for(size_t i=0; i<alf.size(); i++)
|
||||
{
|
||||
const double sqSigma = obj.sigma * obj.sigma;
|
||||
const double pos = ((1 + alf[i])/2) * exp(-1.0 * 0.5 * (temp[i] * temp[i]) / sqSigma);
|
||||
const double neg = ((1 - alf[i])/2) * exp(-1.0 * 0.5 * (temp1[i] * temp1[i]) / sqSigma);
|
||||
G_pos[i] = pos;
|
||||
G_neg[i] = neg;
|
||||
}
|
||||
|
||||
for(size_t i=0; i<G_pos.size(); i++)
|
||||
EXPsum[i] = G_pos[i]+G_neg[i];
|
||||
|
||||
for(size_t i=0; i<EXPsum.size(); i++)
|
||||
temp2[i] = (EXPsum[i] == 0) ? 1.0 : 0.0;
|
||||
|
||||
for(size_t i=0; i<G_pos.size(); i++)
|
||||
EXPterm[i] = (G_pos[i] - G_neg[i])/(EXPsum[i] + temp2[i]);
|
||||
|
||||
for(int i=0; i<int(polyGrad.size()); i++)
|
||||
{
|
||||
double val1 = 0.0;
|
||||
for(int j=0; j<int(polyGrad[0].size()); j++)
|
||||
{
|
||||
val1 = val1 + (Mt.at<float>(i,j) * EXPterm[j]);
|
||||
}
|
||||
wei1[i] = val1;
|
||||
}
|
||||
|
||||
for(size_t i=0; i<wei.size(); i++)
|
||||
wei[i] = wei1[i];
|
||||
|
||||
E = obj.energyCalcu(Cg, polyGrad, wei);
|
||||
|
||||
if(iterCount > maxIter)
|
||||
break;
|
||||
}
|
||||
|
||||
Mat Gray = Mat::zeros(img.size(),CV_32FC1);
|
||||
obj.grayImContruct(wei, img, Gray);
|
||||
|
||||
Gray.convertTo(dst,CV_8UC1,255);
|
||||
|
||||
/////////////////////////////////// Contrast Boosting /////////////////////////////////
|
||||
|
||||
Mat lab;
|
||||
cvtColor(I,lab,COLOR_BGR2Lab);
|
||||
|
||||
vector <Mat> lab_channel;
|
||||
split(lab,lab_channel);
|
||||
|
||||
dst.copyTo(lab_channel[0]);
|
||||
|
||||
merge(lab_channel,lab);
|
||||
|
||||
cvtColor(lab,color_boost,COLOR_Lab2BGR);
|
||||
}
|
||||
373
3rdparty/opencv-4.5.4/modules/photo/src/contrast_preserve.hpp
vendored
Normal file
373
3rdparty/opencv-4.5.4/modules/photo/src/contrast_preserve.hpp
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class Decolor
|
||||
{
|
||||
private:
|
||||
Mat kernelx;
|
||||
Mat kernely;
|
||||
int order;
|
||||
|
||||
public:
|
||||
float sigma;
|
||||
|
||||
Decolor();
|
||||
static vector<double> product(const vector <Vec3i> &comb, const double initRGB[3]);
|
||||
double energyCalcu(const vector <double> &Cg, const vector < vector <double> > &polyGrad, const vector <double> &wei) const;
|
||||
void singleChannelGradx(const Mat &img, Mat& dest) const;
|
||||
void singleChannelGrady(const Mat &img, Mat& dest) const;
|
||||
void gradvector(const Mat &img, vector <double> &grad) const;
|
||||
void colorGrad(const Mat &img, vector <double> &Cg) const;
|
||||
static void add_vector(vector <Vec3i> &comb, int &idx, int r,int g,int b);
|
||||
static void add_to_vector_poly(vector < vector <double> > &polyGrad, const vector <double> &curGrad, int &idx1);
|
||||
void weak_order(const Mat &img, vector <double> &alf) const;
|
||||
void grad_system(const Mat &img, vector < vector < double > > &polyGrad,
|
||||
vector < double > &Cg, vector <Vec3i>& comb) const;
|
||||
static void wei_update_matrix(const vector < vector <double> > &poly, const vector <double> &Cg, Mat &X);
|
||||
static void wei_inti(const vector <Vec3i> &comb, vector <double> &wei);
|
||||
void grayImContruct(vector <double> &wei, const Mat &img, Mat &Gray) const;
|
||||
};
|
||||
|
||||
double Decolor::energyCalcu(const vector <double> &Cg, const vector < vector <double> > &polyGrad, const vector <double> &wei) const
|
||||
{
|
||||
const size_t size = polyGrad[0].size();
|
||||
vector <double> energy(size);
|
||||
vector <double> temp(size);
|
||||
vector <double> temp1(size);
|
||||
|
||||
for(size_t i=0;i< polyGrad[0].size();i++)
|
||||
{
|
||||
double val = 0.0;
|
||||
for(size_t j =0;j<polyGrad.size();j++)
|
||||
val = val + (polyGrad[j][i] * wei[j]);
|
||||
temp[i] = val - Cg[i];
|
||||
temp1[i] = val + Cg[i];
|
||||
}
|
||||
|
||||
for(size_t i=0;i<polyGrad[0].size();i++)
|
||||
energy[i] = -1.0*log(exp(-1.0*pow(temp[i],2)/sigma) + exp(-1.0*pow(temp1[i],2)/sigma));
|
||||
|
||||
double sum = 0.0;
|
||||
for(size_t i=0;i<polyGrad[0].size();i++)
|
||||
sum +=energy[i];
|
||||
|
||||
return (sum/polyGrad[0].size());
|
||||
|
||||
}
|
||||
|
||||
Decolor::Decolor()
|
||||
{
|
||||
kernelx = Mat(1,2, CV_32FC1);
|
||||
kernely = Mat(2,1, CV_32FC1);
|
||||
kernelx.at<float>(0,0)=1.0;
|
||||
kernelx.at<float>(0,1)=-1.0;
|
||||
kernely.at<float>(0,0)=1.0;
|
||||
kernely.at<float>(1,0)=-1.0;
|
||||
order = 2;
|
||||
sigma = 0.02f;
|
||||
}
|
||||
|
||||
vector<double> Decolor::product(const vector <Vec3i> &comb, const double initRGB[3])
|
||||
{
|
||||
vector <double> res(comb.size());
|
||||
for (size_t i=0;i<comb.size();i++)
|
||||
{
|
||||
double dp = 0.0;
|
||||
for(int j=0;j<3;j++)
|
||||
dp = dp + (comb[i][j] * initRGB[j]);
|
||||
res[i] = dp;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Decolor::singleChannelGradx(const Mat &img, Mat& dest) const
|
||||
{
|
||||
const int w = img.size().width;
|
||||
const Point anchor(kernelx.cols - kernelx.cols/2 - 1, kernelx.rows - kernelx.rows/2 - 1);
|
||||
filter2D(img, dest, -1, kernelx, anchor, 0.0, BORDER_CONSTANT);
|
||||
dest.col(w - 1) = 0.0;
|
||||
}
|
||||
|
||||
void Decolor::singleChannelGrady(const Mat &img, Mat& dest) const
|
||||
{
|
||||
const int h = img.size().height;
|
||||
const Point anchor(kernely.cols - kernely.cols/2 - 1, kernely.rows - kernely.rows/2 - 1);
|
||||
filter2D(img, dest, -1, kernely, anchor, 0.0, BORDER_CONSTANT);
|
||||
dest.row(h - 1) = 0.0;
|
||||
}
|
||||
|
||||
void Decolor::gradvector(const Mat &img, vector <double> &grad) const
|
||||
{
|
||||
Mat dest;
|
||||
Mat dest1;
|
||||
singleChannelGradx(img,dest);
|
||||
singleChannelGrady(img,dest1);
|
||||
|
||||
Mat d_trans=dest.t();
|
||||
Mat d1_trans=dest1.t();
|
||||
|
||||
const int height = d_trans.size().height;
|
||||
const int width = d_trans.size().width;
|
||||
|
||||
grad.resize(width * height * 2);
|
||||
|
||||
for(int i=0;i<height;i++)
|
||||
for(int j=0;j<width;j++)
|
||||
grad[i*width + j] = d_trans.at<float>(i, j);
|
||||
|
||||
const int offset = width * height;
|
||||
for(int i=0;i<height;i++)
|
||||
for(int j=0;j<width;j++)
|
||||
grad[offset + i * width + j] = d1_trans.at<float>(i, j);
|
||||
}
|
||||
|
||||
void Decolor::colorGrad(const Mat &img, vector <double> &Cg) const
|
||||
{
|
||||
Mat lab;
|
||||
|
||||
cvtColor(img,lab,COLOR_BGR2Lab);
|
||||
|
||||
vector <Mat> lab_channel;
|
||||
split(lab,lab_channel);
|
||||
|
||||
vector <double> ImL;
|
||||
vector <double> Ima;
|
||||
vector <double> Imb;
|
||||
|
||||
gradvector(lab_channel[0],ImL);
|
||||
gradvector(lab_channel[1],Ima);
|
||||
gradvector(lab_channel[2],Imb);
|
||||
|
||||
Cg.resize(ImL.size());
|
||||
for(size_t i=0;i<ImL.size();i++)
|
||||
{
|
||||
const double res = sqrt(pow(ImL[i],2) + pow(Ima[i],2) + pow(Imb[i],2))/100;
|
||||
Cg[i] = res;
|
||||
}
|
||||
}
|
||||
|
||||
void Decolor::add_vector(vector <Vec3i> &comb, int &idx, int r,int g,int b)
|
||||
{
|
||||
comb.push_back(Vec3i(r, g, b));
|
||||
idx++;
|
||||
}
|
||||
|
||||
void Decolor::add_to_vector_poly(vector < vector <double> > &polyGrad, const vector <double> &curGrad, int &idx1)
|
||||
{
|
||||
polyGrad.push_back(curGrad);
|
||||
idx1++;
|
||||
}
|
||||
|
||||
void Decolor::weak_order(const Mat &im, vector <double> &alf) const
|
||||
{
|
||||
Mat img;
|
||||
const int h = im.size().height;
|
||||
const int w = im.size().width;
|
||||
if((h + w) > 800)
|
||||
{
|
||||
const double sizefactor = double(800)/(h+w);
|
||||
resize(im, img, Size(cvRound(w*sizefactor), cvRound(h*sizefactor)));
|
||||
}
|
||||
else
|
||||
{
|
||||
img = im;
|
||||
}
|
||||
|
||||
Mat curIm = Mat(img.size(),CV_32FC1);
|
||||
vector <Mat> rgb_channel;
|
||||
split(img,rgb_channel);
|
||||
|
||||
vector <double> Rg, Gg, Bg;
|
||||
gradvector(rgb_channel[2],Rg);
|
||||
gradvector(rgb_channel[1],Gg);
|
||||
gradvector(rgb_channel[0],Bg);
|
||||
|
||||
vector <double> t1(Rg.size()), t2(Rg.size()), t3(Rg.size());
|
||||
vector <double> tmp1(Rg.size()), tmp2(Rg.size()), tmp3(Rg.size());
|
||||
|
||||
const double level = .05;
|
||||
|
||||
for(size_t i=0;i<Rg.size();i++)
|
||||
{
|
||||
t1[i] = (Rg[i] > level) ? 1.0 : 0.0;
|
||||
t2[i] = (Gg[i] > level) ? 1.0 : 0.0;
|
||||
t3[i] = (Bg[i] > level) ? 1.0 : 0.0;
|
||||
tmp1[i] = (Rg[i] < -1.0*level) ? 1.0 : 0.0;
|
||||
tmp2[i] = (Gg[i] < -1.0*level) ? 1.0 : 0.0;
|
||||
tmp3[i] = (Bg[i] < -1.0*level) ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
alf.resize(Rg.size());
|
||||
for(size_t i =0 ;i < Rg.size();i++)
|
||||
alf[i] = (t1[i] * t2[i] * t3[i]);
|
||||
|
||||
for(size_t i =0 ;i < Rg.size();i++)
|
||||
alf[i] -= tmp1[i] * tmp2[i] * tmp3[i];
|
||||
}
|
||||
|
||||
void Decolor::grad_system(const Mat &im, vector < vector < double > > &polyGrad,
|
||||
vector < double > &Cg, vector <Vec3i>& comb) const
|
||||
{
|
||||
Mat img;
|
||||
int h = im.size().height;
|
||||
int w = im.size().width;
|
||||
if((h + w) > 800)
|
||||
{
|
||||
const double sizefactor = double(800)/(h+w);
|
||||
resize(im, img, Size(cvRound(w*sizefactor), cvRound(h*sizefactor)));
|
||||
}
|
||||
else
|
||||
{
|
||||
img = im;
|
||||
}
|
||||
|
||||
h = img.size().height;
|
||||
w = img.size().width;
|
||||
colorGrad(img,Cg);
|
||||
|
||||
Mat curIm = Mat(img.size(),CV_32FC1);
|
||||
vector <Mat> rgb_channel;
|
||||
split(img,rgb_channel);
|
||||
|
||||
int idx = 0, idx1 = 0;
|
||||
for(int r=0 ;r <=order; r++)
|
||||
for(int g=0; g<=order;g++)
|
||||
for(int b =0; b <=order;b++)
|
||||
{
|
||||
if((r+g+b)<=order && (r+g+b) > 0)
|
||||
{
|
||||
add_vector(comb,idx,r,g,b);
|
||||
for(int i = 0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
curIm.at<float>(i,j)=static_cast<float>(
|
||||
pow(rgb_channel[2].at<float>(i,j),r)*pow(rgb_channel[1].at<float>(i,j),g)*
|
||||
pow(rgb_channel[0].at<float>(i,j),b));
|
||||
vector <double> curGrad;
|
||||
gradvector(curIm,curGrad);
|
||||
add_to_vector_poly(polyGrad,curGrad,idx1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decolor::wei_update_matrix(const vector < vector <double> > &poly, const vector <double> &Cg, Mat &X)
|
||||
{
|
||||
const int size = static_cast<int>(poly.size());
|
||||
const int size0 = static_cast<int>(poly[0].size());
|
||||
Mat P = Mat(size, size0, CV_32FC1);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
for (int j = 0; j < size0;j++)
|
||||
P.at<float>(i,j) = static_cast<float>(poly[i][j]);
|
||||
|
||||
const Mat P_trans = P.t();
|
||||
Mat B = Mat(size, size0, CV_32FC1);
|
||||
for(int i =0;i < size;i++)
|
||||
{
|
||||
for(int j = 0, end = int(Cg.size()); j < end;j++)
|
||||
B.at<float>(i,j) = static_cast<float>(poly[i][j] * Cg[j]);
|
||||
}
|
||||
|
||||
Mat A = P*P_trans;
|
||||
solve(A, B, X, DECOMP_NORMAL);
|
||||
|
||||
}
|
||||
|
||||
void Decolor::wei_inti(const vector <Vec3i> &comb, vector <double> &wei)
|
||||
{
|
||||
double initRGB[3] = { .33, .33, .33 };
|
||||
|
||||
wei = product(comb,initRGB);
|
||||
|
||||
vector <int> sum(comb.size());
|
||||
|
||||
for(size_t i=0;i<comb.size();i++)
|
||||
sum[i] = (comb[i][0] + comb[i][1] + comb[i][2]);
|
||||
|
||||
for(size_t i=0;i<sum.size();i++)
|
||||
{
|
||||
if(sum[i] == 1)
|
||||
wei[i] = wei[i] * double(1);
|
||||
else
|
||||
wei[i] = wei[i] * double(0);
|
||||
}
|
||||
|
||||
sum.clear();
|
||||
|
||||
}
|
||||
|
||||
void Decolor::grayImContruct(vector <double> &wei, const Mat &img, Mat &Gray) const
|
||||
{
|
||||
const int h = img.size().height;
|
||||
const int w = img.size().width;
|
||||
|
||||
vector <Mat> rgb_channel;
|
||||
split(img,rgb_channel);
|
||||
|
||||
int kk =0;
|
||||
|
||||
for(int r =0;r<=order;r++)
|
||||
for(int g=0;g<=order;g++)
|
||||
for(int b=0;b<=order;b++)
|
||||
if((r + g + b) <=order && (r+g+b) > 0)
|
||||
{
|
||||
for(int i = 0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
Gray.at<float>(i,j)=static_cast<float>(Gray.at<float>(i,j) +
|
||||
static_cast<float>(wei[kk])*pow(rgb_channel[2].at<float>(i,j),r)*pow(rgb_channel[1].at<float>(i,j),g)*
|
||||
pow(rgb_channel[0].at<float>(i,j),b));
|
||||
|
||||
kk=kk+1;
|
||||
}
|
||||
|
||||
double minval, maxval;
|
||||
minMaxLoc(Gray, &minval, &maxval);
|
||||
|
||||
Gray -= minval;
|
||||
Gray /= maxval - minval;
|
||||
}
|
||||
564
3rdparty/opencv-4.5.4/modules/photo/src/cuda/nlm.cu
vendored
Normal file
564
3rdparty/opencv-4.5.4/modules/photo/src/cuda/nlm.cu
vendored
Normal file
@ -0,0 +1,564 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "opencv2/core/cuda/common.hpp"
|
||||
#include "opencv2/core/cuda/vec_traits.hpp"
|
||||
#include "opencv2/core/cuda/vec_math.hpp"
|
||||
#include "opencv2/core/cuda/functional.hpp"
|
||||
#include "opencv2/core/cuda/reduce.hpp"
|
||||
#include "opencv2/core/cuda/border_interpolate.hpp"
|
||||
|
||||
using namespace cv::cuda;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//// Non Local Means Denosing
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
__device__ __forceinline__ float norm2(const float& v) { return v*v; }
|
||||
__device__ __forceinline__ float norm2(const float2& v) { return v.x*v.x + v.y*v.y; }
|
||||
__device__ __forceinline__ float norm2(const float3& v) { return v.x*v.x + v.y*v.y + v.z*v.z; }
|
||||
__device__ __forceinline__ float norm2(const float4& v) { return v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; }
|
||||
|
||||
template<typename T, typename B>
|
||||
__global__ void nlm_kernel(const PtrStep<T> src, PtrStepSz<T> dst, const B b, int search_radius, int block_radius, float noise_mult)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type value_type;
|
||||
|
||||
const int i = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
const int j = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
|
||||
if (j >= dst.cols || i >= dst.rows)
|
||||
return;
|
||||
|
||||
int bsize = search_radius + block_radius;
|
||||
int search_window = 2 * search_radius + 1;
|
||||
float minus_search_window2_inv = -1.f/(search_window * search_window);
|
||||
|
||||
value_type sum1 = VecTraits<value_type>::all(0);
|
||||
float sum2 = 0.f;
|
||||
|
||||
if (j - bsize >= 0 && j + bsize < dst.cols && i - bsize >= 0 && i + bsize < dst.rows)
|
||||
{
|
||||
for(float y = -search_radius; y <= search_radius; ++y)
|
||||
for(float x = -search_radius; x <= search_radius; ++x)
|
||||
{
|
||||
float dist2 = 0;
|
||||
for(float ty = -block_radius; ty <= block_radius; ++ty)
|
||||
for(float tx = -block_radius; tx <= block_radius; ++tx)
|
||||
{
|
||||
value_type bv = saturate_cast<value_type>(src(i + y + ty, j + x + tx));
|
||||
value_type av = saturate_cast<value_type>(src(i + ty, j + tx));
|
||||
|
||||
dist2 += norm2(av - bv);
|
||||
}
|
||||
|
||||
float w = __expf(dist2 * noise_mult + (x * x + y * y) * minus_search_window2_inv);
|
||||
|
||||
/*if (i == 255 && j == 255)
|
||||
printf("%f %f\n", w, dist2 * minus_h2_inv + (x * x + y * y) * minus_search_window2_inv);*/
|
||||
|
||||
sum1 = sum1 + w * saturate_cast<value_type>(src(i + y, j + x));
|
||||
sum2 += w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(float y = -search_radius; y <= search_radius; ++y)
|
||||
for(float x = -search_radius; x <= search_radius; ++x)
|
||||
{
|
||||
float dist2 = 0;
|
||||
for(float ty = -block_radius; ty <= block_radius; ++ty)
|
||||
for(float tx = -block_radius; tx <= block_radius; ++tx)
|
||||
{
|
||||
value_type bv = saturate_cast<value_type>(b.at(i + y + ty, j + x + tx, src));
|
||||
value_type av = saturate_cast<value_type>(b.at(i + ty, j + tx, src));
|
||||
dist2 += norm2(av - bv);
|
||||
}
|
||||
|
||||
float w = __expf(dist2 * noise_mult + (x * x + y * y) * minus_search_window2_inv);
|
||||
|
||||
sum1 = sum1 + w * saturate_cast<value_type>(b.at(i + y, j + x, src));
|
||||
sum2 += w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dst(i, j) = saturate_cast<T>(sum1 / sum2);
|
||||
|
||||
}
|
||||
|
||||
template<typename T, template <typename> class B>
|
||||
void nlm_caller(const PtrStepSzb src, PtrStepSzb dst, int search_radius, int block_radius, float h, cudaStream_t stream)
|
||||
{
|
||||
dim3 block (32, 8);
|
||||
dim3 grid (divUp (src.cols, block.x), divUp (src.rows, block.y));
|
||||
|
||||
B<T> b(src.rows, src.cols);
|
||||
|
||||
int block_window = 2 * block_radius + 1;
|
||||
float minus_h2_inv = -1.f/(h * h * VecTraits<T>::cn);
|
||||
float noise_mult = minus_h2_inv/(block_window * block_window);
|
||||
|
||||
cudaSafeCall( cudaFuncSetCacheConfig (nlm_kernel<T, B<T> >, cudaFuncCachePreferL1) );
|
||||
nlm_kernel<<<grid, block>>>((PtrStepSz<T>)src, (PtrStepSz<T>)dst, b, search_radius, block_radius, noise_mult);
|
||||
cudaSafeCall ( cudaGetLastError () );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void nlm_bruteforce_gpu(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream)
|
||||
{
|
||||
typedef void (*func_t)(const PtrStepSzb src, PtrStepSzb dst, int search_radius, int block_radius, float h, cudaStream_t stream);
|
||||
|
||||
static func_t funcs[] =
|
||||
{
|
||||
nlm_caller<T, BrdConstant>,
|
||||
nlm_caller<T, BrdReplicate>,
|
||||
nlm_caller<T, BrdReflect>,
|
||||
nlm_caller<T, BrdWrap>,
|
||||
nlm_caller<T, BrdReflect101>
|
||||
};
|
||||
funcs[borderMode](src, dst, search_radius, block_radius, h, stream);
|
||||
}
|
||||
|
||||
template void nlm_bruteforce_gpu<uchar>(const PtrStepSzb&, PtrStepSzb, int, int, float, int, cudaStream_t);
|
||||
template void nlm_bruteforce_gpu<uchar2>(const PtrStepSzb&, PtrStepSzb, int, int, float, int, cudaStream_t);
|
||||
template void nlm_bruteforce_gpu<uchar3>(const PtrStepSzb&, PtrStepSzb, int, int, float, int, cudaStream_t);
|
||||
}
|
||||
}}}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//// Non Local Means Denosing (fast approximate version)
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
|
||||
template <int cn> struct Unroll;
|
||||
template <> struct Unroll<1>
|
||||
{
|
||||
template <int BLOCK_SIZE>
|
||||
static __device__ __forceinline__ thrust::tuple<volatile float*, volatile float*> smem_tuple(float* smem)
|
||||
{
|
||||
return cv::cuda::device::smem_tuple(smem, smem + BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ thrust::tuple<float&, float&> tie(float& val1, float& val2)
|
||||
{
|
||||
return thrust::tie(val1, val2);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ const thrust::tuple<plus<float>, plus<float> > op()
|
||||
{
|
||||
plus<float> op;
|
||||
return thrust::make_tuple(op, op);
|
||||
}
|
||||
};
|
||||
template <> struct Unroll<2>
|
||||
{
|
||||
template <int BLOCK_SIZE>
|
||||
static __device__ __forceinline__ thrust::tuple<volatile float*, volatile float*, volatile float*> smem_tuple(float* smem)
|
||||
{
|
||||
return cv::cuda::device::smem_tuple(smem, smem + BLOCK_SIZE, smem + 2 * BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ thrust::tuple<float&, float&, float&> tie(float& val1, float2& val2)
|
||||
{
|
||||
return thrust::tie(val1, val2.x, val2.y);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ const thrust::tuple<plus<float>, plus<float>, plus<float> > op()
|
||||
{
|
||||
plus<float> op;
|
||||
return thrust::make_tuple(op, op, op);
|
||||
}
|
||||
};
|
||||
template <> struct Unroll<3>
|
||||
{
|
||||
template <int BLOCK_SIZE>
|
||||
static __device__ __forceinline__ thrust::tuple<volatile float*, volatile float*, volatile float*, volatile float*> smem_tuple(float* smem)
|
||||
{
|
||||
return cv::cuda::device::smem_tuple(smem, smem + BLOCK_SIZE, smem + 2 * BLOCK_SIZE, smem + 3 * BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ thrust::tuple<float&, float&, float&, float&> tie(float& val1, float3& val2)
|
||||
{
|
||||
return thrust::tie(val1, val2.x, val2.y, val2.z);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ const thrust::tuple<plus<float>, plus<float>, plus<float>, plus<float> > op()
|
||||
{
|
||||
plus<float> op;
|
||||
return thrust::make_tuple(op, op, op, op);
|
||||
}
|
||||
};
|
||||
template <> struct Unroll<4>
|
||||
{
|
||||
template <int BLOCK_SIZE>
|
||||
static __device__ __forceinline__ thrust::tuple<volatile float*, volatile float*, volatile float*, volatile float*, volatile float*> smem_tuple(float* smem)
|
||||
{
|
||||
return cv::cuda::device::smem_tuple(smem, smem + BLOCK_SIZE, smem + 2 * BLOCK_SIZE, smem + 3 * BLOCK_SIZE, smem + 4 * BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ thrust::tuple<float&, float&, float&, float&, float&> tie(float& val1, float4& val2)
|
||||
{
|
||||
return thrust::tie(val1, val2.x, val2.y, val2.z, val2.w);
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ const thrust::tuple<plus<float>, plus<float>, plus<float>, plus<float>, plus<float> > op()
|
||||
{
|
||||
plus<float> op;
|
||||
return thrust::make_tuple(op, op, op, op, op);
|
||||
}
|
||||
};
|
||||
|
||||
__device__ __forceinline__ int calcDist(const uchar& a, const uchar& b) { return (a-b)*(a-b); }
|
||||
__device__ __forceinline__ int calcDist(const uchar2& a, const uchar2& b) { return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); }
|
||||
__device__ __forceinline__ int calcDist(const uchar3& a, const uchar3& b) { return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z); }
|
||||
|
||||
template <class T> struct FastNonLocalMeans
|
||||
{
|
||||
enum
|
||||
{
|
||||
CTA_SIZE = 128,
|
||||
|
||||
TILE_COLS = 128,
|
||||
TILE_ROWS = 32,
|
||||
|
||||
STRIDE = CTA_SIZE
|
||||
};
|
||||
|
||||
struct plus
|
||||
{
|
||||
__device__ __forceinline__ float operator()(float v1, float v2) const { return v1 + v2; }
|
||||
};
|
||||
|
||||
int search_radius;
|
||||
int block_radius;
|
||||
|
||||
int search_window;
|
||||
int block_window;
|
||||
float minus_h2_inv;
|
||||
|
||||
FastNonLocalMeans(int search_window_, int block_window_, float h) : search_radius(search_window_/2), block_radius(block_window_/2),
|
||||
search_window(search_window_), block_window(block_window_), minus_h2_inv(-1.f/(h * h * VecTraits<T>::cn)) {}
|
||||
|
||||
PtrStep<T> src;
|
||||
mutable PtrStepi buffer;
|
||||
|
||||
__device__ __forceinline__ void initSums_BruteForce(int i, int j, int* dist_sums, PtrStepi& col_sums, PtrStepi& up_col_sums) const
|
||||
{
|
||||
for(int index = threadIdx.x; index < search_window * search_window; index += STRIDE)
|
||||
{
|
||||
dist_sums[index] = 0;
|
||||
|
||||
for(int tx = 0; tx < block_window; ++tx)
|
||||
col_sums(tx, index) = 0;
|
||||
|
||||
int y = index / search_window;
|
||||
int x = index - y * search_window;
|
||||
|
||||
int ay = i;
|
||||
int ax = j;
|
||||
|
||||
int by = i + y - search_radius;
|
||||
int bx = j + x - search_radius;
|
||||
|
||||
#if 1
|
||||
for (int tx = -block_radius; tx <= block_radius; ++tx)
|
||||
{
|
||||
int col_sum = 0;
|
||||
for (int ty = -block_radius; ty <= block_radius; ++ty)
|
||||
{
|
||||
int dist = calcDist(src(ay + ty, ax + tx), src(by + ty, bx + tx));
|
||||
|
||||
dist_sums[index] += dist;
|
||||
col_sum += dist;
|
||||
}
|
||||
col_sums(tx + block_radius, index) = col_sum;
|
||||
}
|
||||
#else
|
||||
for (int ty = -block_radius; ty <= block_radius; ++ty)
|
||||
for (int tx = -block_radius; tx <= block_radius; ++tx)
|
||||
{
|
||||
int dist = calcDist(src(ay + ty, ax + tx), src(by + ty, bx + tx));
|
||||
|
||||
dist_sums[index] += dist;
|
||||
col_sums(tx + block_radius, index) += dist;
|
||||
}
|
||||
#endif
|
||||
|
||||
up_col_sums(j, index) = col_sums(block_window - 1, index);
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void shiftRight_FirstRow(int i, int j, int first, int* dist_sums, PtrStepi& col_sums, PtrStepi& up_col_sums) const
|
||||
{
|
||||
for(int index = threadIdx.x; index < search_window * search_window; index += STRIDE)
|
||||
{
|
||||
int y = index / search_window;
|
||||
int x = index - y * search_window;
|
||||
|
||||
int ay = i;
|
||||
int ax = j + block_radius;
|
||||
|
||||
int by = i + y - search_radius;
|
||||
int bx = j + x - search_radius + block_radius;
|
||||
|
||||
int col_sum = 0;
|
||||
|
||||
for (int ty = -block_radius; ty <= block_radius; ++ty)
|
||||
col_sum += calcDist(src(ay + ty, ax), src(by + ty, bx));
|
||||
|
||||
dist_sums[index] += col_sum - col_sums(first, index);
|
||||
|
||||
col_sums(first, index) = col_sum;
|
||||
up_col_sums(j, index) = col_sum;
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void shiftRight_UpSums(int i, int j, int first, int* dist_sums, PtrStepi& col_sums, PtrStepi& up_col_sums) const
|
||||
{
|
||||
int ay = i;
|
||||
int ax = j + block_radius;
|
||||
|
||||
T a_up = src(ay - block_radius - 1, ax);
|
||||
T a_down = src(ay + block_radius, ax);
|
||||
|
||||
for(int index = threadIdx.x; index < search_window * search_window; index += STRIDE)
|
||||
{
|
||||
int y = index / search_window;
|
||||
int x = index - y * search_window;
|
||||
|
||||
int by = i + y - search_radius;
|
||||
int bx = j + x - search_radius + block_radius;
|
||||
|
||||
T b_up = src(by - block_radius - 1, bx);
|
||||
T b_down = src(by + block_radius, bx);
|
||||
|
||||
int col_sum = up_col_sums(j, index) + calcDist(a_down, b_down) - calcDist(a_up, b_up);
|
||||
|
||||
dist_sums[index] += col_sum - col_sums(first, index);
|
||||
col_sums(first, index) = col_sum;
|
||||
up_col_sums(j, index) = col_sum;
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void convolve_window(int i, int j, const int* dist_sums, T& dst) const
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type sum_type;
|
||||
|
||||
float weights_sum = 0;
|
||||
sum_type sum = VecTraits<sum_type>::all(0);
|
||||
|
||||
float bw2_inv = 1.f/(block_window * block_window);
|
||||
|
||||
int sx = j - search_radius;
|
||||
int sy = i - search_radius;
|
||||
|
||||
for(int index = threadIdx.x; index < search_window * search_window; index += STRIDE)
|
||||
{
|
||||
int y = index / search_window;
|
||||
int x = index - y * search_window;
|
||||
|
||||
float avg_dist = dist_sums[index] * bw2_inv;
|
||||
float weight = __expf(avg_dist * minus_h2_inv);
|
||||
weights_sum += weight;
|
||||
|
||||
sum = sum + weight * saturate_cast<sum_type>(src(sy + y, sx + x));
|
||||
}
|
||||
|
||||
__shared__ float cta_buffer[CTA_SIZE * (VecTraits<T>::cn + 1)];
|
||||
|
||||
reduce<CTA_SIZE>(Unroll<VecTraits<T>::cn>::template smem_tuple<CTA_SIZE>(cta_buffer),
|
||||
Unroll<VecTraits<T>::cn>::tie(weights_sum, sum),
|
||||
threadIdx.x,
|
||||
Unroll<VecTraits<T>::cn>::op());
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
dst = saturate_cast<T>(sum / weights_sum);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void operator()(PtrStepSz<T>& dst) const
|
||||
{
|
||||
int tbx = blockIdx.x * TILE_COLS;
|
||||
int tby = blockIdx.y * TILE_ROWS;
|
||||
|
||||
int tex = ::min(tbx + TILE_COLS, dst.cols);
|
||||
int tey = ::min(tby + TILE_ROWS, dst.rows);
|
||||
|
||||
PtrStepi col_sums;
|
||||
col_sums.data = buffer.ptr(dst.cols + blockIdx.x * block_window) + blockIdx.y * search_window * search_window;
|
||||
col_sums.step = buffer.step;
|
||||
|
||||
PtrStepi up_col_sums;
|
||||
up_col_sums.data = buffer.data + blockIdx.y * search_window * search_window;
|
||||
up_col_sums.step = buffer.step;
|
||||
|
||||
extern __shared__ int dist_sums[]; //search_window * search_window
|
||||
|
||||
int first = 0;
|
||||
|
||||
for (int i = tby; i < tey; ++i)
|
||||
for (int j = tbx; j < tex; ++j)
|
||||
{
|
||||
__syncthreads();
|
||||
|
||||
if (j == tbx)
|
||||
{
|
||||
initSums_BruteForce(i, j, dist_sums, col_sums, up_col_sums);
|
||||
first = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i == tby)
|
||||
shiftRight_FirstRow(i, j, first, dist_sums, col_sums, up_col_sums);
|
||||
else
|
||||
shiftRight_UpSums(i, j, first, dist_sums, col_sums, up_col_sums);
|
||||
|
||||
first = (first + 1) % block_window;
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
convolve_window(i, j, dist_sums, dst(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
__global__ void fast_nlm_kernel(const FastNonLocalMeans<T> fnlm, PtrStepSz<T> dst) { fnlm(dst); }
|
||||
|
||||
void nln_fast_get_buffer_size(const PtrStepSzb& src, int search_window, int block_window, int& buffer_cols, int& buffer_rows)
|
||||
{
|
||||
typedef FastNonLocalMeans<uchar> FNLM;
|
||||
dim3 grid(divUp(src.cols, FNLM::TILE_COLS), divUp(src.rows, FNLM::TILE_ROWS));
|
||||
|
||||
buffer_cols = search_window * search_window * grid.y;
|
||||
buffer_rows = src.cols + block_window * grid.x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void nlm_fast_gpu(const PtrStepSzb& src, PtrStepSzb dst, PtrStepi buffer,
|
||||
int search_window, int block_window, float h, cudaStream_t stream)
|
||||
{
|
||||
typedef FastNonLocalMeans<T> FNLM;
|
||||
FNLM fnlm(search_window, block_window, h);
|
||||
|
||||
fnlm.src = (PtrStepSz<T>)src;
|
||||
fnlm.buffer = buffer;
|
||||
|
||||
dim3 block(FNLM::CTA_SIZE, 1);
|
||||
dim3 grid(divUp(src.cols, FNLM::TILE_COLS), divUp(src.rows, FNLM::TILE_ROWS));
|
||||
int smem = search_window * search_window * sizeof(int);
|
||||
|
||||
|
||||
fast_nlm_kernel<<<grid, block, smem>>>(fnlm, (PtrStepSz<T>)dst);
|
||||
cudaSafeCall ( cudaGetLastError () );
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template void nlm_fast_gpu<uchar>(const PtrStepSzb&, PtrStepSzb, PtrStepi, int, int, float, cudaStream_t);
|
||||
template void nlm_fast_gpu<uchar2>(const PtrStepSzb&, PtrStepSzb, PtrStepi, int, int, float, cudaStream_t);
|
||||
template void nlm_fast_gpu<uchar3>(const PtrStepSzb&, PtrStepSzb, PtrStepi, int, int, float, cudaStream_t);
|
||||
|
||||
|
||||
|
||||
__global__ void fnlm_split_kernel(const PtrStepSz<uchar3> lab, PtrStepb l, PtrStep<uchar2> ab)
|
||||
{
|
||||
int x = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
int y = threadIdx.y + blockIdx.y * blockDim.y;
|
||||
|
||||
if (x < lab.cols && y < lab.rows)
|
||||
{
|
||||
uchar3 p = lab(y, x);
|
||||
ab(y,x) = make_uchar2(p.y, p.z);
|
||||
l(y,x) = p.x;
|
||||
}
|
||||
}
|
||||
|
||||
void fnlm_split_channels(const PtrStepSz<uchar3>& lab, PtrStepb l, PtrStep<uchar2> ab, cudaStream_t stream)
|
||||
{
|
||||
dim3 b(32, 8);
|
||||
dim3 g(divUp(lab.cols, b.x), divUp(lab.rows, b.y));
|
||||
|
||||
fnlm_split_kernel<<<g, b>>>(lab, l, ab);
|
||||
cudaSafeCall ( cudaGetLastError () );
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
__global__ void fnlm_merge_kernel(const PtrStepb l, const PtrStep<uchar2> ab, PtrStepSz<uchar3> lab)
|
||||
{
|
||||
int x = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
int y = threadIdx.y + blockIdx.y * blockDim.y;
|
||||
|
||||
if (x < lab.cols && y < lab.rows)
|
||||
{
|
||||
uchar2 p = ab(y, x);
|
||||
lab(y, x) = make_uchar3(l(y, x), p.x, p.y);
|
||||
}
|
||||
}
|
||||
|
||||
void fnlm_merge_channels(const PtrStepb& l, const PtrStep<uchar2>& ab, PtrStepSz<uchar3> lab, cudaStream_t stream)
|
||||
{
|
||||
dim3 b(32, 8);
|
||||
dim3 g(divUp(lab.cols, b.x), divUp(lab.rows, b.y));
|
||||
|
||||
fnlm_merge_kernel<<<g, b>>>(l, ab, lab);
|
||||
cudaSafeCall ( cudaGetLastError () );
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
}
|
||||
}}}
|
||||
153
3rdparty/opencv-4.5.4/modules/photo/src/denoise_tvl1.cpp
vendored
Normal file
153
3rdparty/opencv-4.5.4/modules/photo/src/denoise_tvl1.cpp
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 OpenCV Foundation 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 "precomp.hpp"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#define ABSCLIP(val,threshold) MIN(MAX((val),-(threshold)),(threshold))
|
||||
|
||||
namespace cv{
|
||||
|
||||
class AddFloatToCharScaled{
|
||||
public:
|
||||
AddFloatToCharScaled(double scale):_scale(scale){}
|
||||
inline double operator()(double a,uchar b){
|
||||
return a+_scale*((double)b);
|
||||
}
|
||||
private:
|
||||
double _scale;
|
||||
};
|
||||
|
||||
using std::transform;
|
||||
|
||||
void denoise_TVL1(const std::vector<Mat>& observations,Mat& result, double lambda, int niters){
|
||||
|
||||
CV_Assert(observations.size()>0 && niters>0 && lambda>0);
|
||||
|
||||
const double L2 = 8.0, tau = 0.02, sigma = 1./(L2*tau), theta = 1.0;
|
||||
double clambda = (double)lambda;
|
||||
double s=0;
|
||||
const int workdepth = CV_64F;
|
||||
|
||||
int i, x, y, rows=observations[0].rows, cols=observations[0].cols,count;
|
||||
for(i=1;i<(int)observations.size();i++){
|
||||
CV_Assert(observations[i].rows==rows && observations[i].cols==cols);
|
||||
}
|
||||
|
||||
Mat X, P = Mat::zeros(rows, cols, CV_MAKETYPE(workdepth, 2));
|
||||
observations[0].convertTo(X, workdepth, 1./255);
|
||||
std::vector< Mat_<double> > Rs(observations.size());
|
||||
for(count=0;count<(int)Rs.size();count++){
|
||||
Rs[count]=Mat::zeros(rows,cols,workdepth);
|
||||
}
|
||||
|
||||
for( i = 0; i < niters; i++ )
|
||||
{
|
||||
double currsigma = i == 0 ? 1 + sigma : sigma;
|
||||
|
||||
// P_ = P + sigma*nabla(X)
|
||||
// P(x,y) = P_(x,y)/max(||P(x,y)||,1)
|
||||
for( y = 0; y < rows; y++ )
|
||||
{
|
||||
const double* x_curr = X.ptr<double>(y);
|
||||
const double* x_next = X.ptr<double>(std::min(y+1, rows-1));
|
||||
Point2d* p_curr = P.ptr<Point2d>(y);
|
||||
double dx, dy, m;
|
||||
for( x = 0; x < cols-1; x++ )
|
||||
{
|
||||
dx = (x_curr[x+1] - x_curr[x])*currsigma + p_curr[x].x;
|
||||
dy = (x_next[x] - x_curr[x])*currsigma + p_curr[x].y;
|
||||
m = 1.0/std::max(std::sqrt(dx*dx + dy*dy), 1.0);
|
||||
p_curr[x].x = dx*m;
|
||||
p_curr[x].y = dy*m;
|
||||
}
|
||||
dy = (x_next[x] - x_curr[x])*currsigma + p_curr[x].y;
|
||||
m = 1.0/std::max(std::abs(dy), 1.0);
|
||||
p_curr[x].x = 0.0;
|
||||
p_curr[x].y = dy*m;
|
||||
}
|
||||
|
||||
|
||||
//Rs = clip(Rs + sigma*(X-imgs), -clambda, clambda)
|
||||
for(count=0;count<(int)Rs.size();count++){
|
||||
transform<MatIterator_<double>,MatConstIterator_<uchar>,MatIterator_<double>,AddFloatToCharScaled>(
|
||||
Rs[count].begin(),Rs[count].end(),observations[count].begin<uchar>(),
|
||||
Rs[count].begin(),AddFloatToCharScaled(-sigma/255.0));
|
||||
Rs[count]+=sigma*X;
|
||||
min(Rs[count],clambda,Rs[count]);
|
||||
max(Rs[count],-clambda,Rs[count]);
|
||||
}
|
||||
|
||||
for( y = 0; y < rows; y++ )
|
||||
{
|
||||
double* x_curr = X.ptr<double>(y);
|
||||
const Point2d* p_curr = P.ptr<Point2d>(y);
|
||||
const Point2d* p_prev = P.ptr<Point2d>(std::max(y - 1, 0));
|
||||
|
||||
// X1 = X + tau*(-nablaT(P))
|
||||
x = 0;
|
||||
s=0.0;
|
||||
for(count=0;count<(int)Rs.size();count++){
|
||||
s=s+Rs[count](y,x);
|
||||
}
|
||||
double x_new = x_curr[x] + tau*(p_curr[x].y - p_prev[x].y)-tau*s;
|
||||
// X = X2 + theta*(X2 - X)
|
||||
x_curr[x] = x_new + theta*(x_new - x_curr[x]);
|
||||
|
||||
|
||||
for(x = 1; x < cols; x++ )
|
||||
{
|
||||
s=0.0;
|
||||
for(count=0;count<(int)Rs.size();count++){
|
||||
s+=Rs[count](y,x);
|
||||
}
|
||||
// X1 = X + tau*(-nablaT(P))
|
||||
x_new = x_curr[x] + tau*(p_curr[x].x - p_curr[x-1].x + p_curr[x].y - p_prev[x].y)-tau*s;
|
||||
// X = X2 + theta*(X2 - X)
|
||||
x_curr[x] = x_new + theta*(x_new - x_curr[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.create(X.rows,X.cols,CV_8U);
|
||||
X.convertTo(result, CV_8U, 255);
|
||||
}
|
||||
}
|
||||
441
3rdparty/opencv-4.5.4/modules/photo/src/denoising.cpp
vendored
Normal file
441
3rdparty/opencv-4.5.4/modules/photo/src/denoising.cpp
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective icvers.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 "precomp.hpp"
|
||||
|
||||
#include "fast_nlmeans_denoising_invoker.hpp"
|
||||
#include "fast_nlmeans_multi_denoising_invoker.hpp"
|
||||
#include "fast_nlmeans_denoising_opencl.hpp"
|
||||
|
||||
template<typename ST, typename IT, typename UIT, typename D>
|
||||
static void fastNlMeansDenoising_( const Mat& src, Mat& dst, const std::vector<float>& h,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
int hn = (int)h.size();
|
||||
double granularity = (double)std::max(1., (double)dst.total()/(1 << 17));
|
||||
|
||||
switch (CV_MAT_CN(src.type())) {
|
||||
case 1:
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<ST, IT, UIT, D, int>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
case 2:
|
||||
if (hn == 1)
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, int>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
else
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, Vec2i>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
case 3:
|
||||
if (hn == 1)
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, int>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
else
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, Vec3i>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
case 4:
|
||||
if (hn == 1)
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, int>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
else
|
||||
parallel_for_(cv::Range(0, src.rows),
|
||||
FastNlMeansDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, Vec4i>(
|
||||
src, dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported number of channels! Only 1, 2, 3, and 4 are supported");
|
||||
}
|
||||
}
|
||||
|
||||
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
fastNlMeansDenoising(_src, _dst, std::vector<float>(1, h),
|
||||
templateWindowSize, searchWindowSize);
|
||||
}
|
||||
|
||||
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, const std::vector<float>& h,
|
||||
int templateWindowSize, int searchWindowSize, int normType)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int hn = (int)h.size(), type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
CV_Assert(!_src.empty());
|
||||
CV_Assert(hn == 1 || hn == cn);
|
||||
|
||||
Size src_size = _src.size();
|
||||
CV_OCL_RUN(_src.dims() <= 2 && (_src.isUMat() || _dst.isUMat()) &&
|
||||
src_size.width > 5 && src_size.height > 5, // low accuracy on small sizes
|
||||
ocl_fastNlMeansDenoising(_src, _dst, &h[0], hn,
|
||||
templateWindowSize, searchWindowSize, normType))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src_size, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
switch (normType) {
|
||||
case NORM_L2:
|
||||
switch (depth) {
|
||||
case CV_8U:
|
||||
fastNlMeansDenoising_<uchar, int, unsigned, DistSquared>(src, dst, h,
|
||||
templateWindowSize,
|
||||
searchWindowSize);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported depth! Only CV_8U is supported for NORM_L2");
|
||||
}
|
||||
break;
|
||||
case NORM_L1:
|
||||
switch (depth) {
|
||||
case CV_8U:
|
||||
fastNlMeansDenoising_<uchar, int, unsigned, DistAbs>(src, dst, h,
|
||||
templateWindowSize,
|
||||
searchWindowSize);
|
||||
break;
|
||||
case CV_16U:
|
||||
fastNlMeansDenoising_<ushort, int64, uint64, DistAbs>(src, dst, h,
|
||||
templateWindowSize,
|
||||
searchWindowSize);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported depth! Only CV_8U and CV_16U are supported for NORM_L1");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported norm type! Only NORM_L2 and NORM_L1 are supported");
|
||||
}
|
||||
}
|
||||
|
||||
void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
|
||||
float h, float hForColorComponents,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
Size src_size = _src.size();
|
||||
if (type != CV_8UC3 && type != CV_8UC4)
|
||||
{
|
||||
CV_Error(Error::StsBadArg, "Type of input image should be CV_8UC3 or CV_8UC4!");
|
||||
return;
|
||||
}
|
||||
|
||||
CV_OCL_RUN(_src.dims() <= 2 && (_dst.isUMat() || _src.isUMat()) &&
|
||||
src_size.width > 5 && src_size.height > 5, // low accuracy on small sizes
|
||||
ocl_fastNlMeansDenoisingColored(_src, _dst, h, hForColorComponents,
|
||||
templateWindowSize, searchWindowSize))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src_size, type);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Mat src_lab;
|
||||
cvtColor(src, src_lab, COLOR_LBGR2Lab);
|
||||
|
||||
Mat l(src_size, CV_MAKE_TYPE(depth, 1));
|
||||
Mat ab(src_size, CV_MAKE_TYPE(depth, 2));
|
||||
Mat l_ab[] = { l, ab };
|
||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
||||
mixChannels(&src_lab, 1, l_ab, 2, from_to, 3);
|
||||
|
||||
fastNlMeansDenoising(l, l, h, templateWindowSize, searchWindowSize);
|
||||
fastNlMeansDenoising(ab, ab, hForColorComponents, templateWindowSize, searchWindowSize);
|
||||
|
||||
Mat l_ab_denoised[] = { l, ab };
|
||||
Mat dst_lab(src_size, CV_MAKE_TYPE(depth, 3));
|
||||
mixChannels(l_ab_denoised, 2, &dst_lab, 1, from_to, 3);
|
||||
|
||||
cvtColor(dst_lab, dst, COLOR_Lab2LBGR, cn);
|
||||
}
|
||||
|
||||
static void fastNlMeansDenoisingMultiCheckPreconditions(
|
||||
const std::vector<Mat>& srcImgs,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
int src_imgs_size = static_cast<int>(srcImgs.size());
|
||||
if (src_imgs_size == 0)
|
||||
{
|
||||
CV_Error(Error::StsBadArg, "Input images vector should not be empty!");
|
||||
}
|
||||
|
||||
if (temporalWindowSize % 2 == 0 ||
|
||||
searchWindowSize % 2 == 0 ||
|
||||
templateWindowSize % 2 == 0) {
|
||||
CV_Error(Error::StsBadArg, "All windows sizes should be odd!");
|
||||
}
|
||||
|
||||
int temporalWindowHalfSize = temporalWindowSize / 2;
|
||||
if (imgToDenoiseIndex - temporalWindowHalfSize < 0 ||
|
||||
imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size)
|
||||
{
|
||||
CV_Error(Error::StsBadArg,
|
||||
"imgToDenoiseIndex and temporalWindowSize "
|
||||
"should be chosen corresponding srcImgs size!");
|
||||
}
|
||||
|
||||
for (int i = 1; i < src_imgs_size; i++)
|
||||
if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type())
|
||||
{
|
||||
CV_Error(Error::StsBadArg, "Input images should have the same size and type!");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ST, typename IT, typename UIT, typename D>
|
||||
static void fastNlMeansDenoisingMulti_( const std::vector<Mat>& srcImgs, Mat& dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
const std::vector<float>& h,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
int hn = (int)h.size();
|
||||
double granularity = (double)std::max(1., (double)dst.total()/(1 << 16));
|
||||
|
||||
switch (srcImgs[0].type())
|
||||
{
|
||||
case CV_8U:
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<uchar, IT, UIT, D, int>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
case CV_8UC2:
|
||||
if (hn == 1)
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, int>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
else
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, Vec2i>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
case CV_8UC3:
|
||||
if (hn == 1)
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, int>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
else
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, Vec3i>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
case CV_8UC4:
|
||||
if (hn == 1)
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, int>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
else
|
||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||
FastNlMeansMultiDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, Vec4i>(
|
||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||
dst, templateWindowSize, searchWindowSize, &h[0]),
|
||||
granularity);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported image format! Only CV_8U, CV_8UC2, CV_8UC3 and CV_8UC4 are supported");
|
||||
}
|
||||
}
|
||||
|
||||
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h, int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
fastNlMeansDenoisingMulti(_srcImgs, _dst, imgToDenoiseIndex, temporalWindowSize,
|
||||
std::vector<float>(1, h), templateWindowSize, searchWindowSize);
|
||||
}
|
||||
|
||||
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
const std::vector<float>& h,
|
||||
int templateWindowSize, int searchWindowSize, int normType)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> srcImgs;
|
||||
_srcImgs.getMatVector(srcImgs);
|
||||
|
||||
fastNlMeansDenoisingMultiCheckPreconditions(
|
||||
srcImgs, imgToDenoiseIndex,
|
||||
temporalWindowSize, templateWindowSize, searchWindowSize);
|
||||
|
||||
int hn = (int)h.size();
|
||||
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
CV_Assert(hn == 1 || hn == cn);
|
||||
|
||||
_dst.create(srcImgs[0].size(), srcImgs[0].type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
switch (normType) {
|
||||
case NORM_L2:
|
||||
switch (depth) {
|
||||
case CV_8U:
|
||||
fastNlMeansDenoisingMulti_<uchar, int, unsigned,
|
||||
DistSquared>(srcImgs, dst,
|
||||
imgToDenoiseIndex, temporalWindowSize,
|
||||
h,
|
||||
templateWindowSize, searchWindowSize);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported depth! Only CV_8U is supported for NORM_L2");
|
||||
}
|
||||
break;
|
||||
case NORM_L1:
|
||||
switch (depth) {
|
||||
case CV_8U:
|
||||
fastNlMeansDenoisingMulti_<uchar, int, unsigned,
|
||||
DistAbs>(srcImgs, dst,
|
||||
imgToDenoiseIndex, temporalWindowSize,
|
||||
h,
|
||||
templateWindowSize, searchWindowSize);
|
||||
break;
|
||||
case CV_16U:
|
||||
fastNlMeansDenoisingMulti_<ushort, int64, uint64,
|
||||
DistAbs>(srcImgs, dst,
|
||||
imgToDenoiseIndex, temporalWindowSize,
|
||||
h,
|
||||
templateWindowSize, searchWindowSize);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported depth! Only CV_8U and CV_16U are supported for NORM_L1");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Unsupported norm type! Only NORM_L2 and NORM_L1 are supported");
|
||||
}
|
||||
}
|
||||
|
||||
void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h, float hForColorComponents,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> srcImgs;
|
||||
_srcImgs.getMatVector(srcImgs);
|
||||
|
||||
fastNlMeansDenoisingMultiCheckPreconditions(
|
||||
srcImgs, imgToDenoiseIndex,
|
||||
temporalWindowSize, templateWindowSize, searchWindowSize);
|
||||
|
||||
_dst.create(srcImgs[0].size(), srcImgs[0].type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type);
|
||||
int src_imgs_size = static_cast<int>(srcImgs.size());
|
||||
|
||||
if (type != CV_8UC3)
|
||||
{
|
||||
CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!");
|
||||
return;
|
||||
}
|
||||
|
||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
||||
|
||||
// TODO convert only required images
|
||||
std::vector<Mat> src_lab(src_imgs_size);
|
||||
std::vector<Mat> l(src_imgs_size);
|
||||
std::vector<Mat> ab(src_imgs_size);
|
||||
for (int i = 0; i < src_imgs_size; i++)
|
||||
{
|
||||
src_lab[i] = Mat::zeros(srcImgs[0].size(), type);
|
||||
l[i] = Mat::zeros(srcImgs[0].size(), CV_MAKE_TYPE(depth, 1));
|
||||
ab[i] = Mat::zeros(srcImgs[0].size(), CV_MAKE_TYPE(depth, 2));
|
||||
cvtColor(srcImgs[i], src_lab[i], COLOR_LBGR2Lab);
|
||||
|
||||
Mat l_ab[] = { l[i], ab[i] };
|
||||
mixChannels(&src_lab[i], 1, l_ab, 2, from_to, 3);
|
||||
}
|
||||
|
||||
Mat dst_l;
|
||||
Mat dst_ab;
|
||||
|
||||
fastNlMeansDenoisingMulti(
|
||||
l, dst_l, imgToDenoiseIndex, temporalWindowSize,
|
||||
h, templateWindowSize, searchWindowSize);
|
||||
|
||||
fastNlMeansDenoisingMulti(
|
||||
ab, dst_ab, imgToDenoiseIndex, temporalWindowSize,
|
||||
hForColorComponents, templateWindowSize, searchWindowSize);
|
||||
|
||||
Mat l_ab_denoised[] = { dst_l, dst_ab };
|
||||
Mat dst_lab(srcImgs[0].size(), srcImgs[0].type());
|
||||
mixChannels(l_ab_denoised, 2, &dst_lab, 1, from_to, 3);
|
||||
|
||||
cvtColor(dst_lab, dst, COLOR_Lab2LBGR);
|
||||
}
|
||||
170
3rdparty/opencv-4.5.4/modules/photo/src/denoising.cuda.cpp
vendored
Normal file
170
3rdparty/opencv-4.5.4/modules/photo/src/denoising.cuda.cpp
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
|
||||
#include "opencv2/photo/cuda.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCV_CUDAARITHM
|
||||
# include "opencv2/cudaarithm.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_CUDAIMGPROC
|
||||
# include "opencv2/cudaimgproc.hpp"
|
||||
#endif
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
|
||||
#if !defined (HAVE_CUDA) || !defined(HAVE_OPENCV_CUDAARITHM) || !defined(HAVE_OPENCV_CUDAIMGPROC)
|
||||
|
||||
void cv::cuda::nonLocalMeans(InputArray, OutputArray, float, int, int, int, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::fastNlMeansDenoising(InputArray, OutputArray, float, int, int, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::fastNlMeansDenoisingColored(InputArray, OutputArray, float, float, int, int, Stream&) { throw_no_cuda(); }
|
||||
|
||||
#else
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//// Non Local Means Denosing (brute force)
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template<typename T>
|
||||
void nlm_bruteforce_gpu(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::cuda::nonLocalMeans(InputArray _src, OutputArray _dst, float h, int search_window, int block_window, int borderMode, Stream& stream)
|
||||
{
|
||||
using cv::cuda::device::imgproc::nlm_bruteforce_gpu;
|
||||
typedef void (*func_t)(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream);
|
||||
|
||||
static const func_t funcs[4] = { nlm_bruteforce_gpu<uchar>, nlm_bruteforce_gpu<uchar2>, nlm_bruteforce_gpu<uchar3>, 0/*nlm_bruteforce_gpu<uchar4>,*/ };
|
||||
|
||||
const GpuMat src = _src.getGpuMat();
|
||||
|
||||
CV_Assert(src.type() == CV_8U || src.type() == CV_8UC2 || src.type() == CV_8UC3);
|
||||
|
||||
const func_t func = funcs[src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
int b = borderMode;
|
||||
CV_Assert(b == BORDER_REFLECT101 || b == BORDER_REPLICATE || b == BORDER_CONSTANT || b == BORDER_REFLECT || b == BORDER_WRAP);
|
||||
|
||||
_dst.create(src.size(), src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
func(src, dst, search_window/2, block_window/2, h, borderMode, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
void nln_fast_get_buffer_size(const PtrStepSzb& src, int search_window, int block_window, int& buffer_cols, int& buffer_rows);
|
||||
|
||||
template<typename T>
|
||||
void nlm_fast_gpu(const PtrStepSzb& src, PtrStepSzb dst, PtrStepi buffer,
|
||||
int search_window, int block_window, float h, cudaStream_t stream);
|
||||
|
||||
void fnlm_split_channels(const PtrStepSz<uchar3>& lab, PtrStepb l, PtrStep<uchar2> ab, cudaStream_t stream);
|
||||
void fnlm_merge_channels(const PtrStepb& l, const PtrStep<uchar2>& ab, PtrStepSz<uchar3> lab, cudaStream_t stream);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::cuda::fastNlMeansDenoising(InputArray _src, OutputArray _dst, float h, int search_window, int block_window, Stream& stream)
|
||||
{
|
||||
const GpuMat src = _src.getGpuMat();
|
||||
|
||||
CV_Assert(src.depth() == CV_8U && src.channels() < 4);
|
||||
|
||||
int border_size = search_window/2 + block_window/2;
|
||||
Size esize = src.size() + Size(border_size, border_size) * 2;
|
||||
|
||||
BufferPool pool(stream);
|
||||
|
||||
GpuMat extended_src = pool.getBuffer(esize, src.type());
|
||||
cv::cuda::copyMakeBorder(src, extended_src, border_size, border_size, border_size, border_size, cv::BORDER_DEFAULT, Scalar(), stream);
|
||||
GpuMat src_hdr = extended_src(Rect(Point2i(border_size, border_size), src.size()));
|
||||
|
||||
int bcols, brows;
|
||||
device::imgproc::nln_fast_get_buffer_size(src_hdr, search_window, block_window, bcols, brows);
|
||||
GpuMat buffer = pool.getBuffer(brows, bcols, CV_32S);
|
||||
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
typedef void (*nlm_fast_t)(const PtrStepSzb&, PtrStepSzb, PtrStepi, int, int, float, cudaStream_t);
|
||||
static const nlm_fast_t funcs[] = { nlm_fast_gpu<uchar>, nlm_fast_gpu<uchar2>, nlm_fast_gpu<uchar3>, 0};
|
||||
|
||||
_dst.create(src.size(), src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
funcs[src.channels()-1](src_hdr, dst, buffer, search_window, block_window, h, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
void cv::cuda::fastNlMeansDenoisingColored(InputArray _src, OutputArray _dst, float h_luminance, float h_color, int search_window, int block_window, Stream& stream)
|
||||
{
|
||||
const GpuMat src = _src.getGpuMat();
|
||||
|
||||
CV_Assert(src.type() == CV_8UC3);
|
||||
|
||||
BufferPool pool(stream);
|
||||
|
||||
GpuMat lab = pool.getBuffer(src.size(), src.type());
|
||||
cv::cuda::cvtColor(src, lab, cv::COLOR_BGR2Lab, 0, stream);
|
||||
|
||||
GpuMat l = pool.getBuffer(src.size(), CV_8U);
|
||||
GpuMat ab = pool.getBuffer(src.size(), CV_8UC2);
|
||||
device::imgproc::fnlm_split_channels(lab, l, ab, StreamAccessor::getStream(stream));
|
||||
|
||||
fastNlMeansDenoising(l, l, h_luminance, search_window, block_window, stream);
|
||||
fastNlMeansDenoising(ab, ab, h_color, search_window, block_window, stream);
|
||||
|
||||
device::imgproc::fnlm_merge_channels(l, ab, lab, StreamAccessor::getStream(stream));
|
||||
cv::cuda::cvtColor(lab, _dst, cv::COLOR_Lab2BGR, 0, stream);
|
||||
}
|
||||
|
||||
#endif
|
||||
321
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_denoising_invoker.hpp
vendored
Normal file
321
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_denoising_invoker.hpp
vendored
Normal file
@ -0,0 +1,321 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective icvers.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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*/
|
||||
|
||||
#ifndef __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_HPP__
|
||||
#define __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_HPP__
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <limits>
|
||||
|
||||
#include "fast_nlmeans_denoising_invoker_commons.hpp"
|
||||
#include "arrays.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
struct FastNlMeansDenoisingInvoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst,
|
||||
int template_window_size, int search_window_size, const float *h);
|
||||
|
||||
void operator() (const Range& range) const CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
void operator= (const FastNlMeansDenoisingInvoker&);
|
||||
|
||||
const Mat& src_;
|
||||
Mat& dst_;
|
||||
|
||||
Mat extended_src_;
|
||||
int border_size_;
|
||||
|
||||
int template_window_size_;
|
||||
int search_window_size_;
|
||||
|
||||
int template_window_half_size_;
|
||||
int search_window_half_size_;
|
||||
|
||||
typename pixelInfo<WT>::sampleType fixed_point_mult_;
|
||||
int almost_template_window_size_sq_bin_shift_;
|
||||
std::vector<WT> almost_dist2weight_;
|
||||
|
||||
void calcDistSumsForFirstElementInRow(
|
||||
int i, Array2d<int>& dist_sums,
|
||||
Array3d<int>& col_dist_sums,
|
||||
Array3d<int>& up_col_dist_sums) const;
|
||||
|
||||
void calcDistSumsForElementInFirstRow(
|
||||
int i, int j, int first_col_num,
|
||||
Array2d<int>& dist_sums,
|
||||
Array3d<int>& col_dist_sums,
|
||||
Array3d<int>& up_col_dist_sums) const;
|
||||
};
|
||||
|
||||
inline int getNearestPowerOf2(int value)
|
||||
{
|
||||
int p = 0;
|
||||
while( 1 << p < value)
|
||||
++p;
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
FastNlMeansDenoisingInvoker<T, IT, UIT, D, WT>::FastNlMeansDenoisingInvoker(
|
||||
const Mat& src, Mat& dst,
|
||||
int template_window_size,
|
||||
int search_window_size,
|
||||
const float *h) :
|
||||
src_(src), dst_(dst)
|
||||
{
|
||||
CV_Assert(src.channels() == pixelInfo<T>::channels);
|
||||
|
||||
template_window_half_size_ = template_window_size / 2;
|
||||
search_window_half_size_ = search_window_size / 2;
|
||||
template_window_size_ = template_window_half_size_ * 2 + 1;
|
||||
search_window_size_ = search_window_half_size_ * 2 + 1;
|
||||
|
||||
border_size_ = search_window_half_size_ + template_window_half_size_;
|
||||
copyMakeBorder(src_, extended_src_, border_size_, border_size_, border_size_, border_size_, BORDER_DEFAULT);
|
||||
|
||||
const IT max_estimate_sum_value =
|
||||
(IT)search_window_size_ * (IT)search_window_size_ * (IT)pixelInfo<T>::sampleMax();
|
||||
fixed_point_mult_ = (int)std::min<IT>(std::numeric_limits<IT>::max() / max_estimate_sum_value,
|
||||
pixelInfo<WT>::sampleMax());
|
||||
|
||||
// precalc weight for every possible l2 dist between blocks
|
||||
// additional optimization of precalced weights to replace division(averaging) by binary shift
|
||||
CV_Assert(template_window_size_ <= 46340); // sqrt(INT_MAX)
|
||||
int template_window_size_sq = template_window_size_ * template_window_size_;
|
||||
almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(template_window_size_sq);
|
||||
double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq;
|
||||
|
||||
int max_dist = D::template maxDist<T>();
|
||||
int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1);
|
||||
almost_dist2weight_.resize(almost_max_dist);
|
||||
|
||||
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++)
|
||||
{
|
||||
double dist = almost_dist * almost_dist2actual_dist_multiplier;
|
||||
almost_dist2weight_[almost_dist] =
|
||||
D::template calcWeight<T, WT>(dist, h, fixed_point_mult_);
|
||||
}
|
||||
|
||||
// additional optimization init end
|
||||
if (dst_.empty())
|
||||
dst_ = Mat::zeros(src_.size(), src_.type());
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
void FastNlMeansDenoisingInvoker<T, IT, UIT, D, WT>::operator() (const Range& range) const
|
||||
{
|
||||
int row_from = range.start;
|
||||
int row_to = range.end - 1;
|
||||
|
||||
// sums of cols anf rows for current pixel p
|
||||
Array2d<int> dist_sums(search_window_size_, search_window_size_);
|
||||
|
||||
// for lazy calc optimization (sum of cols for current pixel)
|
||||
Array3d<int> col_dist_sums(template_window_size_, search_window_size_, search_window_size_);
|
||||
|
||||
int first_col_num = -1;
|
||||
// last elements of column sum (for each element in row)
|
||||
Array3d<int> up_col_dist_sums(src_.cols, search_window_size_, search_window_size_);
|
||||
|
||||
for (int i = row_from; i <= row_to; i++)
|
||||
{
|
||||
for (int j = 0; j < src_.cols; j++)
|
||||
{
|
||||
int search_window_y = i - search_window_half_size_;
|
||||
int search_window_x = j - search_window_half_size_;
|
||||
|
||||
// calc dist_sums
|
||||
if (j == 0)
|
||||
{
|
||||
calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums);
|
||||
first_col_num = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calc cur dist_sums using previous dist_sums
|
||||
if (i == row_from)
|
||||
{
|
||||
calcDistSumsForElementInFirstRow(i, j, first_col_num,
|
||||
dist_sums, col_dist_sums, up_col_dist_sums);
|
||||
}
|
||||
else
|
||||
{
|
||||
int ay = border_size_ + i;
|
||||
int ax = border_size_ + j + template_window_half_size_;
|
||||
|
||||
int start_by = border_size_ + i - search_window_half_size_;
|
||||
int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
||||
|
||||
T a_up = extended_src_.at<T>(ay - template_window_half_size_ - 1, ax);
|
||||
T a_down = extended_src_.at<T>(ay + template_window_half_size_, ax);
|
||||
|
||||
// copy class member to local variable for optimization
|
||||
int search_window_size = search_window_size_;
|
||||
|
||||
for (int y = 0; y < search_window_size; y++)
|
||||
{
|
||||
int * dist_sums_row = dist_sums.row_ptr(y);
|
||||
int * col_dist_sums_row = col_dist_sums.row_ptr(first_col_num, y);
|
||||
int * up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y);
|
||||
|
||||
const T * b_up_ptr = extended_src_.ptr<T>(start_by - template_window_half_size_ - 1 + y);
|
||||
const T * b_down_ptr = extended_src_.ptr<T>(start_by + template_window_half_size_ + y);
|
||||
|
||||
// MSVC 2015 generates unaligned destination for "movaps" instruction for 32-bit builds
|
||||
#if defined _MSC_VER && _MSC_VER == 1900 && !defined _WIN64
|
||||
#pragma loop(no_vector)
|
||||
#endif
|
||||
for (int x = 0; x < search_window_size; x++)
|
||||
{
|
||||
// remove from current pixel sum column sum with index "first_col_num"
|
||||
dist_sums_row[x] -= col_dist_sums_row[x];
|
||||
|
||||
int bx = start_bx + x;
|
||||
col_dist_sums_row[x] = up_col_dist_sums_row[x] + D::template calcUpDownDist<T>(a_up, a_down, b_up_ptr[bx], b_down_ptr[bx]);
|
||||
|
||||
dist_sums_row[x] += col_dist_sums_row[x];
|
||||
up_col_dist_sums_row[x] = col_dist_sums_row[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
first_col_num = (first_col_num + 1) % template_window_size_;
|
||||
}
|
||||
|
||||
// calc weights
|
||||
IT estimation[pixelInfo<T>::channels], weights_sum[pixelInfo<WT>::channels];
|
||||
for (int channel_num = 0; channel_num < pixelInfo<T>::channels; channel_num++)
|
||||
estimation[channel_num] = 0;
|
||||
for (int channel_num = 0; channel_num < pixelInfo<WT>::channels; channel_num++)
|
||||
weights_sum[channel_num] = 0;
|
||||
|
||||
for (int y = 0; y < search_window_size_; y++)
|
||||
{
|
||||
const T* cur_row_ptr = extended_src_.ptr<T>(border_size_ + search_window_y + y);
|
||||
int* dist_sums_row = dist_sums.row_ptr(y);
|
||||
for (int x = 0; x < search_window_size_; x++)
|
||||
{
|
||||
int almostAvgDist = dist_sums_row[x] >> almost_template_window_size_sq_bin_shift_;
|
||||
WT weight = almost_dist2weight_[almostAvgDist];
|
||||
T p = cur_row_ptr[border_size_ + search_window_x + x];
|
||||
incWithWeight<T, IT, WT>(estimation, weights_sum, weight, p);
|
||||
}
|
||||
}
|
||||
|
||||
divByWeightsSum<IT, UIT, pixelInfo<T>::channels, pixelInfo<WT>::channels>(estimation,
|
||||
weights_sum);
|
||||
dst_.at<T>(i,j) = saturateCastFromArray<T, IT>(estimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
inline void FastNlMeansDenoisingInvoker<T, IT, UIT, D, WT>::calcDistSumsForFirstElementInRow(
|
||||
int i,
|
||||
Array2d<int>& dist_sums,
|
||||
Array3d<int>& col_dist_sums,
|
||||
Array3d<int>& up_col_dist_sums) const
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
for (int y = 0; y < search_window_size_; y++)
|
||||
for (int x = 0; x < search_window_size_; x++)
|
||||
{
|
||||
dist_sums[y][x] = 0;
|
||||
for (int tx = 0; tx < template_window_size_; tx++)
|
||||
col_dist_sums[tx][y][x] = 0;
|
||||
|
||||
int start_y = i + y - search_window_half_size_;
|
||||
int start_x = j + x - search_window_half_size_;
|
||||
|
||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
|
||||
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++)
|
||||
{
|
||||
int dist = D::template calcDist<T>(extended_src_,
|
||||
border_size_ + i + ty, border_size_ + j + tx,
|
||||
border_size_ + start_y + ty, border_size_ + start_x + tx);
|
||||
|
||||
dist_sums[y][x] += dist;
|
||||
col_dist_sums[tx + template_window_half_size_][y][x] += dist;
|
||||
}
|
||||
|
||||
up_col_dist_sums[j][y][x] = col_dist_sums[template_window_size_ - 1][y][x];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
inline void FastNlMeansDenoisingInvoker<T, IT, UIT, D, WT>::calcDistSumsForElementInFirstRow(
|
||||
int i, int j, int first_col_num,
|
||||
Array2d<int>& dist_sums,
|
||||
Array3d<int>& col_dist_sums,
|
||||
Array3d<int>& up_col_dist_sums) const
|
||||
{
|
||||
int ay = border_size_ + i;
|
||||
int ax = border_size_ + j + template_window_half_size_;
|
||||
|
||||
int start_by = border_size_ + i - search_window_half_size_;
|
||||
int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
||||
|
||||
int new_last_col_num = first_col_num;
|
||||
|
||||
for (int y = 0; y < search_window_size_; y++)
|
||||
for (int x = 0; x < search_window_size_; x++)
|
||||
{
|
||||
dist_sums[y][x] -= col_dist_sums[first_col_num][y][x];
|
||||
|
||||
col_dist_sums[new_last_col_num][y][x] = 0;
|
||||
int by = start_by + y;
|
||||
int bx = start_bx + x;
|
||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
|
||||
col_dist_sums[new_last_col_num][y][x] += D::template calcDist<T>(extended_src_, ay + ty, ax, by + ty, bx);
|
||||
|
||||
dist_sums[y][x] += col_dist_sums[new_last_col_num][y][x];
|
||||
up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
489
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp
vendored
Normal file
489
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp
vendored
Normal file
@ -0,0 +1,489 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective icvers.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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*/
|
||||
|
||||
#ifndef __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__
|
||||
#define __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__
|
||||
|
||||
using namespace cv;
|
||||
|
||||
// std::isnan is a part of C++11 and it is not supported in MSVS2010/2012
|
||||
#if defined _MSC_VER && _MSC_VER < 1800 /* MSVC 2013 */
|
||||
#include <float.h>
|
||||
namespace std {
|
||||
template <typename T> bool isnan(T value) { return _isnan(value) != 0; }
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T> struct pixelInfo_
|
||||
{
|
||||
static const int channels = 1;
|
||||
typedef T sampleType;
|
||||
};
|
||||
|
||||
template <typename ET, int n> struct pixelInfo_<Vec<ET, n> >
|
||||
{
|
||||
static const int channels = n;
|
||||
typedef ET sampleType;
|
||||
};
|
||||
|
||||
template <typename T> struct pixelInfo: public pixelInfo_<T>
|
||||
{
|
||||
typedef typename pixelInfo_<T>::sampleType sampleType;
|
||||
|
||||
static inline sampleType sampleMax()
|
||||
{
|
||||
return std::numeric_limits<sampleType>::max();
|
||||
}
|
||||
|
||||
static inline sampleType sampleMin()
|
||||
{
|
||||
return std::numeric_limits<sampleType>::min();
|
||||
}
|
||||
|
||||
static inline size_t sampleBytes()
|
||||
{
|
||||
return sizeof(sampleType);
|
||||
}
|
||||
|
||||
static inline size_t sampleBits()
|
||||
{
|
||||
return 8*sampleBytes();
|
||||
}
|
||||
};
|
||||
|
||||
class DistAbs
|
||||
{
|
||||
template <typename T> struct calcDist_
|
||||
{
|
||||
static inline int f(const T a, const T b)
|
||||
{
|
||||
return std::abs((int)(a-b));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET> struct calcDist_<Vec<ET, 2> >
|
||||
{
|
||||
static inline int f(const Vec<ET, 2> a, const Vec<ET, 2> b)
|
||||
{
|
||||
return std::abs((int)(a[0]-b[0])) + std::abs((int)(a[1]-b[1]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET> struct calcDist_<Vec<ET, 3> >
|
||||
{
|
||||
static inline int f(const Vec<ET, 3> a, const Vec<ET, 3> b)
|
||||
{
|
||||
return
|
||||
std::abs((int)(a[0]-b[0])) +
|
||||
std::abs((int)(a[1]-b[1])) +
|
||||
std::abs((int)(a[2]-b[2]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET> struct calcDist_<Vec<ET, 4> >
|
||||
{
|
||||
static inline int f(const Vec<ET, 4> a, const Vec<ET, 4> b)
|
||||
{
|
||||
return
|
||||
std::abs((int)(a[0]-b[0])) +
|
||||
std::abs((int)(a[1]-b[1])) +
|
||||
std::abs((int)(a[2]-b[2])) +
|
||||
std::abs((int)(a[3]-b[3]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename WT> struct calcWeight_
|
||||
{
|
||||
static inline WT f(double dist, const float *h, WT fixed_point_mult)
|
||||
{
|
||||
double w = std::exp(-dist*dist / (h[0]*h[0] * pixelInfo<T>::channels));
|
||||
if (std::isnan(w)) w = 1.0; // Handle h = 0.0
|
||||
|
||||
static const double WEIGHT_THRESHOLD = 0.001;
|
||||
WT weight = (WT)cvRound(fixed_point_mult * w);
|
||||
if (weight < WEIGHT_THRESHOLD * fixed_point_mult) weight = 0;
|
||||
|
||||
return weight;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename ET, int n> struct calcWeight_<T, Vec<ET, n> >
|
||||
{
|
||||
static inline Vec<ET, n> f(double dist, const float *h, ET fixed_point_mult)
|
||||
{
|
||||
Vec<ET, n> res;
|
||||
for (int i=0; i<n; i++)
|
||||
res[i] = calcWeight<T, ET>(dist, &h[i], fixed_point_mult);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename T> static inline int calcDist(const T a, const T b)
|
||||
{
|
||||
return calcDist_<T>::f(a, b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)
|
||||
{
|
||||
const T a = m.at<T>(i1, j1);
|
||||
const T b = m.at<T>(i2, j2);
|
||||
return calcDist<T>(a,b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
|
||||
{
|
||||
return calcDist<T>(a_down, b_down) - calcDist<T>(a_up, b_up);
|
||||
};
|
||||
|
||||
template <typename T, typename WT>
|
||||
static inline WT calcWeight(double dist, const float *h,
|
||||
typename pixelInfo<WT>::sampleType fixed_point_mult)
|
||||
{
|
||||
return calcWeight_<T, WT>::f(dist, h, fixed_point_mult);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int maxDist()
|
||||
{
|
||||
return (int)pixelInfo<T>::sampleMax() * pixelInfo<T>::channels;
|
||||
}
|
||||
};
|
||||
|
||||
class DistSquared
|
||||
{
|
||||
template <typename T> struct calcDist_
|
||||
{
|
||||
static inline int f(const T a, const T b)
|
||||
{
|
||||
return (int)(a-b) * (int)(a-b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET> struct calcDist_<Vec<ET, 2> >
|
||||
{
|
||||
static inline int f(const Vec<ET, 2> a, const Vec<ET, 2> b)
|
||||
{
|
||||
return (int)(a[0]-b[0])*(int)(a[0]-b[0]) + (int)(a[1]-b[1])*(int)(a[1]-b[1]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET> struct calcDist_<Vec<ET, 3> >
|
||||
{
|
||||
static inline int f(const Vec<ET, 3> a, const Vec<ET, 3> b)
|
||||
{
|
||||
return
|
||||
(int)(a[0]-b[0])*(int)(a[0]-b[0]) +
|
||||
(int)(a[1]-b[1])*(int)(a[1]-b[1]) +
|
||||
(int)(a[2]-b[2])*(int)(a[2]-b[2]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET> struct calcDist_<Vec<ET, 4> >
|
||||
{
|
||||
static inline int f(const Vec<ET, 4> a, const Vec<ET, 4> b)
|
||||
{
|
||||
return
|
||||
(int)(a[0]-b[0])*(int)(a[0]-b[0]) +
|
||||
(int)(a[1]-b[1])*(int)(a[1]-b[1]) +
|
||||
(int)(a[2]-b[2])*(int)(a[2]-b[2]) +
|
||||
(int)(a[3]-b[3])*(int)(a[3]-b[3]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct calcUpDownDist_
|
||||
{
|
||||
static inline int f(T a_up, T a_down, T b_up, T b_down)
|
||||
{
|
||||
int A = a_down - b_down;
|
||||
int B = a_up - b_up;
|
||||
return (A-B)*(A+B);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, int n> struct calcUpDownDist_<Vec<ET, n> >
|
||||
{
|
||||
private:
|
||||
typedef Vec<ET, n> T;
|
||||
public:
|
||||
static inline int f(T a_up, T a_down, T b_up, T b_down)
|
||||
{
|
||||
return calcDist<T>(a_down, b_down) - calcDist<T>(a_up, b_up);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename WT> struct calcWeight_
|
||||
{
|
||||
static inline WT f(double dist, const float *h, WT fixed_point_mult)
|
||||
{
|
||||
double w = std::exp(-dist / (h[0]*h[0] * pixelInfo<T>::channels));
|
||||
if (std::isnan(w)) w = 1.0; // Handle h = 0.0
|
||||
|
||||
static const double WEIGHT_THRESHOLD = 0.001;
|
||||
WT weight = (WT)cvRound(fixed_point_mult * w);
|
||||
if (weight < WEIGHT_THRESHOLD * fixed_point_mult) weight = 0;
|
||||
|
||||
return weight;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename ET, int n> struct calcWeight_<T, Vec<ET, n> >
|
||||
{
|
||||
static inline Vec<ET, n> f(double dist, const float *h, ET fixed_point_mult)
|
||||
{
|
||||
Vec<ET, n> res;
|
||||
for (int i=0; i<n; i++)
|
||||
res[i] = calcWeight<T, ET>(dist, &h[i], fixed_point_mult);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename T> static inline int calcDist(const T a, const T b)
|
||||
{
|
||||
return calcDist_<T>::f(a, b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)
|
||||
{
|
||||
const T a = m.at<T>(i1, j1);
|
||||
const T b = m.at<T>(i2, j2);
|
||||
return calcDist<T>(a,b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
|
||||
{
|
||||
return calcUpDownDist_<T>::f(a_up, a_down, b_up, b_down);
|
||||
};
|
||||
|
||||
template <typename T, typename WT>
|
||||
static inline WT calcWeight(double dist, const float *h,
|
||||
typename pixelInfo<WT>::sampleType fixed_point_mult)
|
||||
{
|
||||
return calcWeight_<T, WT>::f(dist, h, fixed_point_mult);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int maxDist()
|
||||
{
|
||||
return (int)pixelInfo<T>::sampleMax() * (int)pixelInfo<T>::sampleMax() *
|
||||
pixelInfo<T>::channels;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename IT, typename WT> struct incWithWeight_
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, WT weight, T p)
|
||||
{
|
||||
estimation[0] += (IT)weight * p;
|
||||
weights_sum[0] += (IT)weight;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 2>, IT, WT>
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 2> p)
|
||||
{
|
||||
estimation[0] += (IT)weight * p[0];
|
||||
estimation[1] += (IT)weight * p[1];
|
||||
weights_sum[0] += (IT)weight;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 3>, IT, WT>
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 3> p)
|
||||
{
|
||||
estimation[0] += (IT)weight * p[0];
|
||||
estimation[1] += (IT)weight * p[1];
|
||||
estimation[2] += (IT)weight * p[2];
|
||||
weights_sum[0] += (IT)weight;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 4>, IT, WT>
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 4> p)
|
||||
{
|
||||
estimation[0] += (IT)weight * p[0];
|
||||
estimation[1] += (IT)weight * p[1];
|
||||
estimation[2] += (IT)weight * p[2];
|
||||
estimation[3] += (IT)weight * p[3];
|
||||
weights_sum[0] += (IT)weight;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 2>, IT, Vec<EW, 2> >
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 2> weight, Vec<ET, 2> p)
|
||||
{
|
||||
estimation[0] += (IT)weight[0] * p[0];
|
||||
estimation[1] += (IT)weight[1] * p[1];
|
||||
weights_sum[0] += (IT)weight[0];
|
||||
weights_sum[1] += (IT)weight[1];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 3>, IT, Vec<EW, 3> >
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 3> weight, Vec<ET, 3> p)
|
||||
{
|
||||
estimation[0] += (IT)weight[0] * p[0];
|
||||
estimation[1] += (IT)weight[1] * p[1];
|
||||
estimation[2] += (IT)weight[2] * p[2];
|
||||
weights_sum[0] += (IT)weight[0];
|
||||
weights_sum[1] += (IT)weight[1];
|
||||
weights_sum[2] += (IT)weight[2];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 4>, IT, Vec<EW, 4> >
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 4> weight, Vec<ET, 4> p)
|
||||
{
|
||||
estimation[0] += (IT)weight[0] * p[0];
|
||||
estimation[1] += (IT)weight[1] * p[1];
|
||||
estimation[2] += (IT)weight[2] * p[2];
|
||||
estimation[3] += (IT)weight[3] * p[3];
|
||||
weights_sum[0] += (IT)weight[0];
|
||||
weights_sum[1] += (IT)weight[1];
|
||||
weights_sum[2] += (IT)weight[2];
|
||||
weights_sum[3] += (IT)weight[3];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename IT, typename WT>
|
||||
static inline void incWithWeight(IT* estimation, IT* weights_sum, WT weight, T p)
|
||||
{
|
||||
incWithWeight_<T, IT, WT>::f(estimation, weights_sum, weight, p);
|
||||
}
|
||||
|
||||
template <typename IT, typename UIT, int nc, int nw> struct divByWeightsSum_
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum);
|
||||
};
|
||||
|
||||
template <typename IT, typename UIT> struct divByWeightsSum_<IT, UIT, 1, 1>
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum)
|
||||
{
|
||||
estimation[0] = (static_cast<UIT>(estimation[0]) + weights_sum[0]/2) / weights_sum[0];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IT, typename UIT, int n> struct divByWeightsSum_<IT, UIT, n, 1>
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
estimation[i] = (static_cast<UIT>(estimation[i]) + weights_sum[0]/2) / weights_sum[0];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IT, typename UIT, int n> struct divByWeightsSum_<IT, UIT, n, n>
|
||||
{
|
||||
static inline void f(IT* estimation, IT* weights_sum)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
estimation[i] = (static_cast<UIT>(estimation[i]) + weights_sum[i]/2) / weights_sum[i];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IT, typename UIT, int nc, int nw>
|
||||
static inline void divByWeightsSum(IT* estimation, IT* weights_sum)
|
||||
{
|
||||
divByWeightsSum_<IT, UIT, nc, nw>::f(estimation, weights_sum);
|
||||
}
|
||||
|
||||
template <typename T, typename IT> struct saturateCastFromArray_
|
||||
{
|
||||
static inline T f(IT* estimation)
|
||||
{
|
||||
return saturate_cast<T>(estimation[0]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 2>, IT>
|
||||
{
|
||||
static inline Vec<ET, 2> f(IT* estimation)
|
||||
{
|
||||
Vec<ET, 2> res;
|
||||
res[0] = saturate_cast<ET>(estimation[0]);
|
||||
res[1] = saturate_cast<ET>(estimation[1]);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 3>, IT>
|
||||
{
|
||||
static inline Vec<ET, 3> f(IT* estimation)
|
||||
{
|
||||
Vec<ET, 3> res;
|
||||
res[0] = saturate_cast<ET>(estimation[0]);
|
||||
res[1] = saturate_cast<ET>(estimation[1]);
|
||||
res[2] = saturate_cast<ET>(estimation[2]);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 4>, IT>
|
||||
{
|
||||
static inline Vec<ET, 4> f(IT* estimation)
|
||||
{
|
||||
Vec<ET, 4> res;
|
||||
res[0] = saturate_cast<ET>(estimation[0]);
|
||||
res[1] = saturate_cast<ET>(estimation[1]);
|
||||
res[2] = saturate_cast<ET>(estimation[2]);
|
||||
res[3] = saturate_cast<ET>(estimation[3]);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename IT> static inline T saturateCastFromArray(IT* estimation)
|
||||
{
|
||||
return saturateCastFromArray_<T, IT>::f(estimation);
|
||||
}
|
||||
|
||||
#endif
|
||||
217
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_denoising_opencl.hpp
vendored
Normal file
217
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_denoising_opencl.hpp
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
// 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.
|
||||
|
||||
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "precomp.hpp"
|
||||
#ifndef __OPENCV_FAST_NLMEANS_DENOISING_OPENCL_HPP__
|
||||
#define __OPENCV_FAST_NLMEANS_DENOISING_OPENCL_HPP__
|
||||
|
||||
#include "opencl_kernels_photo.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cv {
|
||||
|
||||
enum
|
||||
{
|
||||
BLOCK_ROWS = 32,
|
||||
BLOCK_COLS = 32,
|
||||
CTA_SIZE_INTEL = 64,
|
||||
CTA_SIZE_DEFAULT = 256
|
||||
};
|
||||
|
||||
template <typename FT, typename ST, typename WT>
|
||||
static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight,
|
||||
int searchWindowSize, int templateWindowSize,
|
||||
const FT *h, int hn, int cn, int normType,
|
||||
int & almostTemplateWindowSizeSqBinShift)
|
||||
{
|
||||
const WT maxEstimateSumValue = searchWindowSize * searchWindowSize *
|
||||
std::numeric_limits<ST>::max();
|
||||
int fixedPointMult = (int)std::min<WT>(std::numeric_limits<WT>::max() / maxEstimateSumValue,
|
||||
std::numeric_limits<int>::max());
|
||||
int depth = DataType<FT>::depth;
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if (depth == CV_64F && !doubleSupport)
|
||||
return false;
|
||||
|
||||
// precalc weight for every possible l2 dist between blocks
|
||||
// additional optimization of precalced weights to replace division(averaging) by binary shift
|
||||
CV_Assert(templateWindowSize <= 46340); // sqrt(INT_MAX)
|
||||
int templateWindowSizeSq = templateWindowSize * templateWindowSize;
|
||||
almostTemplateWindowSizeSqBinShift = getNearestPowerOf2(templateWindowSizeSq);
|
||||
FT almostDist2ActualDistMultiplier = (FT)(1 << almostTemplateWindowSizeSqBinShift) / templateWindowSizeSq;
|
||||
|
||||
const FT WEIGHT_THRESHOLD = 1e-3f;
|
||||
WT maxDist = normType == NORM_L1 ? (WT)std::numeric_limits<ST>::max() * cn :
|
||||
(WT)std::numeric_limits<ST>::max() * (WT)std::numeric_limits<ST>::max() * cn;
|
||||
int almostMaxDist = (int)(maxDist / almostDist2ActualDistMultiplier + 1);
|
||||
FT den[4];
|
||||
CV_Assert(hn > 0 && hn <= 4);
|
||||
for (int i=0; i<hn; i++)
|
||||
den[i] = 1.0f / (h[i] * h[i] * cn);
|
||||
|
||||
almostDist2Weight.create(1, almostMaxDist, CV_32SC(hn == 3 ? 4 : hn));
|
||||
|
||||
char buf[40];
|
||||
ocl::Kernel k("calcAlmostDist2Weight", ocl::photo::nlmeans_oclsrc,
|
||||
format("-D OP_CALC_WEIGHTS -D FT=%s -D w_t=%s"
|
||||
" -D wlut_t=%s -D convert_wlut_t=%s%s%s",
|
||||
ocl::typeToStr(depth), ocl::typeToStr(CV_MAKE_TYPE(depth, hn)),
|
||||
ocl::typeToStr(CV_32SC(hn)), ocl::convertTypeStr(depth, CV_32S, hn, buf),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
normType == NORM_L1 ? " -D ABS" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::PtrWriteOnly(almostDist2Weight), almostMaxDist,
|
||||
almostDist2ActualDistMultiplier, fixedPointMult,
|
||||
ocl::KernelArg::Constant(den, (hn == 3 ? 4 : hn)*sizeof(FT)), WEIGHT_THRESHOLD);
|
||||
|
||||
size_t globalsize[1] = { (size_t)almostMaxDist };
|
||||
return k.run(1, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const float *h, int hn,
|
||||
int templateWindowSize, int searchWindowSize, int normType)
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int ctaSize = ocl::Device::getDefault().isIntel() ? CTA_SIZE_INTEL : CTA_SIZE_DEFAULT;
|
||||
Size size = _src.size();
|
||||
|
||||
if (cn < 1 || cn > 4 || ((normType != NORM_L2 || depth != CV_8U) &&
|
||||
(normType != NORM_L1 || (depth != CV_8U && depth != CV_16U))))
|
||||
return false;
|
||||
|
||||
int templateWindowHalfWize = templateWindowSize / 2;
|
||||
int searchWindowHalfSize = searchWindowSize / 2;
|
||||
templateWindowSize = templateWindowHalfWize * 2 + 1;
|
||||
searchWindowSize = searchWindowHalfSize * 2 + 1;
|
||||
int nblocksx = divUp(size.width, BLOCK_COLS), nblocksy = divUp(size.height, BLOCK_ROWS);
|
||||
int almostTemplateWindowSizeSqBinShift = -1;
|
||||
|
||||
char buf[4][40];
|
||||
const unsigned psz = (depth == CV_8U ? sizeof(uchar) : sizeof(ushort)) * (cn == 3 ? 4 : cn);
|
||||
String opts = format("-D OP_CALC_FASTNLMEANS -D TEMPLATE_SIZE=%d -D SEARCH_SIZE=%d"
|
||||
" -D pixel_t=%s -D int_t=%s -D wlut_t=%s"
|
||||
" -D weight_t=%s -D convert_weight_t=%s -D sum_t=%s -D convert_sum_t=%s"
|
||||
" -D BLOCK_COLS=%d -D BLOCK_ROWS=%d"
|
||||
" -D CTA_SIZE=%d -D TEMPLATE_SIZE2=%d -D SEARCH_SIZE2=%d"
|
||||
" -D convert_int_t=%s -D cn=%d -D psz=%u -D convert_pixel_t=%s%s",
|
||||
templateWindowSize, searchWindowSize,
|
||||
ocl::typeToStr(type), ocl::typeToStr(CV_32SC(cn)),
|
||||
ocl::typeToStr(CV_32SC(hn)),
|
||||
depth == CV_8U ? ocl::typeToStr(CV_32SC(hn)) :
|
||||
format("long%s", hn > 1 ? format("%d", hn).c_str() : "").c_str(),
|
||||
depth == CV_8U ? ocl::convertTypeStr(CV_32S, CV_32S, hn, buf[0]) :
|
||||
format("convert_long%s", hn > 1 ? format("%d", hn).c_str() : "").c_str(),
|
||||
depth == CV_8U ? ocl::typeToStr(CV_32SC(cn)) :
|
||||
format("long%s", cn > 1 ? format("%d", cn).c_str() : "").c_str(),
|
||||
depth == CV_8U ? ocl::convertTypeStr(depth, CV_32S, cn, buf[1]) :
|
||||
format("convert_long%s", cn > 1 ? format("%d", cn).c_str() : "").c_str(),
|
||||
BLOCK_COLS, BLOCK_ROWS,
|
||||
ctaSize, templateWindowHalfWize, searchWindowHalfSize,
|
||||
ocl::convertTypeStr(depth, CV_32S, cn, buf[2]), cn,
|
||||
psz,
|
||||
ocl::convertTypeStr(CV_32S, depth, cn, buf[3]),
|
||||
normType == NORM_L1 ? " -D ABS" : "");
|
||||
|
||||
ocl::Kernel k("fastNlMeansDenoising", ocl::photo::nlmeans_oclsrc, opts);
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat almostDist2Weight;
|
||||
if ((depth == CV_8U &&
|
||||
!ocl_calcAlmostDist2Weight<float, uchar, int>(almostDist2Weight,
|
||||
searchWindowSize, templateWindowSize,
|
||||
h, hn, cn, normType,
|
||||
almostTemplateWindowSizeSqBinShift)) ||
|
||||
(depth == CV_16U &&
|
||||
!ocl_calcAlmostDist2Weight<float, ushort, int64>(almostDist2Weight,
|
||||
searchWindowSize, templateWindowSize,
|
||||
h, hn, cn, normType,
|
||||
almostTemplateWindowSizeSqBinShift)))
|
||||
return false;
|
||||
CV_Assert(almostTemplateWindowSizeSqBinShift >= 0);
|
||||
|
||||
UMat srcex;
|
||||
int borderSize = searchWindowHalfSize + templateWindowHalfWize;
|
||||
if (cn == 3) {
|
||||
srcex.create(size.height + 2*borderSize, size.width + 2*borderSize, CV_MAKE_TYPE(depth, 4));
|
||||
UMat src(srcex, Rect(borderSize, borderSize, size.width, size.height));
|
||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
||||
mixChannels(std::vector<UMat>(1, _src.getUMat()), std::vector<UMat>(1, src), from_to, 3);
|
||||
copyMakeBorder(src, srcex, borderSize, borderSize, borderSize, borderSize,
|
||||
BORDER_DEFAULT|BORDER_ISOLATED); // create borders in place
|
||||
}
|
||||
else
|
||||
copyMakeBorder(_src, srcex, borderSize, borderSize, borderSize, borderSize, BORDER_DEFAULT);
|
||||
|
||||
_dst.create(size, type);
|
||||
UMat dst;
|
||||
if (cn == 3)
|
||||
dst.create(size, CV_MAKE_TYPE(depth, 4));
|
||||
else
|
||||
dst = _dst.getUMat();
|
||||
|
||||
int searchWindowSizeSq = searchWindowSize * searchWindowSize;
|
||||
Size upColSumSize(size.width, searchWindowSizeSq * nblocksy);
|
||||
Size colSumSize(nblocksx * templateWindowSize, searchWindowSizeSq * nblocksy);
|
||||
UMat buffer(upColSumSize + colSumSize, CV_32SC(cn));
|
||||
|
||||
srcex = srcex(Rect(Point(borderSize, borderSize), size));
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(srcex), ocl::KernelArg::WriteOnly(dst),
|
||||
ocl::KernelArg::PtrReadOnly(almostDist2Weight),
|
||||
ocl::KernelArg::PtrReadOnly(buffer), almostTemplateWindowSizeSqBinShift);
|
||||
|
||||
size_t globalsize[2] = { (size_t)nblocksx * ctaSize, (size_t)nblocksy }, localsize[2] = { (size_t)ctaSize, 1 };
|
||||
if (!k.run(2, globalsize, localsize, false)) return false;
|
||||
|
||||
if (cn == 3) {
|
||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
||||
mixChannels(std::vector<UMat>(1, dst), std::vector<UMat>(1, _dst.getUMat()), from_to, 3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ocl_fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
|
||||
float h, float hForColorComponents,
|
||||
int templateWindowSize, int searchWindowSize)
|
||||
{
|
||||
UMat src = _src.getUMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
UMat src_lab;
|
||||
cvtColor(src, src_lab, COLOR_LBGR2Lab);
|
||||
|
||||
UMat l(src.size(), CV_8U);
|
||||
UMat ab(src.size(), CV_8UC2);
|
||||
std::vector<UMat> l_ab(2), l_ab_denoised(2);
|
||||
l_ab[0] = l;
|
||||
l_ab[1] = ab;
|
||||
l_ab_denoised[0].create(src.size(), CV_8U);
|
||||
l_ab_denoised[1].create(src.size(), CV_8UC2);
|
||||
|
||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
||||
mixChannels(std::vector<UMat>(1, src_lab), l_ab, from_to, 3);
|
||||
|
||||
fastNlMeansDenoising(l_ab[0], l_ab_denoised[0], h, templateWindowSize, searchWindowSize);
|
||||
fastNlMeansDenoising(l_ab[1], l_ab_denoised[1], hForColorComponents, templateWindowSize, searchWindowSize);
|
||||
|
||||
UMat dst_lab(src.size(), CV_8UC3);
|
||||
mixChannels(l_ab_denoised, std::vector<UMat>(1, dst_lab), from_to, 3);
|
||||
|
||||
cvtColor(dst_lab, dst, COLOR_Lab2LBGR, src.channels());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
360
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp
vendored
Normal file
360
3rdparty/opencv-4.5.4/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp
vendored
Normal file
@ -0,0 +1,360 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective icvers.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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*/
|
||||
|
||||
#ifndef __OPENCV_FAST_NLMEANS_MULTI_DENOISING_INVOKER_HPP__
|
||||
#define __OPENCV_FAST_NLMEANS_MULTI_DENOISING_INVOKER_HPP__
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <limits>
|
||||
|
||||
#include "fast_nlmeans_denoising_invoker_commons.hpp"
|
||||
#include "arrays.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
struct FastNlMeansMultiDenoisingInvoker :
|
||||
ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
FastNlMeansMultiDenoisingInvoker(const std::vector<Mat>& srcImgs, int imgToDenoiseIndex,
|
||||
int temporalWindowSize, Mat& dst, int template_window_size,
|
||||
int search_window_size, const float *h);
|
||||
|
||||
void operator() (const Range& range) const CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
void operator= (const FastNlMeansMultiDenoisingInvoker&);
|
||||
|
||||
int rows_;
|
||||
int cols_;
|
||||
|
||||
Mat& dst_;
|
||||
|
||||
std::vector<Mat> extended_srcs_;
|
||||
Mat main_extended_src_;
|
||||
int border_size_;
|
||||
|
||||
int template_window_size_;
|
||||
int search_window_size_;
|
||||
int temporal_window_size_;
|
||||
|
||||
int template_window_half_size_;
|
||||
int search_window_half_size_;
|
||||
int temporal_window_half_size_;
|
||||
|
||||
typename pixelInfo<WT>::sampleType fixed_point_mult_;
|
||||
int almost_template_window_size_sq_bin_shift;
|
||||
std::vector<WT> almost_dist2weight;
|
||||
|
||||
void calcDistSumsForFirstElementInRow(int i, Array3d<int>& dist_sums,
|
||||
Array4d<int>& col_dist_sums,
|
||||
Array4d<int>& up_col_dist_sums) const;
|
||||
|
||||
void calcDistSumsForElementInFirstRow(int i, int j, int first_col_num,
|
||||
Array3d<int>& dist_sums, Array4d<int>& col_dist_sums,
|
||||
Array4d<int>& up_col_dist_sums) const;
|
||||
};
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D, WT>::FastNlMeansMultiDenoisingInvoker(
|
||||
const std::vector<Mat>& srcImgs,
|
||||
int imgToDenoiseIndex,
|
||||
int temporalWindowSize,
|
||||
cv::Mat& dst,
|
||||
int template_window_size,
|
||||
int search_window_size,
|
||||
const float *h) :
|
||||
dst_(dst), extended_srcs_(srcImgs.size())
|
||||
{
|
||||
CV_Assert(srcImgs.size() > 0);
|
||||
CV_Assert(srcImgs[0].channels() == pixelInfo<T>::channels);
|
||||
|
||||
rows_ = srcImgs[0].rows;
|
||||
cols_ = srcImgs[0].cols;
|
||||
|
||||
template_window_half_size_ = template_window_size / 2;
|
||||
search_window_half_size_ = search_window_size / 2;
|
||||
temporal_window_half_size_ = temporalWindowSize / 2;
|
||||
|
||||
template_window_size_ = template_window_half_size_ * 2 + 1;
|
||||
search_window_size_ = search_window_half_size_ * 2 + 1;
|
||||
temporal_window_size_ = temporal_window_half_size_ * 2 + 1;
|
||||
|
||||
border_size_ = search_window_half_size_ + template_window_half_size_;
|
||||
for (int i = 0; i < temporal_window_size_; i++)
|
||||
copyMakeBorder(srcImgs[imgToDenoiseIndex - temporal_window_half_size_ + i], extended_srcs_[i],
|
||||
border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT);
|
||||
|
||||
main_extended_src_ = extended_srcs_[temporal_window_half_size_];
|
||||
const IT max_estimate_sum_value =
|
||||
(IT)temporal_window_size_ * (IT)search_window_size_ * (IT)search_window_size_ * (IT)pixelInfo<T>::sampleMax();
|
||||
fixed_point_mult_ = (int)std::min<IT>(std::numeric_limits<IT>::max() / max_estimate_sum_value,
|
||||
pixelInfo<WT>::sampleMax());
|
||||
|
||||
// precalc weight for every possible l2 dist between blocks
|
||||
// additional optimization of precalced weights to replace division(averaging) by binary shift
|
||||
int template_window_size_sq = template_window_size_ * template_window_size_;
|
||||
almost_template_window_size_sq_bin_shift = 0;
|
||||
while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq)
|
||||
almost_template_window_size_sq_bin_shift++;
|
||||
|
||||
int almost_template_window_size_sq = 1 << almost_template_window_size_sq_bin_shift;
|
||||
double almost_dist2actual_dist_multiplier = (double) almost_template_window_size_sq / template_window_size_sq;
|
||||
|
||||
int max_dist = D::template maxDist<T>();
|
||||
int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1);
|
||||
almost_dist2weight.resize(almost_max_dist);
|
||||
|
||||
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++)
|
||||
{
|
||||
double dist = almost_dist * almost_dist2actual_dist_multiplier;
|
||||
almost_dist2weight[almost_dist] =
|
||||
D::template calcWeight<T, WT>(dist, h, fixed_point_mult_);
|
||||
}
|
||||
|
||||
// additional optimization init end
|
||||
if (dst_.empty())
|
||||
dst_ = Mat::zeros(srcImgs[0].size(), srcImgs[0].type());
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D, WT>::operator() (const Range& range) const
|
||||
{
|
||||
int row_from = range.start;
|
||||
int row_to = range.end - 1;
|
||||
|
||||
Array3d<int> dist_sums(temporal_window_size_, search_window_size_, search_window_size_);
|
||||
|
||||
// for lazy calc optimization
|
||||
Array4d<int> col_dist_sums(template_window_size_, temporal_window_size_, search_window_size_, search_window_size_);
|
||||
|
||||
int first_col_num = -1;
|
||||
Array4d<int> up_col_dist_sums(cols_, temporal_window_size_, search_window_size_, search_window_size_);
|
||||
|
||||
for (int i = row_from; i <= row_to; i++)
|
||||
{
|
||||
for (int j = 0; j < cols_; j++)
|
||||
{
|
||||
int search_window_y = i - search_window_half_size_;
|
||||
int search_window_x = j - search_window_half_size_;
|
||||
|
||||
// calc dist_sums
|
||||
if (j == 0)
|
||||
{
|
||||
calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums);
|
||||
first_col_num = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calc cur dist_sums using previous dist_sums
|
||||
if (i == row_from)
|
||||
{
|
||||
calcDistSumsForElementInFirstRow(i, j, first_col_num,
|
||||
dist_sums, col_dist_sums, up_col_dist_sums);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int ay = border_size_ + i;
|
||||
int ax = border_size_ + j + template_window_half_size_;
|
||||
|
||||
int start_by =
|
||||
border_size_ + i - search_window_half_size_;
|
||||
|
||||
int start_bx =
|
||||
border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
||||
|
||||
T a_up = main_extended_src_.at<T>(ay - template_window_half_size_ - 1, ax);
|
||||
T a_down = main_extended_src_.at<T>(ay + template_window_half_size_, ax);
|
||||
|
||||
// copy class member to local variable for optimization
|
||||
int search_window_size = search_window_size_;
|
||||
|
||||
for (int d = 0; d < temporal_window_size_; d++)
|
||||
{
|
||||
Mat cur_extended_src = extended_srcs_[d];
|
||||
Array2d<int> cur_dist_sums = dist_sums[d];
|
||||
Array2d<int> cur_col_dist_sums = col_dist_sums[first_col_num][d];
|
||||
Array2d<int> cur_up_col_dist_sums = up_col_dist_sums[j][d];
|
||||
for (int y = 0; y < search_window_size; y++)
|
||||
{
|
||||
int* dist_sums_row = cur_dist_sums.row_ptr(y);
|
||||
|
||||
int* col_dist_sums_row = cur_col_dist_sums.row_ptr(y);
|
||||
int* up_col_dist_sums_row = cur_up_col_dist_sums.row_ptr(y);
|
||||
|
||||
const T* b_up_ptr = cur_extended_src.ptr<T>(start_by - template_window_half_size_ - 1 + y);
|
||||
const T* b_down_ptr = cur_extended_src.ptr<T>(start_by + template_window_half_size_ + y);
|
||||
|
||||
for (int x = 0; x < search_window_size; x++)
|
||||
{
|
||||
dist_sums_row[x] -= col_dist_sums_row[x];
|
||||
|
||||
col_dist_sums_row[x] = up_col_dist_sums_row[x] +
|
||||
D::template calcUpDownDist<T>(a_up, a_down, b_up_ptr[start_bx + x], b_down_ptr[start_bx + x]);
|
||||
|
||||
dist_sums_row[x] += col_dist_sums_row[x];
|
||||
up_col_dist_sums_row[x] = col_dist_sums_row[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
first_col_num = (first_col_num + 1) % template_window_size_;
|
||||
}
|
||||
|
||||
// calc weights
|
||||
IT estimation[pixelInfo<T>::channels], weights_sum[pixelInfo<WT>::channels];
|
||||
for (size_t channel_num = 0; channel_num < pixelInfo<T>::channels; channel_num++)
|
||||
estimation[channel_num] = 0;
|
||||
for (size_t channel_num = 0; channel_num < pixelInfo<WT>::channels; channel_num++)
|
||||
weights_sum[channel_num] = 0;
|
||||
|
||||
for (int d = 0; d < temporal_window_size_; d++)
|
||||
{
|
||||
const Mat& esrc_d = extended_srcs_[d];
|
||||
for (int y = 0; y < search_window_size_; y++)
|
||||
{
|
||||
const T* cur_row_ptr = esrc_d.ptr<T>(border_size_ + search_window_y + y);
|
||||
|
||||
int* dist_sums_row = dist_sums.row_ptr(d, y);
|
||||
|
||||
for (int x = 0; x < search_window_size_; x++)
|
||||
{
|
||||
int almostAvgDist = dist_sums_row[x] >> almost_template_window_size_sq_bin_shift;
|
||||
|
||||
WT weight = almost_dist2weight[almostAvgDist];
|
||||
T p = cur_row_ptr[border_size_ + search_window_x + x];
|
||||
incWithWeight<T, IT, WT>(estimation, weights_sum, weight, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
divByWeightsSum<IT, UIT, pixelInfo<T>::channels, pixelInfo<WT>::channels>(estimation,
|
||||
weights_sum);
|
||||
dst_.at<T>(i,j) = saturateCastFromArray<T, IT>(estimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D, WT>::calcDistSumsForFirstElementInRow(
|
||||
int i, Array3d<int>& dist_sums, Array4d<int>& col_dist_sums, Array4d<int>& up_col_dist_sums) const
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
for (int d = 0; d < temporal_window_size_; d++)
|
||||
{
|
||||
Mat cur_extended_src = extended_srcs_[d];
|
||||
for (int y = 0; y < search_window_size_; y++)
|
||||
for (int x = 0; x < search_window_size_; x++)
|
||||
{
|
||||
dist_sums[d][y][x] = 0;
|
||||
for (int tx = 0; tx < template_window_size_; tx++)
|
||||
col_dist_sums[tx][d][y][x] = 0;
|
||||
|
||||
int start_y = i + y - search_window_half_size_;
|
||||
int start_x = j + x - search_window_half_size_;
|
||||
|
||||
int* dist_sums_ptr = &dist_sums[d][y][x];
|
||||
int* col_dist_sums_ptr = &col_dist_sums[0][d][y][x];
|
||||
int col_dist_sums_step = col_dist_sums.step_size(0);
|
||||
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++)
|
||||
{
|
||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
|
||||
{
|
||||
int dist = D::template calcDist<T>(
|
||||
main_extended_src_.at<T>(border_size_ + i + ty, border_size_ + j + tx),
|
||||
cur_extended_src.at<T>(border_size_ + start_y + ty, border_size_ + start_x + tx));
|
||||
|
||||
*dist_sums_ptr += dist;
|
||||
*col_dist_sums_ptr += dist;
|
||||
}
|
||||
col_dist_sums_ptr += col_dist_sums_step;
|
||||
}
|
||||
|
||||
up_col_dist_sums[j][d][y][x] = col_dist_sums[template_window_size_ - 1][d][y][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename IT, typename UIT, typename D, typename WT>
|
||||
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D, WT>::calcDistSumsForElementInFirstRow(
|
||||
int i, int j, int first_col_num, Array3d<int>& dist_sums,
|
||||
Array4d<int>& col_dist_sums, Array4d<int>& up_col_dist_sums) const
|
||||
{
|
||||
int ay = border_size_ + i;
|
||||
int ax = border_size_ + j + template_window_half_size_;
|
||||
|
||||
int start_by = border_size_ + i - search_window_half_size_;
|
||||
int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
||||
|
||||
int new_last_col_num = first_col_num;
|
||||
|
||||
for (int d = 0; d < temporal_window_size_; d++)
|
||||
{
|
||||
Mat cur_extended_src = extended_srcs_[d];
|
||||
for (int y = 0; y < search_window_size_; y++)
|
||||
for (int x = 0; x < search_window_size_; x++)
|
||||
{
|
||||
dist_sums[d][y][x] -= col_dist_sums[first_col_num][d][y][x];
|
||||
|
||||
col_dist_sums[new_last_col_num][d][y][x] = 0;
|
||||
int by = start_by + y;
|
||||
int bx = start_bx + x;
|
||||
|
||||
int* col_dist_sums_ptr = &col_dist_sums[new_last_col_num][d][y][x];
|
||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
|
||||
{
|
||||
*col_dist_sums_ptr += D::template calcDist<T>(
|
||||
main_extended_src_.at<T>(ay + ty, ax),
|
||||
cur_extended_src.at<T>(by + ty, bx));
|
||||
}
|
||||
|
||||
dist_sums[d][y][x] += col_dist_sums[new_last_col_num][d][y][x];
|
||||
|
||||
up_col_dist_sums[j][d][y][x] = col_dist_sums[new_last_col_num][d][y][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
110
3rdparty/opencv-4.5.4/modules/photo/src/hdr_common.cpp
vendored
Normal file
110
3rdparty/opencv-4.5.4/modules/photo/src/hdr_common.cpp
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "hdr_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
void checkImageDimensions(const std::vector<Mat>& images)
|
||||
{
|
||||
CV_Assert(!images.empty());
|
||||
int width = images[0].cols;
|
||||
int height = images[0].rows;
|
||||
int type = images[0].type();
|
||||
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
CV_Assert(images[i].cols == width && images[i].rows == height);
|
||||
CV_Assert(images[i].type() == type);
|
||||
}
|
||||
}
|
||||
|
||||
Mat triangleWeights()
|
||||
{
|
||||
// hat function
|
||||
Mat w(LDR_SIZE, 1, CV_32F);
|
||||
int half = LDR_SIZE / 2;
|
||||
for(int i = 0; i < LDR_SIZE; i++) {
|
||||
w.at<float>(i) = i < half ? i + 1.0f : LDR_SIZE - i;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
Mat RobertsonWeights()
|
||||
{
|
||||
Mat weight(LDR_SIZE, 1, CV_32FC3);
|
||||
float q = (LDR_SIZE - 1) / 4.0f;
|
||||
float e4 = exp(4.f);
|
||||
float scale = e4/(e4 - 1.f);
|
||||
float shift = 1 / (1.f - e4);
|
||||
|
||||
for(int i = 0; i < LDR_SIZE; i++) {
|
||||
float value = i / q - 2.0f;
|
||||
value = scale*exp(-value * value) + shift;
|
||||
weight.at<Vec3f>(i) = Vec3f::all(value);
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
void mapLuminance(Mat src, Mat dst, Mat lum, Mat new_lum, float saturation)
|
||||
{
|
||||
std::vector<Mat> channels(3);
|
||||
split(src, channels);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
channels[i] = channels[i].mul(1.0f / lum);
|
||||
pow(channels[i], saturation, channels[i]);
|
||||
channels[i] = channels[i].mul(new_lum);
|
||||
}
|
||||
merge(channels, dst);
|
||||
}
|
||||
|
||||
Mat linearResponse(int channels)
|
||||
{
|
||||
Mat response = Mat(LDR_SIZE, 1, CV_MAKETYPE(CV_32F, channels));
|
||||
for(int i = 0; i < LDR_SIZE; i++) {
|
||||
response.at<Vec3f>(i) = Vec3f::all(static_cast<float>(i));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
62
3rdparty/opencv-4.5.4/modules/photo/src/hdr_common.hpp
vendored
Normal file
62
3rdparty/opencv-4.5.4/modules/photo/src/hdr_common.hpp
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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*/
|
||||
|
||||
#ifndef __OPENCV_HDR_COMMON_HPP__
|
||||
#define __OPENCV_HDR_COMMON_HPP__
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
void checkImageDimensions(const std::vector<Mat>& images);
|
||||
|
||||
Mat triangleWeights();
|
||||
|
||||
void mapLuminance(Mat src, Mat dst, Mat lum, Mat new_lum, float saturation);
|
||||
|
||||
Mat RobertsonWeights();
|
||||
|
||||
Mat linearResponse(int channels);
|
||||
}
|
||||
|
||||
#endif
|
||||
863
3rdparty/opencv-4.5.4/modules/photo/src/inpaint.cpp
vendored
Normal file
863
3rdparty/opencv-4.5.4/modules/photo/src/inpaint.cpp
vendored
Normal file
@ -0,0 +1,863 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective icvers.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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*/
|
||||
|
||||
/* ////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Geometrical transforms on images and matrices: rotation, zoom etc.
|
||||
//
|
||||
// */
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/photo/legacy/constants_c.h"
|
||||
|
||||
#undef CV_MAT_ELEM_PTR_FAST
|
||||
#define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \
|
||||
((mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col))
|
||||
|
||||
inline float
|
||||
min4( float a, float b, float c, float d )
|
||||
{
|
||||
a = MIN(a,b);
|
||||
c = MIN(c,d);
|
||||
return MIN(a,c);
|
||||
}
|
||||
|
||||
#define CV_MAT_3COLOR_ELEM(img,type,y,x,c) CV_MAT_ELEM(img,type,y,(x)*3+(c))
|
||||
#define KNOWN 0 //known outside narrow band
|
||||
#define BAND 1 //narrow band (known)
|
||||
#define INSIDE 2 //unknown
|
||||
#define CHANGE 3 //servise
|
||||
|
||||
typedef struct CvHeapElem
|
||||
{
|
||||
float T;
|
||||
int i,j;
|
||||
struct CvHeapElem* prev;
|
||||
struct CvHeapElem* next;
|
||||
}
|
||||
CvHeapElem;
|
||||
|
||||
|
||||
class CvPriorityQueueFloat
|
||||
{
|
||||
private:
|
||||
CvPriorityQueueFloat(const CvPriorityQueueFloat & ); // copy disabled
|
||||
CvPriorityQueueFloat& operator=(const CvPriorityQueueFloat &); // assign disabled
|
||||
|
||||
protected:
|
||||
CvHeapElem *mem,*empty,*head,*tail;
|
||||
int num,in;
|
||||
|
||||
public:
|
||||
bool Init( const CvMat* f )
|
||||
{
|
||||
int i,j;
|
||||
for( i = num = 0; i < f->rows; i++ )
|
||||
{
|
||||
for( j = 0; j < f->cols; j++ )
|
||||
num += CV_MAT_ELEM(*f,uchar,i,j)!=0;
|
||||
}
|
||||
if (num<=0) return false;
|
||||
mem = (CvHeapElem*)cvAlloc((num+2)*sizeof(CvHeapElem));
|
||||
if (mem==NULL) return false;
|
||||
|
||||
head = mem;
|
||||
head->i = head->j = -1;
|
||||
head->prev = NULL;
|
||||
head->next = mem+1;
|
||||
head->T = -FLT_MAX;
|
||||
empty = mem+1;
|
||||
for (i=1; i<=num; i++) {
|
||||
mem[i].prev = mem+i-1;
|
||||
mem[i].next = mem+i+1;
|
||||
mem[i].i = -1;
|
||||
mem[i].T = FLT_MAX;
|
||||
}
|
||||
tail = mem+i;
|
||||
tail->i = tail->j = -1;
|
||||
tail->prev = mem+i-1;
|
||||
tail->next = NULL;
|
||||
tail->T = FLT_MAX;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Add(const CvMat* f) {
|
||||
int i,j;
|
||||
for (i=0; i<f->rows; i++) {
|
||||
for (j=0; j<f->cols; j++) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j)!=0) {
|
||||
if (!Push(i,j,0)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Push(int i, int j, float T) {
|
||||
CvHeapElem *tmp=empty,*add=empty;
|
||||
if (empty==tail) return false;
|
||||
while (tmp->prev->T>T) tmp = tmp->prev;
|
||||
if (tmp!=empty) {
|
||||
add->prev->next = add->next;
|
||||
add->next->prev = add->prev;
|
||||
empty = add->next;
|
||||
add->prev = tmp->prev;
|
||||
add->next = tmp;
|
||||
add->prev->next = add;
|
||||
add->next->prev = add;
|
||||
} else {
|
||||
empty = empty->next;
|
||||
}
|
||||
add->i = i;
|
||||
add->j = j;
|
||||
add->T = T;
|
||||
in++;
|
||||
// printf("push i %3d j %3d T %12.4e in %4d\n",i,j,T,in);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pop(int *i, int *j) {
|
||||
CvHeapElem *tmp=head->next;
|
||||
if (empty==tmp) return false;
|
||||
*i = tmp->i;
|
||||
*j = tmp->j;
|
||||
tmp->prev->next = tmp->next;
|
||||
tmp->next->prev = tmp->prev;
|
||||
tmp->prev = empty->prev;
|
||||
tmp->next = empty;
|
||||
tmp->prev->next = tmp;
|
||||
tmp->next->prev = tmp;
|
||||
empty = tmp;
|
||||
in--;
|
||||
// printf("pop i %3d j %3d T %12.4e in %4d\n",tmp->i,tmp->j,tmp->T,in);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pop(int *i, int *j, float *T) {
|
||||
CvHeapElem *tmp=head->next;
|
||||
if (empty==tmp) return false;
|
||||
*i = tmp->i;
|
||||
*j = tmp->j;
|
||||
*T = tmp->T;
|
||||
tmp->prev->next = tmp->next;
|
||||
tmp->next->prev = tmp->prev;
|
||||
tmp->prev = empty->prev;
|
||||
tmp->next = empty;
|
||||
tmp->prev->next = tmp;
|
||||
tmp->next->prev = tmp;
|
||||
empty = tmp;
|
||||
in--;
|
||||
// printf("pop i %3d j %3d T %12.4e in %4d\n",tmp->i,tmp->j,tmp->T,in);
|
||||
return true;
|
||||
}
|
||||
|
||||
CvPriorityQueueFloat(void) {
|
||||
num=in=0;
|
||||
mem=empty=head=tail=NULL;
|
||||
}
|
||||
|
||||
~CvPriorityQueueFloat(void)
|
||||
{
|
||||
cvFree( &mem );
|
||||
}
|
||||
};
|
||||
|
||||
static inline float VectorScalMult(const cv::Point2f& v1, const cv::Point2f& v2)
|
||||
{
|
||||
return v1.x*v2.x+v1.y*v2.y;
|
||||
}
|
||||
|
||||
static inline float VectorLength(const cv::Point2f& v1)
|
||||
{
|
||||
return v1.x*v1.x+v1.y*v1.y;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
//HEAP::iterator Heap_Iterator;
|
||||
//HEAP Heap;
|
||||
|
||||
static float FastMarching_solve(int i1,int j1,int i2,int j2, const CvMat* f, const CvMat* t)
|
||||
{
|
||||
double sol, a11, a22, m12;
|
||||
a11=CV_MAT_ELEM(*t,float,i1,j1);
|
||||
a22=CV_MAT_ELEM(*t,float,i2,j2);
|
||||
m12=MIN(a11,a22);
|
||||
|
||||
if( CV_MAT_ELEM(*f,uchar,i1,j1) != INSIDE )
|
||||
if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
|
||||
if( fabs(a11-a22) >= 1.0 )
|
||||
sol = 1+m12;
|
||||
else
|
||||
sol = (a11+a22+sqrt((double)(2-(a11-a22)*(a11-a22))))*0.5;
|
||||
else
|
||||
sol = 1+a11;
|
||||
else if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
|
||||
sol = 1+a22;
|
||||
else
|
||||
sol = 1+m12;
|
||||
|
||||
return (float)sol;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void
|
||||
icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) {
|
||||
int i, j, ii = 0, jj = 0, q;
|
||||
float dist;
|
||||
|
||||
while (Heap->Pop(&ii,&jj)) {
|
||||
|
||||
unsigned known=(negate)?CHANGE:KNOWN;
|
||||
CV_MAT_ELEM(*f,uchar,ii,jj) = (uchar)known;
|
||||
|
||||
for (q=0; q<4; q++) {
|
||||
i=0; j=0;
|
||||
if (q==0) {i=ii-1; j=jj;}
|
||||
else if(q==1) {i=ii; j=jj-1;}
|
||||
else if(q==2) {i=ii+1; j=jj;}
|
||||
else {i=ii; j=jj+1;}
|
||||
if ((i<=0)||(j<=0)||(i>f->rows)||(j>f->cols)) continue;
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
||||
Heap->Push(i,j,dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (negate) {
|
||||
for (i=0; i<f->rows; i++) {
|
||||
for(j=0; j<f->cols; j++) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j) == CHANGE) {
|
||||
CV_MAT_ELEM(*f,uchar,i,j) = KNOWN;
|
||||
CV_MAT_ELEM(*t,float,i,j) = -CV_MAT_ELEM(*t,float,i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename data_type>
|
||||
static void
|
||||
icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap ) {
|
||||
int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
|
||||
float dist;
|
||||
|
||||
if (CV_MAT_CN(out->type)==3) {
|
||||
|
||||
while (Heap->Pop(&ii,&jj)) {
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
||||
for(q=0; q<4; q++) {
|
||||
if (q==0) {i=ii-1; j=jj;}
|
||||
else if(q==1) {i=ii; j=jj-1;}
|
||||
else if(q==2) {i=ii+1; j=jj;}
|
||||
else if(q==3) {i=ii; j=jj+1;}
|
||||
if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
||||
|
||||
cv::Point2f gradT[3];
|
||||
for (color=0; color<=2; color++) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
||||
gradT[color].x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
|
||||
} else {
|
||||
gradT[color].x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
||||
gradT[color].x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
|
||||
} else {
|
||||
gradT[color].x=0;
|
||||
}
|
||||
}
|
||||
if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
||||
gradT[color].y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
|
||||
} else {
|
||||
gradT[color].y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
||||
gradT[color].y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
|
||||
} else {
|
||||
gradT[color].y=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cv::Point2f gradI,r;
|
||||
float Jx[3] = {0,0,0};
|
||||
float Jy[3] = {0,0,0};
|
||||
float Ia[3] = {0,0,0};
|
||||
float s[3] = {1.0e-20f,1.0e-20f,1.0e-20f};
|
||||
float w,dst,lev,dir,sat;
|
||||
|
||||
for (k=i-range; k<=i+range; k++) {
|
||||
int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
|
||||
for (l=j-range; l<=j+range; l++) {
|
||||
int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
|
||||
if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
|
||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
||||
for (color=0; color<=2; color++) {
|
||||
r.y = (float)(i-k);
|
||||
r.x = (float)(j-l);
|
||||
|
||||
dst = (float)(1./(VectorLength(r)*sqrt((double)VectorLength(r))));
|
||||
lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
|
||||
|
||||
dir=VectorScalMult(r,gradT[color]);
|
||||
if (fabs(dir)<=0.01) dir=0.000001f;
|
||||
w = (float)fabs(dst*lev*dir);
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)))*2.0f;
|
||||
} else {
|
||||
gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)));
|
||||
} else {
|
||||
gradI.x=0;
|
||||
}
|
||||
}
|
||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)))*2.0f;
|
||||
} else {
|
||||
gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)));
|
||||
} else {
|
||||
gradI.y=0;
|
||||
}
|
||||
}
|
||||
Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color));
|
||||
Jx[color] -= (float)w * (float)(gradI.x*r.x);
|
||||
Jy[color] -= (float)w * (float)(gradI.y*r.y);
|
||||
s[color] += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (color=0; color<=2; color++) {
|
||||
sat = (float)((Ia[color]/s[color]+(Jx[color]+Jy[color])/(sqrt(Jx[color]*Jx[color]+Jy[color]*Jy[color])+1.0e-20f)+0.5f));
|
||||
CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = cv::saturate_cast<uchar>(sat);
|
||||
}
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
||||
Heap->Push(i,j,dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (CV_MAT_CN(out->type)==1) {
|
||||
|
||||
while (Heap->Pop(&ii,&jj)) {
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
||||
for(q=0; q<4; q++) {
|
||||
if (q==0) {i=ii-1; j=jj;}
|
||||
else if(q==1) {i=ii; j=jj-1;}
|
||||
else if(q==2) {i=ii+1; j=jj;}
|
||||
else if(q==3) {i=ii; j=jj+1;}
|
||||
if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
||||
|
||||
for (color=0; color<=0; color++) {
|
||||
cv::Point2f gradI,gradT,r;
|
||||
float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat;
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
|
||||
} else {
|
||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
|
||||
} else {
|
||||
gradT.x=0;
|
||||
}
|
||||
}
|
||||
if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
|
||||
} else {
|
||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
|
||||
} else {
|
||||
gradT.y=0;
|
||||
}
|
||||
}
|
||||
for (k=i-range; k<=i+range; k++) {
|
||||
int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
|
||||
for (l=j-range; l<=j+range; l++) {
|
||||
int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
|
||||
if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
|
||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
||||
r.y = (float)(i-k);
|
||||
r.x = (float)(j-l);
|
||||
|
||||
dst = (float)(1./(VectorLength(r)*sqrt(VectorLength(r))));
|
||||
lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
|
||||
|
||||
dir=VectorScalMult(r,gradT);
|
||||
if (fabs(dir)<=0.01) dir=0.000001f;
|
||||
w = (float)fabs(dst*lev*dir);
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.x=(float)((CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm-1)))*2.0f;
|
||||
} else {
|
||||
gradI.x=(float)((CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.x=(float)((CV_MAT_ELEM(*out,data_type,km,lp)-CV_MAT_ELEM(*out,data_type,km,lm-1)));
|
||||
} else {
|
||||
gradI.x=0;
|
||||
}
|
||||
}
|
||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.y=(float)((CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)))*2.0f;
|
||||
} else {
|
||||
gradI.y=(float)((CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,km,lm)));
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.y=(float)((CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)));
|
||||
} else {
|
||||
gradI.y=0;
|
||||
}
|
||||
}
|
||||
Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,km,lm));
|
||||
Jx -= (float)w * (float)(gradI.x*r.x);
|
||||
Jy -= (float)w * (float)(gradI.y*r.y);
|
||||
s += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f));
|
||||
{
|
||||
CV_MAT_ELEM(*out,data_type,i-1,j-1) = cv::saturate_cast<data_type>(sat);
|
||||
}
|
||||
}
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
||||
Heap->Push(i,j,dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename data_type>
|
||||
static void
|
||||
icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap) {
|
||||
int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
|
||||
float dist;
|
||||
|
||||
if (CV_MAT_CN(out->type)==3) {
|
||||
|
||||
while (Heap->Pop(&ii,&jj)) {
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
||||
for(q=0; q<4; q++) {
|
||||
if (q==0) {i=ii-1; j=jj;}
|
||||
else if(q==1) {i=ii; j=jj-1;}
|
||||
else if(q==2) {i=ii+1; j=jj;}
|
||||
else if(q==3) {i=ii; j=jj+1;}
|
||||
if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
||||
|
||||
cv::Point2f gradI,r;
|
||||
float Ia[3]={0,0,0};
|
||||
float s[3]={1.0e-20f,1.0e-20f,1.0e-20f};
|
||||
float w,dst,dir;
|
||||
|
||||
for (k=i-range; k<=i+range; k++) {
|
||||
int km=k-1+(k==1),kp=k-1-(k==f->rows-2);
|
||||
for (l=j-range; l<=j+range; l++) {
|
||||
int lm=l-1+(l==1),lp=l-1-(l==f->cols-2);
|
||||
if (k>0&&l>0&&k<f->rows-1&&l<f->cols-1) {
|
||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
||||
for (color=0; color<=2; color++) {
|
||||
r.y=(float)(k-i);
|
||||
r.x=(float)(l-j);
|
||||
|
||||
dst = 1/(VectorLength(r)*VectorLength(r)+1);
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color))+
|
||||
abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)));
|
||||
} else {
|
||||
gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)))*2.0f;
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)))*2.0f;
|
||||
} else {
|
||||
gradI.x=0;
|
||||
}
|
||||
}
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color))+
|
||||
abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)));
|
||||
} else {
|
||||
gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)))*2.0f;
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)))*2.0f;
|
||||
} else {
|
||||
gradI.y=0;
|
||||
}
|
||||
}
|
||||
|
||||
gradI.x=-gradI.x;
|
||||
dir=VectorScalMult(r,gradI);
|
||||
|
||||
if (fabs(dir)<=0.01) {
|
||||
dir=0.000001f;
|
||||
} else {
|
||||
dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
|
||||
}
|
||||
w = dst*dir;
|
||||
Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color));
|
||||
s[color] += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (color=0; color<=2; color++) {
|
||||
CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = cv::saturate_cast<uchar>((double)Ia[color]/s[color]);
|
||||
}
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
||||
Heap->Push(i,j,dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (CV_MAT_CN(out->type)==1) {
|
||||
|
||||
while (Heap->Pop(&ii,&jj)) {
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
||||
for(q=0; q<4; q++) {
|
||||
if (q==0) {i=ii-1; j=jj;}
|
||||
else if(q==1) {i=ii; j=jj-1;}
|
||||
else if(q==2) {i=ii+1; j=jj;}
|
||||
else if(q==3) {i=ii; j=jj+1;}
|
||||
if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
||||
|
||||
{
|
||||
cv::Point2f gradI,r;
|
||||
float Ia=0,s=1.0e-20f,w,dst,dir;
|
||||
|
||||
for (k=i-range; k<=i+range; k++) {
|
||||
int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
|
||||
for (l=j-range; l<=j+range; l++) {
|
||||
int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
|
||||
if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
|
||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
||||
r.y=(float)(i-k);
|
||||
r.x=(float)(j-l);
|
||||
|
||||
dst = 1/(VectorLength(r)*VectorLength(r)+1);
|
||||
|
||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm))+
|
||||
std::abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)));
|
||||
} else {
|
||||
gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm)))*2.0f;
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
||||
gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)))*2.0f;
|
||||
} else {
|
||||
gradI.x=0;
|
||||
}
|
||||
}
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm))+
|
||||
std::abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)));
|
||||
} else {
|
||||
gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm)))*2.0f;
|
||||
}
|
||||
} else {
|
||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
||||
gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)))*2.0f;
|
||||
} else {
|
||||
gradI.y=0;
|
||||
}
|
||||
}
|
||||
|
||||
gradI.x=-gradI.x;
|
||||
dir=VectorScalMult(r,gradI);
|
||||
|
||||
if (fabs(dir)<=0.01) {
|
||||
dir=0.000001f;
|
||||
} else {
|
||||
dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
|
||||
}
|
||||
w = dst*dir;
|
||||
Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,km,lm));
|
||||
s += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CV_MAT_ELEM(*out,data_type,i-1,j-1) = cv::saturate_cast<data_type>((double)Ia/s);
|
||||
}
|
||||
|
||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
||||
Heap->Push(i,j,dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define SET_BORDER1_C1(image,type,value) {\
|
||||
int i,j;\
|
||||
for(j=0; j<image->cols; j++) {\
|
||||
CV_MAT_ELEM(*image,type,0,j) = value;\
|
||||
}\
|
||||
for (i=1; i<image->rows-1; i++) {\
|
||||
CV_MAT_ELEM(*image,type,i,0) = CV_MAT_ELEM(*image,type,i,image->cols-1) = value;\
|
||||
}\
|
||||
for(j=0; j<image->cols; j++) {\
|
||||
CV_MAT_ELEM(*image,type,erows-1,j) = value;\
|
||||
}\
|
||||
}
|
||||
|
||||
#define COPY_MASK_BORDER1_C1(src,dst,type) {\
|
||||
int i,j;\
|
||||
for (i=0; i<src->rows; i++) {\
|
||||
for(j=0; j<src->cols; j++) {\
|
||||
if (CV_MAT_ELEM(*src,type,i,j)!=0)\
|
||||
CV_MAT_ELEM(*dst,type,i+1,j+1) = INSIDE;\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
template<> struct DefaultDeleter<IplConvKernel>{ void operator ()(IplConvKernel* obj) const { cvReleaseStructuringElement(&obj); } };
|
||||
}
|
||||
|
||||
static void
|
||||
icvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img,
|
||||
double inpaintRange, int flags )
|
||||
{
|
||||
cv::Ptr<CvMat> mask, band, f, t, out;
|
||||
cv::Ptr<CvPriorityQueueFloat> Heap, Out;
|
||||
cv::Ptr<IplConvKernel> el_cross, el_range;
|
||||
|
||||
CvMat input_hdr, mask_hdr, output_hdr;
|
||||
CvMat* input_img, *inpaint_mask, *output_img;
|
||||
int range=cvRound(inpaintRange);
|
||||
int erows, ecols;
|
||||
|
||||
input_img = cvGetMat( _input_img, &input_hdr );
|
||||
inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr );
|
||||
output_img = cvGetMat( _output_img, &output_hdr );
|
||||
|
||||
if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))
|
||||
CV_Error( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );
|
||||
|
||||
if( (CV_MAT_TYPE(input_img->type) != CV_8U &&
|
||||
CV_MAT_TYPE(input_img->type) != CV_16U &&
|
||||
CV_MAT_TYPE(input_img->type) != CV_32F &&
|
||||
CV_MAT_TYPE(input_img->type) != CV_8UC3) ||
|
||||
!CV_ARE_TYPES_EQ(input_img,output_img) )
|
||||
CV_Error( CV_StsUnsupportedFormat,
|
||||
"8-bit, 16-bit unsigned or 32-bit float 1-channel and 8-bit 3-channel input/output images are supported" );
|
||||
|
||||
if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )
|
||||
CV_Error( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );
|
||||
|
||||
range = MAX(range,1);
|
||||
range = MIN(range,100);
|
||||
|
||||
ecols = input_img->cols + 2;
|
||||
erows = input_img->rows + 2;
|
||||
|
||||
f.reset(cvCreateMat(erows, ecols, CV_8UC1));
|
||||
t.reset(cvCreateMat(erows, ecols, CV_32FC1));
|
||||
band.reset(cvCreateMat(erows, ecols, CV_8UC1));
|
||||
mask.reset(cvCreateMat(erows, ecols, CV_8UC1));
|
||||
el_cross.reset(cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL));
|
||||
|
||||
cvCopy( input_img, output_img );
|
||||
cvSet(mask,cvScalar(KNOWN,0,0,0));
|
||||
COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar);
|
||||
SET_BORDER1_C1(mask,uchar,0);
|
||||
cvSet(f,cvScalar(KNOWN,0,0,0));
|
||||
cvSet(t,cvScalar(1.0e6f,0,0,0));
|
||||
cvDilate(mask,band,el_cross,1); // image with narrow band
|
||||
Heap=cv::makePtr<CvPriorityQueueFloat>();
|
||||
if (!Heap->Init(band))
|
||||
return;
|
||||
cvSub(band,mask,band,NULL);
|
||||
SET_BORDER1_C1(band,uchar,0);
|
||||
if (!Heap->Add(band))
|
||||
return;
|
||||
cvSet(f,cvScalar(BAND,0,0,0),band);
|
||||
cvSet(f,cvScalar(INSIDE,0,0,0),mask);
|
||||
cvSet(t,cvScalar(0,0,0,0),band);
|
||||
|
||||
if( flags == cv::INPAINT_TELEA )
|
||||
{
|
||||
out.reset(cvCreateMat(erows, ecols, CV_8UC1));
|
||||
el_range.reset(cvCreateStructuringElementEx(2*range+1,2*range+1,
|
||||
range,range,CV_SHAPE_RECT,NULL));
|
||||
cvDilate(mask,out,el_range,1);
|
||||
cvSub(out,mask,out,NULL);
|
||||
Out=cv::makePtr<CvPriorityQueueFloat>();
|
||||
if (!Out->Init(out))
|
||||
return;
|
||||
if (!Out->Add(band))
|
||||
return;
|
||||
cvSub(out,band,out,NULL);
|
||||
SET_BORDER1_C1(out,uchar,0);
|
||||
icvCalcFMM(out,t,Out,true);
|
||||
switch(CV_MAT_DEPTH(output_img->type))
|
||||
{
|
||||
case CV_8U:
|
||||
icvTeleaInpaintFMM<uchar>(mask,t,output_img,range,Heap);
|
||||
break;
|
||||
case CV_16U:
|
||||
icvTeleaInpaintFMM<ushort>(mask,t,output_img,range,Heap);
|
||||
break;
|
||||
case CV_32F:
|
||||
icvTeleaInpaintFMM<float>(mask,t,output_img,range,Heap);
|
||||
break;
|
||||
default:
|
||||
CV_Error( cv::Error::StsBadArg, "Unsupportedformat of the input image" );
|
||||
}
|
||||
}
|
||||
else if (flags == cv::INPAINT_NS) {
|
||||
switch(CV_MAT_DEPTH(output_img->type))
|
||||
{
|
||||
case CV_8U:
|
||||
icvNSInpaintFMM<uchar>(mask,t,output_img,range,Heap);
|
||||
break;
|
||||
case CV_16U:
|
||||
icvNSInpaintFMM<ushort>(mask,t,output_img,range,Heap);
|
||||
break;
|
||||
case CV_32F:
|
||||
icvNSInpaintFMM<float>(mask,t,output_img,range,Heap);
|
||||
break;
|
||||
default:
|
||||
CV_Error( cv::Error::StsBadArg, "Unsupported format of the input image" );
|
||||
}
|
||||
} else {
|
||||
CV_Error( cv::Error::StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" );
|
||||
}
|
||||
}
|
||||
|
||||
void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst,
|
||||
double inpaintRange, int flags )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat(), mask = _mask.getMat();
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
CvMat c_src = cvMat(src), c_mask = cvMat(mask), c_dst = cvMat(dst);
|
||||
icvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags );
|
||||
}
|
||||
367
3rdparty/opencv-4.5.4/modules/photo/src/merge.cpp
vendored
Normal file
367
3rdparty/opencv-4.5.4/modules/photo/src/merge.cpp
vendored
Normal file
@ -0,0 +1,367 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "hdr_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class MergeDebevecImpl CV_FINAL : public MergeDebevec
|
||||
{
|
||||
public:
|
||||
MergeDebevecImpl() :
|
||||
name("MergeDebevec"),
|
||||
weights(triangleWeights())
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
Mat times = _times.getMat();
|
||||
|
||||
CV_Assert(images.size() == times.total());
|
||||
checkImageDimensions(images);
|
||||
CV_Assert(images[0].depth() == CV_8U);
|
||||
|
||||
int channels = images[0].channels();
|
||||
Size size = images[0].size();
|
||||
int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
|
||||
|
||||
dst.create(images[0].size(), CV_32FCC);
|
||||
Mat result = dst.getMat();
|
||||
|
||||
Mat response = input_response.getMat();
|
||||
|
||||
if(response.empty()) {
|
||||
response = linearResponse(channels);
|
||||
response.at<Vec3f>(0) = response.at<Vec3f>(1);
|
||||
}
|
||||
|
||||
Mat log_response;
|
||||
log(response, log_response);
|
||||
CV_Assert(log_response.rows == LDR_SIZE && log_response.cols == 1 &&
|
||||
log_response.channels() == channels);
|
||||
|
||||
Mat exp_values(times.clone());
|
||||
log(exp_values, exp_values);
|
||||
|
||||
result = Mat::zeros(size, CV_32FCC);
|
||||
std::vector<Mat> result_split;
|
||||
split(result, result_split);
|
||||
Mat weight_sum = Mat::zeros(size, CV_32F);
|
||||
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
std::vector<Mat> splitted;
|
||||
split(images[i], splitted);
|
||||
|
||||
Mat w = Mat::zeros(size, CV_32F);
|
||||
for(int c = 0; c < channels; c++) {
|
||||
LUT(splitted[c], weights, splitted[c]);
|
||||
w += splitted[c];
|
||||
}
|
||||
w /= channels;
|
||||
|
||||
Mat response_img;
|
||||
LUT(images[i], log_response, response_img);
|
||||
split(response_img, splitted);
|
||||
for(int c = 0; c < channels; c++) {
|
||||
result_split[c] += w.mul(splitted[c] - exp_values.at<float>((int)i));
|
||||
}
|
||||
weight_sum += w;
|
||||
}
|
||||
weight_sum = 1.0f / weight_sum;
|
||||
for(int c = 0; c < channels; c++) {
|
||||
result_split[c] = result_split[c].mul(weight_sum);
|
||||
}
|
||||
merge(result_split, result);
|
||||
exp(result, result);
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, InputArray times) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
process(src, dst, times, Mat());
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
Mat weights;
|
||||
};
|
||||
|
||||
Ptr<MergeDebevec> createMergeDebevec()
|
||||
{
|
||||
return makePtr<MergeDebevecImpl>();
|
||||
}
|
||||
|
||||
class MergeMertensImpl CV_FINAL : public MergeMertens
|
||||
{
|
||||
public:
|
||||
MergeMertensImpl(float _wcon, float _wsat, float _wexp) :
|
||||
name("MergeMertens"),
|
||||
wcon(_wcon),
|
||||
wsat(_wsat),
|
||||
wexp(_wexp)
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArrayOfArrays dst, InputArray, InputArray) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
process(src, dst);
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
checkImageDimensions(images);
|
||||
|
||||
int channels = images[0].channels();
|
||||
CV_Assert(channels == 1 || channels == 3);
|
||||
Size size = images[0].size();
|
||||
int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
|
||||
|
||||
std::vector<Mat> weights(images.size());
|
||||
Mat weight_sum = Mat::zeros(size, CV_32F);
|
||||
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
Mat img, gray, contrast, saturation, wellexp;
|
||||
std::vector<Mat> splitted(channels);
|
||||
|
||||
images[i].convertTo(img, CV_32F, 1.0f/255.0f);
|
||||
if(channels == 3) {
|
||||
cvtColor(img, gray, COLOR_RGB2GRAY);
|
||||
} else {
|
||||
img.copyTo(gray);
|
||||
}
|
||||
split(img, splitted);
|
||||
|
||||
Laplacian(gray, contrast, CV_32F);
|
||||
contrast = abs(contrast);
|
||||
|
||||
Mat mean = Mat::zeros(size, CV_32F);
|
||||
for(int c = 0; c < channels; c++) {
|
||||
mean += splitted[c];
|
||||
}
|
||||
mean /= channels;
|
||||
|
||||
saturation = Mat::zeros(size, CV_32F);
|
||||
for(int c = 0; c < channels; c++) {
|
||||
Mat deviation = splitted[c] - mean;
|
||||
pow(deviation, 2.0f, deviation);
|
||||
saturation += deviation;
|
||||
}
|
||||
sqrt(saturation, saturation);
|
||||
|
||||
wellexp = Mat::ones(size, CV_32F);
|
||||
for(int c = 0; c < channels; c++) {
|
||||
Mat expo = splitted[c] - 0.5f;
|
||||
pow(expo, 2.0f, expo);
|
||||
expo = -expo / 0.08f;
|
||||
exp(expo, expo);
|
||||
wellexp = wellexp.mul(expo);
|
||||
}
|
||||
|
||||
pow(contrast, wcon, contrast);
|
||||
pow(saturation, wsat, saturation);
|
||||
pow(wellexp, wexp, wellexp);
|
||||
|
||||
weights[i] = contrast;
|
||||
if(channels == 3) {
|
||||
weights[i] = weights[i].mul(saturation);
|
||||
}
|
||||
weights[i] = weights[i].mul(wellexp) + 1e-12f;
|
||||
weight_sum += weights[i];
|
||||
}
|
||||
int maxlevel = static_cast<int>(logf(static_cast<float>(min(size.width, size.height))) / logf(2.0f));
|
||||
std::vector<Mat> res_pyr(maxlevel + 1);
|
||||
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
weights[i] /= weight_sum;
|
||||
Mat img;
|
||||
images[i].convertTo(img, CV_32F, 1.0f/255.0f);
|
||||
|
||||
std::vector<Mat> img_pyr, weight_pyr;
|
||||
buildPyramid(img, img_pyr, maxlevel);
|
||||
buildPyramid(weights[i], weight_pyr, maxlevel);
|
||||
|
||||
for(int lvl = 0; lvl < maxlevel; lvl++) {
|
||||
Mat up;
|
||||
pyrUp(img_pyr[lvl + 1], up, img_pyr[lvl].size());
|
||||
img_pyr[lvl] -= up;
|
||||
}
|
||||
for(int lvl = 0; lvl <= maxlevel; lvl++) {
|
||||
std::vector<Mat> splitted(channels);
|
||||
split(img_pyr[lvl], splitted);
|
||||
for(int c = 0; c < channels; c++) {
|
||||
splitted[c] = splitted[c].mul(weight_pyr[lvl]);
|
||||
}
|
||||
merge(splitted, img_pyr[lvl]);
|
||||
if(res_pyr[lvl].empty()) {
|
||||
res_pyr[lvl] = img_pyr[lvl];
|
||||
} else {
|
||||
res_pyr[lvl] += img_pyr[lvl];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int lvl = maxlevel; lvl > 0; lvl--) {
|
||||
Mat up;
|
||||
pyrUp(res_pyr[lvl], up, res_pyr[lvl - 1].size());
|
||||
res_pyr[lvl - 1] += up;
|
||||
}
|
||||
dst.create(size, CV_32FCC);
|
||||
res_pyr[0].copyTo(dst);
|
||||
}
|
||||
|
||||
float getContrastWeight() const CV_OVERRIDE { return wcon; }
|
||||
void setContrastWeight(float val) CV_OVERRIDE { wcon = val; }
|
||||
|
||||
float getSaturationWeight() const CV_OVERRIDE { return wsat; }
|
||||
void setSaturationWeight(float val) CV_OVERRIDE { wsat = val; }
|
||||
|
||||
float getExposureWeight() const CV_OVERRIDE { return wexp; }
|
||||
void setExposureWeight(float val) CV_OVERRIDE { wexp = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "contrast_weight" << wcon
|
||||
<< "saturation_weight" << wsat
|
||||
<< "exposure_weight" << wexp;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
wcon = fn["contrast_weight"];
|
||||
wsat = fn["saturation_weight"];
|
||||
wexp = fn["exposure_weight"];
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
float wcon, wsat, wexp;
|
||||
};
|
||||
|
||||
Ptr<MergeMertens> createMergeMertens(float wcon, float wsat, float wexp)
|
||||
{
|
||||
return makePtr<MergeMertensImpl>(wcon, wsat, wexp);
|
||||
}
|
||||
|
||||
class MergeRobertsonImpl CV_FINAL : public MergeRobertson
|
||||
{
|
||||
public:
|
||||
MergeRobertsonImpl() :
|
||||
name("MergeRobertson"),
|
||||
weight(RobertsonWeights())
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
Mat times = _times.getMat();
|
||||
|
||||
CV_Assert(images.size() == times.total());
|
||||
checkImageDimensions(images);
|
||||
CV_Assert(images[0].depth() == CV_8U);
|
||||
|
||||
int channels = images[0].channels();
|
||||
int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
|
||||
|
||||
dst.create(images[0].size(), CV_32FCC);
|
||||
Mat result = dst.getMat();
|
||||
|
||||
Mat response = input_response.getMat();
|
||||
if(response.empty()) {
|
||||
float middle = LDR_SIZE / 2.0f;
|
||||
response = linearResponse(channels) / middle;
|
||||
}
|
||||
CV_Assert(response.rows == LDR_SIZE && response.cols == 1 &&
|
||||
response.channels() == channels);
|
||||
|
||||
result = Mat::zeros(images[0].size(), CV_32FCC);
|
||||
Mat wsum = Mat::zeros(images[0].size(), CV_32FCC);
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
Mat im, w;
|
||||
LUT(images[i], weight, w);
|
||||
LUT(images[i], response, im);
|
||||
|
||||
result += times.at<float>((int)i) * w.mul(im);
|
||||
wsum += times.at<float>((int)i) * times.at<float>((int)i) * w;
|
||||
}
|
||||
result = result.mul(1 / (wsum + Scalar::all(DBL_EPSILON)));
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, InputArray times) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
process(src, dst, times, Mat());
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
Mat weight;
|
||||
};
|
||||
|
||||
Ptr<MergeRobertson> createMergeRobertson()
|
||||
{
|
||||
return makePtr<MergeRobertsonImpl>();
|
||||
}
|
||||
|
||||
}
|
||||
163
3rdparty/opencv-4.5.4/modules/photo/src/npr.cpp
vendored
Normal file
163
3rdparty/opencv-4.5.4/modules/photo/src/npr.cpp
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "npr.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void cv::edgePreservingFilter(InputArray _src, OutputArray dst, int flags, float sigma_s, float sigma_r)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat I = _src.getMat();
|
||||
|
||||
Domain_Filter obj;
|
||||
|
||||
Mat img;
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
Mat res;
|
||||
obj.filter(img, res, sigma_s, sigma_r, flags);
|
||||
|
||||
convertScaleAbs(res, dst, 255,0);
|
||||
}
|
||||
|
||||
void cv::detailEnhance(InputArray _src, OutputArray dst, float sigma_s, float sigma_r)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat I = _src.getMat();
|
||||
|
||||
float factor = 3.0f;
|
||||
|
||||
Mat img;
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
Mat lab;
|
||||
vector <Mat> lab_channel;
|
||||
cvtColor(img,lab,COLOR_BGR2Lab);
|
||||
split(lab,lab_channel);
|
||||
|
||||
Mat L;
|
||||
lab_channel[0].convertTo(L,CV_32FC1,1.0/255.0);
|
||||
|
||||
Domain_Filter obj;
|
||||
|
||||
Mat res;
|
||||
obj.filter(L, res, sigma_s, sigma_r, 1);
|
||||
|
||||
Mat detail = L - res;
|
||||
multiply(detail,factor,detail);
|
||||
L = res + detail;
|
||||
|
||||
L.convertTo(lab_channel[0],CV_32FC1,255);
|
||||
|
||||
merge(lab_channel,lab);
|
||||
|
||||
cvtColor(lab,res,COLOR_Lab2BGR);
|
||||
res.convertTo(dst,CV_8UC3,255);
|
||||
}
|
||||
|
||||
void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, float sigma_s, float sigma_r, float shade_factor)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat I = _src.getMat();
|
||||
_dst1.create(I.size(), CV_8UC1);
|
||||
Mat dst1 = _dst1.getMat();
|
||||
|
||||
_dst2.create(I.size(), CV_8UC3);
|
||||
Mat dst2 = _dst2.getMat();
|
||||
|
||||
Mat img = Mat(I.size(),CV_32FC3);
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
Domain_Filter obj;
|
||||
|
||||
Mat sketch = Mat(I.size(),CV_32FC1);
|
||||
Mat color_sketch = Mat(I.size(),CV_32FC3);
|
||||
|
||||
obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor);
|
||||
|
||||
sketch.convertTo(dst1,CV_8UC1,255);
|
||||
color_sketch.convertTo(dst2,CV_8UC3,255);
|
||||
|
||||
}
|
||||
|
||||
void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat I = _src.getMat();
|
||||
_dst.create(I.size(), CV_8UC3);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Mat img;
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
|
||||
Mat res;
|
||||
Mat magnitude = Mat(h,w,CV_32FC1);
|
||||
|
||||
Domain_Filter obj;
|
||||
obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER);
|
||||
|
||||
obj.find_magnitude(res,magnitude);
|
||||
|
||||
Mat stylized;
|
||||
|
||||
vector <Mat> temp;
|
||||
split(res,temp);
|
||||
multiply(temp[0],magnitude,temp[0]);
|
||||
multiply(temp[1],magnitude,temp[1]);
|
||||
multiply(temp[2],magnitude,temp[2]);
|
||||
merge(temp,stylized);
|
||||
|
||||
stylized.convertTo(dst,CV_8UC3,255);
|
||||
}
|
||||
591
3rdparty/opencv-4.5.4/modules/photo/src/npr.hpp
vendored
Normal file
591
3rdparty/opencv-4.5.4/modules/photo/src/npr.hpp
vendored
Normal file
@ -0,0 +1,591 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <limits>
|
||||
#include "math.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
double myinf = std::numeric_limits<double>::infinity();
|
||||
|
||||
class Domain_Filter
|
||||
{
|
||||
public:
|
||||
Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx;
|
||||
void init(const Mat &img, int flags, float sigma_s, float sigma_r);
|
||||
void getGradientx( const Mat &img, Mat &gx);
|
||||
void getGradienty( const Mat &img, Mat &gy);
|
||||
void diffx(const Mat &img, Mat &temp);
|
||||
void diffy(const Mat &img, Mat &temp);
|
||||
void find_magnitude(Mat &img, Mat &mag);
|
||||
void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius);
|
||||
void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h);
|
||||
void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius);
|
||||
void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags);
|
||||
void pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor);
|
||||
void Depth_of_field(const Mat &img, Mat &img1, float sigma_s, float sigma_r);
|
||||
};
|
||||
|
||||
void Domain_Filter::diffx(const Mat &img, Mat &temp)
|
||||
{
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i = 0; i < img.size().height; i++)
|
||||
for(int j = 0; j < img.size().width-1; j++)
|
||||
{
|
||||
for(int c =0; c < channel; c++)
|
||||
{
|
||||
temp.at<float>(i,j*channel+c) =
|
||||
img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::diffy(const Mat &img, Mat &temp)
|
||||
{
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i = 0; i < img.size().height-1; i++)
|
||||
for(int j = 0; j < img.size().width; j++)
|
||||
{
|
||||
for(int c =0; c < channel; c++)
|
||||
{
|
||||
temp.at<float>(i,j*channel+c) =
|
||||
img.at<float>((i+1),j*channel+c) - img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::getGradientx( const Mat &img, Mat &gx)
|
||||
{
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gx.at<float>(i,j*channel+c) =
|
||||
img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::getGradienty( const Mat &img, Mat &gy)
|
||||
{
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gy.at<float>(i,j*channel+c) =
|
||||
img.at<float>(i+1,j*channel+c) - img.at<float>(i,j*channel+c);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::find_magnitude(Mat &img, Mat &mag)
|
||||
{
|
||||
int h = img.rows;
|
||||
int w = img.cols;
|
||||
|
||||
vector <Mat> planes;
|
||||
split(img, planes);
|
||||
|
||||
Mat magXR = Mat(h, w, CV_32FC1);
|
||||
Mat magYR = Mat(h, w, CV_32FC1);
|
||||
|
||||
Mat magXG = Mat(h, w, CV_32FC1);
|
||||
Mat magYG = Mat(h, w, CV_32FC1);
|
||||
|
||||
Mat magXB = Mat(h, w, CV_32FC1);
|
||||
Mat magYB = Mat(h, w, CV_32FC1);
|
||||
|
||||
Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3);
|
||||
Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3);
|
||||
|
||||
Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3);
|
||||
Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3);
|
||||
|
||||
Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3);
|
||||
Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3);
|
||||
|
||||
Mat mag1 = Mat(h,w,CV_32FC1);
|
||||
Mat mag2 = Mat(h,w,CV_32FC1);
|
||||
Mat mag3 = Mat(h,w,CV_32FC1);
|
||||
|
||||
magnitude(magXR,magYR,mag1);
|
||||
magnitude(magXG,magYG,mag2);
|
||||
magnitude(magXB,magYB,mag3);
|
||||
|
||||
mag = mag1 + mag2 + mag3;
|
||||
mag = 1.0f - mag;
|
||||
}
|
||||
|
||||
void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h)
|
||||
{
|
||||
int h = output.rows;
|
||||
int w = output.cols;
|
||||
int channel = output.channels();
|
||||
|
||||
float a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h);
|
||||
|
||||
Mat temp = Mat(h,w,CV_32FC3);
|
||||
|
||||
output.copyTo(temp);
|
||||
Mat V = Mat(h,w,CV_32FC1);
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
V.at<float>(i,j) = pow(a,hz.at<float>(i,j));
|
||||
|
||||
for(int i=0; i<h; i++)
|
||||
{
|
||||
for(int j =1; j < w; j++)
|
||||
{
|
||||
for(int c = 0; c<channel; c++)
|
||||
{
|
||||
temp.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c) +
|
||||
(temp.at<float>(i,(j-1)*channel+c) - temp.at<float>(i,j*channel+c)) * V.at<float>(i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<h; i++)
|
||||
{
|
||||
for(int j =w-2; j >= 0; j--)
|
||||
{
|
||||
for(int c = 0; c<channel; c++)
|
||||
{
|
||||
temp.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c) +
|
||||
(temp.at<float>(i,(j+1)*channel+c) - temp.at<float>(i,j*channel+c))*V.at<float>(i,j+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
temp.copyTo(output);
|
||||
}
|
||||
|
||||
void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius)
|
||||
{
|
||||
int h = output.rows;
|
||||
int w = output.cols;
|
||||
Mat lower_pos = Mat(h,w,CV_32FC1);
|
||||
Mat upper_pos = Mat(h,w,CV_32FC1);
|
||||
|
||||
lower_pos = hz - radius;
|
||||
upper_pos = hz + radius;
|
||||
|
||||
lower_idx = Mat::zeros(h,w,CV_32FC1);
|
||||
upper_idx = Mat::zeros(h,w,CV_32FC1);
|
||||
|
||||
Mat domain_row = Mat::zeros(1,w+1,CV_32FC1);
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
domain_row.at<float>(0,j) = hz.at<float>(i,j);
|
||||
domain_row.at<float>(0,w) = (float) myinf;
|
||||
|
||||
Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1);
|
||||
Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1);
|
||||
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
lower_pos_row.at<float>(0,j) = lower_pos.at<float>(i,j);
|
||||
upper_pos_row.at<float>(0,j) = upper_pos.at<float>(i,j);
|
||||
}
|
||||
|
||||
Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1);
|
||||
Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1);
|
||||
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
if(domain_row.at<float>(0,j) > lower_pos_row.at<float>(0,0))
|
||||
{
|
||||
temp_lower_idx.at<float>(0,0) = (float) j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
if(domain_row.at<float>(0,j) > upper_pos_row.at<float>(0,0))
|
||||
{
|
||||
temp_upper_idx.at<float>(0,0) = (float) j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int temp = 0;
|
||||
for(int j=1;j<w;j++)
|
||||
{
|
||||
int count=0;
|
||||
for(int k=(int) temp_lower_idx.at<float>(0,j-1);k<w+1;k++)
|
||||
{
|
||||
if(domain_row.at<float>(0,k) > lower_pos_row.at<float>(0,j))
|
||||
{
|
||||
temp = count;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
temp_lower_idx.at<float>(0,j) = temp_lower_idx.at<float>(0,j-1) + temp;
|
||||
|
||||
count = 0;
|
||||
for(int k=(int) temp_upper_idx.at<float>(0,j-1);k<w+1;k++)
|
||||
{
|
||||
|
||||
|
||||
if(domain_row.at<float>(0,k) > upper_pos_row.at<float>(0,j))
|
||||
{
|
||||
temp = count;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
temp_upper_idx.at<float>(0,j) = temp_upper_idx.at<float>(0,j-1) + temp;
|
||||
}
|
||||
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
lower_idx.at<float>(i,j) = temp_lower_idx.at<float>(0,j) + 1;
|
||||
upper_idx.at<float>(i,j) = temp_upper_idx.at<float>(0,j) + 1;
|
||||
}
|
||||
|
||||
}
|
||||
psketch = upper_idx - lower_idx;
|
||||
}
|
||||
void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius)
|
||||
{
|
||||
int h = output.rows;
|
||||
int w = output.cols;
|
||||
int channel = output.channels();
|
||||
|
||||
compute_boxfilter(output,hz,psketch,radius);
|
||||
|
||||
Mat box_filter = Mat::zeros(h,w+1,CV_32FC3);
|
||||
|
||||
for(int i = 0; i < h; i++)
|
||||
{
|
||||
box_filter.at<float>(i,1*channel+0) = output.at<float>(i,0*channel+0);
|
||||
box_filter.at<float>(i,1*channel+1) = output.at<float>(i,0*channel+1);
|
||||
box_filter.at<float>(i,1*channel+2) = output.at<float>(i,0*channel+2);
|
||||
for(int j = 2; j < w+1; j++)
|
||||
{
|
||||
for(int c=0;c<channel;c++)
|
||||
box_filter.at<float>(i,j*channel+c) = output.at<float>(i,(j-1)*channel+c) + box_filter.at<float>(i,(j-1)*channel+c);
|
||||
}
|
||||
}
|
||||
|
||||
Mat indices = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat final = Mat::zeros(h,w,CV_32FC3);
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
indices.at<float>(i,j) = (float) i+1;
|
||||
|
||||
Mat a = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat b = Mat::zeros(h,w,CV_32FC1);
|
||||
|
||||
// Compute the box filter using a summed area table.
|
||||
for(int c=0;c<channel;c++)
|
||||
{
|
||||
Mat flag = Mat::ones(h,w,CV_32FC1);
|
||||
multiply(flag,c+1,flag);
|
||||
|
||||
Mat temp1, temp2;
|
||||
multiply(flag - 1,h*(w+1),temp1);
|
||||
multiply(lower_idx - 1,h,temp2);
|
||||
a = temp1 + temp2 + indices;
|
||||
|
||||
multiply(flag - 1,h*(w+1),temp1);
|
||||
multiply(upper_idx - 1,h,temp2);
|
||||
b = temp1 + temp2 + indices;
|
||||
|
||||
int p,q,r,rem;
|
||||
int p1,q1,r1,rem1;
|
||||
|
||||
// Calculating indices
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
|
||||
r = (int) b.at<float>(i,j)/(h*(w+1));
|
||||
rem = (int) b.at<float>(i,j) - r*h*(w+1);
|
||||
q = rem/h;
|
||||
p = rem - q*h;
|
||||
if(q==0)
|
||||
{
|
||||
p=h;
|
||||
q=w;
|
||||
r=r-1;
|
||||
}
|
||||
if(p==0)
|
||||
{
|
||||
p=h;
|
||||
q=q-1;
|
||||
}
|
||||
|
||||
r1 = (int) a.at<float>(i,j)/(h*(w+1));
|
||||
rem1 = (int) a.at<float>(i,j) - r1*h*(w+1);
|
||||
q1 = rem1/h;
|
||||
p1 = rem1 - q1*h;
|
||||
if(p1==0)
|
||||
{
|
||||
p1=h;
|
||||
q1=q1-1;
|
||||
}
|
||||
|
||||
final.at<float>(i,j*channel+2-c) = (box_filter.at<float>(p-1,q*channel+(2-r)) - box_filter.at<float>(p1-1,q1*channel+(2-r1)))
|
||||
/(upper_idx.at<float>(i,j) - lower_idx.at<float>(i,j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final.copyTo(output);
|
||||
}
|
||||
void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r)
|
||||
{
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
int channel = img.channels();
|
||||
|
||||
//////////////////////////////////// horizontal and vertical partial derivatives /////////////////////////////////
|
||||
|
||||
Mat derivx = Mat::zeros(h,w-1,CV_32FC3);
|
||||
Mat derivy = Mat::zeros(h-1,w,CV_32FC3);
|
||||
|
||||
diffx(img,derivx);
|
||||
diffy(img,derivy);
|
||||
|
||||
Mat distx = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat disty = Mat::zeros(h,w,CV_32FC1);
|
||||
|
||||
//////////////////////// Compute the l1-norm distance of neighbor pixels ////////////////////////////////////////////////
|
||||
|
||||
for(int i = 0; i < h; i++)
|
||||
for(int j = 0,k=1; j < w-1; j++,k++)
|
||||
for(int c = 0; c < channel; c++)
|
||||
{
|
||||
distx.at<float>(i,k) =
|
||||
distx.at<float>(i,k) + abs(derivx.at<float>(i,j*channel+c));
|
||||
}
|
||||
|
||||
for(int i = 0,k=1; i < h-1; i++,k++)
|
||||
for(int j = 0; j < w; j++)
|
||||
for(int c = 0; c < channel; c++)
|
||||
{
|
||||
disty.at<float>(k,j) =
|
||||
disty.at<float>(k,j) + abs(derivy.at<float>(i,j*channel+c));
|
||||
}
|
||||
|
||||
////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. /////////////////////////////
|
||||
|
||||
horiz = Mat(h,w,CV_32FC1);
|
||||
vert = Mat(h,w,CV_32FC1);
|
||||
|
||||
Mat final = Mat(h,w,CV_32FC3);
|
||||
|
||||
Mat tempx,tempy;
|
||||
multiply(distx,sigma_s/sigma_r,tempx);
|
||||
multiply(disty,sigma_s/sigma_r,tempy);
|
||||
|
||||
horiz = 1.0f + tempx;
|
||||
vert = 1.0f + tempy;
|
||||
|
||||
O = Mat(h,w,CV_32FC3);
|
||||
img.copyTo(O);
|
||||
|
||||
O_t = Mat(w,h,CV_32FC3);
|
||||
|
||||
if(flags == 2)
|
||||
{
|
||||
|
||||
ct_H = Mat(h,w,CV_32FC1);
|
||||
ct_V = Mat(h,w,CV_32FC1);
|
||||
|
||||
for(int i = 0; i < h; i++)
|
||||
{
|
||||
ct_H.at<float>(i,0) = horiz.at<float>(i,0);
|
||||
for(int j = 1; j < w; j++)
|
||||
{
|
||||
ct_H.at<float>(i,j) = horiz.at<float>(i,j) + ct_H.at<float>(i,j-1);
|
||||
}
|
||||
}
|
||||
|
||||
for(int j = 0; j < w; j++)
|
||||
{
|
||||
ct_V.at<float>(0,j) = vert.at<float>(0,j);
|
||||
for(int i = 1; i < h; i++)
|
||||
{
|
||||
ct_V.at<float>(i,j) = vert.at<float>(i,j) + ct_V.at<float>(i-1,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1)
|
||||
{
|
||||
int no_of_iter = 3;
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
float sigma_h = sigma_s;
|
||||
|
||||
init(img,flags,sigma_s,sigma_r);
|
||||
|
||||
if(flags == 1)
|
||||
{
|
||||
Mat vert_t = vert.t();
|
||||
|
||||
for(int i=0;i<no_of_iter;i++)
|
||||
{
|
||||
sigma_h = (float) (sigma_s * sqrt(3.0) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1));
|
||||
|
||||
compute_Rfilter(O, horiz, sigma_h);
|
||||
|
||||
O_t = O.t();
|
||||
|
||||
compute_Rfilter(O_t, vert_t, sigma_h);
|
||||
|
||||
O = O_t.t();
|
||||
|
||||
}
|
||||
}
|
||||
else if(flags == 2)
|
||||
{
|
||||
|
||||
Mat vert_t = ct_V.t();
|
||||
Mat temp = Mat(h,w,CV_32FC1);
|
||||
Mat temp1 = Mat(w,h,CV_32FC1);
|
||||
|
||||
float radius;
|
||||
|
||||
for(int i=0;i<no_of_iter;i++)
|
||||
{
|
||||
sigma_h = (float) (sigma_s * sqrt(3.0) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1));
|
||||
|
||||
radius = (float) sqrt(3.0) * sigma_h;
|
||||
|
||||
compute_NCfilter(O, ct_H, temp,radius);
|
||||
|
||||
O_t = O.t();
|
||||
|
||||
compute_NCfilter(O_t, vert_t, temp1, radius);
|
||||
|
||||
O = O_t.t();
|
||||
}
|
||||
}
|
||||
|
||||
res = O.clone();
|
||||
}
|
||||
|
||||
void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor)
|
||||
{
|
||||
|
||||
int no_of_iter = 3;
|
||||
init(img,2,sigma_s,sigma_r);
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
|
||||
/////////////////////// convert to YCBCR model for color pencil drawing //////////////////////////////////////////////////////
|
||||
|
||||
Mat color_sketch = Mat(h,w,CV_32FC3);
|
||||
|
||||
cvtColor(img,color_sketch,COLOR_BGR2YCrCb);
|
||||
|
||||
vector <Mat> YUV_channel;
|
||||
Mat vert_t = ct_V.t();
|
||||
|
||||
float sigma_h = sigma_s;
|
||||
|
||||
Mat penx = Mat(h,w,CV_32FC1);
|
||||
|
||||
Mat pen_res = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat peny = Mat(w,h,CV_32FC1);
|
||||
|
||||
Mat peny_t;
|
||||
|
||||
float radius;
|
||||
|
||||
for(int i=0;i<no_of_iter;i++)
|
||||
{
|
||||
sigma_h = (float) (sigma_s * sqrt(3.0) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1));
|
||||
|
||||
radius = (float) sqrt(3.0) * sigma_h;
|
||||
|
||||
compute_boxfilter(O, ct_H, penx, radius);
|
||||
|
||||
O_t = O.t();
|
||||
|
||||
compute_boxfilter(O_t, vert_t, peny, radius);
|
||||
|
||||
O = O_t.t();
|
||||
|
||||
peny_t = peny.t();
|
||||
|
||||
for(int k=0;k<h;k++)
|
||||
for(int j=0;j<w;j++)
|
||||
pen_res.at<float>(k,j) = (shade_factor * (penx.at<float>(k,j) + peny_t.at<float>(k,j)));
|
||||
|
||||
if(i==0)
|
||||
{
|
||||
sketch = pen_res.clone();
|
||||
split(color_sketch,YUV_channel);
|
||||
pen_res.copyTo(YUV_channel[0]);
|
||||
merge(YUV_channel,color_sketch);
|
||||
cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
302
3rdparty/opencv-4.5.4/modules/photo/src/opencl/nlmeans.cl
vendored
Normal file
302
3rdparty/opencv-4.5.4/modules/photo/src/opencl/nlmeans.cl
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
// 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.
|
||||
|
||||
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#ifdef cl_amd_printf
|
||||
#pragma OPENCL_EXTENSION cl_amd_printf:enable
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined cl_khr_fp64
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OP_CALC_WEIGHTS
|
||||
|
||||
__kernel void calcAlmostDist2Weight(__global wlut_t * almostDist2Weight, int almostMaxDist,
|
||||
FT almostDist2ActualDistMultiplier, int fixedPointMult,
|
||||
w_t den, FT WEIGHT_THRESHOLD)
|
||||
{
|
||||
int almostDist = get_global_id(0);
|
||||
|
||||
if (almostDist < almostMaxDist)
|
||||
{
|
||||
FT dist = almostDist * almostDist2ActualDistMultiplier;
|
||||
#ifdef ABS
|
||||
w_t w = exp((w_t)(-dist*dist) * den);
|
||||
#else
|
||||
w_t w = exp((w_t)(-dist) * den);
|
||||
#endif
|
||||
wlut_t weight = convert_wlut_t(fixedPointMult * (isnan(w) ? (w_t)1.0 : w));
|
||||
almostDist2Weight[almostDist] =
|
||||
weight < (wlut_t)(WEIGHT_THRESHOLD * fixedPointMult) ? (wlut_t)0 : weight;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined OP_CALC_FASTNLMEANS
|
||||
|
||||
#define noconvert
|
||||
|
||||
#define SEARCH_SIZE_SQ (SEARCH_SIZE * SEARCH_SIZE)
|
||||
|
||||
inline int calcDist(pixel_t a, pixel_t b)
|
||||
{
|
||||
#ifdef ABS
|
||||
int_t retval = convert_int_t(abs_diff(a, b));
|
||||
#else
|
||||
int_t diff = convert_int_t(a) - convert_int_t(b);
|
||||
int_t retval = diff * diff;
|
||||
#endif
|
||||
|
||||
#if cn == 1
|
||||
return retval;
|
||||
#elif cn == 2
|
||||
return retval.x + retval.y;
|
||||
#elif cn == 3
|
||||
return retval.x + retval.y + retval.z;
|
||||
#elif cn == 4
|
||||
return retval.x + retval.y + retval.z + retval.w;
|
||||
#else
|
||||
#error "cn should be either 1, 2, 3 or 4"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ABS
|
||||
inline int calcDistUpDown(pixel_t down_value, pixel_t down_value_t, pixel_t up_value, pixel_t up_value_t)
|
||||
{
|
||||
return calcDist(down_value, down_value_t) - calcDist(up_value, up_value_t);
|
||||
}
|
||||
#else
|
||||
inline int calcDistUpDown(pixel_t down_value, pixel_t down_value_t, pixel_t up_value, pixel_t up_value_t)
|
||||
{
|
||||
int_t A = convert_int_t(down_value) - convert_int_t(down_value_t);
|
||||
int_t B = convert_int_t(up_value) - convert_int_t(up_value_t);
|
||||
int_t retval = (A - B) * (A + B);
|
||||
|
||||
#if cn == 1
|
||||
return retval;
|
||||
#elif cn == 2
|
||||
return retval.x + retval.y;
|
||||
#elif cn == 3
|
||||
return retval.x + retval.y + retval.z;
|
||||
#elif cn == 4
|
||||
return retval.x + retval.y + retval.z + retval.w;
|
||||
#else
|
||||
#error "cn should be either 1, 2, 3 or 4"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#define COND if (x == 0 && y == 0)
|
||||
|
||||
inline void calcFirstElementInRow(__global const uchar * src, int src_step, int src_offset,
|
||||
__local int * dists, int y, int x, int id,
|
||||
__global int * col_dists, __global int * up_col_dists)
|
||||
{
|
||||
y -= TEMPLATE_SIZE2;
|
||||
int sx = x - SEARCH_SIZE2, sy = y - SEARCH_SIZE2;
|
||||
int col_dists_current_private[TEMPLATE_SIZE];
|
||||
|
||||
for (int i = id; i < SEARCH_SIZE_SQ; i += CTA_SIZE)
|
||||
{
|
||||
int dist = 0, value;
|
||||
|
||||
__global const pixel_t * src_template = (__global const pixel_t *)(src +
|
||||
mad24(sy + i / SEARCH_SIZE, src_step, mad24(psz, sx + i % SEARCH_SIZE, src_offset)));
|
||||
__global const pixel_t * src_current = (__global const pixel_t *)(src + mad24(y, src_step, mad24(psz, x, src_offset)));
|
||||
__global int * col_dists_current = col_dists + i * TEMPLATE_SIZE;
|
||||
|
||||
#pragma unroll
|
||||
for (int j = 0; j < TEMPLATE_SIZE; ++j)
|
||||
col_dists_current_private[j] = 0;
|
||||
|
||||
for (int ty = 0; ty < TEMPLATE_SIZE; ++ty)
|
||||
{
|
||||
#pragma unroll
|
||||
for (int tx = -TEMPLATE_SIZE2; tx <= TEMPLATE_SIZE2; ++tx)
|
||||
{
|
||||
value = calcDist(src_template[tx], src_current[tx]);
|
||||
|
||||
col_dists_current_private[tx + TEMPLATE_SIZE2] += value;
|
||||
dist += value;
|
||||
}
|
||||
|
||||
src_current = (__global const pixel_t *)((__global const uchar *)src_current + src_step);
|
||||
src_template = (__global const pixel_t *)((__global const uchar *)src_template + src_step);
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int j = 0; j < TEMPLATE_SIZE; ++j)
|
||||
col_dists_current[j] = col_dists_current_private[j];
|
||||
|
||||
dists[i] = dist;
|
||||
up_col_dists[0 + i] = col_dists[TEMPLATE_SIZE - 1];
|
||||
}
|
||||
}
|
||||
|
||||
inline void calcElementInFirstRow(__global const uchar * src, int src_step, int src_offset,
|
||||
__local int * dists, int y, int x0, int x, int id, int first,
|
||||
__global int * col_dists, __global int * up_col_dists)
|
||||
{
|
||||
x += TEMPLATE_SIZE2;
|
||||
y -= TEMPLATE_SIZE2;
|
||||
int sx = x - SEARCH_SIZE2, sy = y - SEARCH_SIZE2;
|
||||
|
||||
for (int i = id; i < SEARCH_SIZE_SQ; i += CTA_SIZE)
|
||||
{
|
||||
__global const pixel_t * src_current = (__global const pixel_t *)(src + mad24(y, src_step, mad24(psz, x, src_offset)));
|
||||
__global const pixel_t * src_template = (__global const pixel_t *)(src +
|
||||
mad24(sy + i / SEARCH_SIZE, src_step, mad24(psz, sx + i % SEARCH_SIZE, src_offset)));
|
||||
__global int * col_dists_current = col_dists + TEMPLATE_SIZE * i;
|
||||
|
||||
int col_dist = 0;
|
||||
|
||||
#pragma unroll
|
||||
for (int ty = 0; ty < TEMPLATE_SIZE; ++ty)
|
||||
{
|
||||
col_dist += calcDist(src_current[0], src_template[0]);
|
||||
|
||||
src_current = (__global const pixel_t *)((__global const uchar *)src_current + src_step);
|
||||
src_template = (__global const pixel_t *)((__global const uchar *)src_template + src_step);
|
||||
}
|
||||
|
||||
dists[i] += col_dist - col_dists_current[first];
|
||||
col_dists_current[first] = col_dist;
|
||||
up_col_dists[mad24(x0, SEARCH_SIZE_SQ, i)] = col_dist;
|
||||
}
|
||||
}
|
||||
|
||||
inline void calcElement(__global const uchar * src, int src_step, int src_offset,
|
||||
__local int * dists, int y, int x0, int x, int id, int first,
|
||||
__global int * col_dists, __global int * up_col_dists)
|
||||
{
|
||||
int sx = x + TEMPLATE_SIZE2;
|
||||
int sy_up = y - TEMPLATE_SIZE2 - 1;
|
||||
int sy_down = y + TEMPLATE_SIZE2;
|
||||
|
||||
pixel_t up_value = *(__global const pixel_t *)(src + mad24(sy_up, src_step, mad24(psz, sx, src_offset)));
|
||||
pixel_t down_value = *(__global const pixel_t *)(src + mad24(sy_down, src_step, mad24(psz, sx, src_offset)));
|
||||
|
||||
sx -= SEARCH_SIZE2;
|
||||
sy_up -= SEARCH_SIZE2;
|
||||
sy_down -= SEARCH_SIZE2;
|
||||
|
||||
for (int i = id; i < SEARCH_SIZE_SQ; i += CTA_SIZE)
|
||||
{
|
||||
int wx = i % SEARCH_SIZE, wy = i / SEARCH_SIZE;
|
||||
|
||||
pixel_t up_value_t = *(__global const pixel_t *)(src + mad24(sy_up + wy, src_step, mad24(psz, sx + wx, src_offset)));
|
||||
pixel_t down_value_t = *(__global const pixel_t *)(src + mad24(sy_down + wy, src_step, mad24(psz, sx + wx, src_offset)));
|
||||
|
||||
__global int * col_dists_current = col_dists + mad24(i, TEMPLATE_SIZE, first);
|
||||
__global int * up_col_dists_current = up_col_dists + mad24(x0, SEARCH_SIZE_SQ, i);
|
||||
|
||||
int col_dist = up_col_dists_current[0] + calcDistUpDown(down_value, down_value_t, up_value, up_value_t);
|
||||
|
||||
dists[i] += col_dist - col_dists_current[0];
|
||||
col_dists_current[0] = col_dist;
|
||||
up_col_dists_current[0] = col_dist;
|
||||
}
|
||||
}
|
||||
|
||||
inline void convolveWindow(__global const uchar * src, int src_step, int src_offset,
|
||||
__local int * dists, __global const wlut_t * almostDist2Weight,
|
||||
__global uchar * dst, int dst_step, int dst_offset,
|
||||
int y, int x, int id, __local weight_t * weights_local,
|
||||
__local sum_t * weighted_sum_local, int almostTemplateWindowSizeSqBinShift)
|
||||
{
|
||||
int sx = x - SEARCH_SIZE2, sy = y - SEARCH_SIZE2;
|
||||
weight_t weights = (weight_t)0;
|
||||
sum_t weighted_sum = (sum_t)0;
|
||||
|
||||
for (int i = id; i < SEARCH_SIZE_SQ; i += CTA_SIZE)
|
||||
{
|
||||
int src_index = mad24(sy + i / SEARCH_SIZE, src_step, mad24(i % SEARCH_SIZE + sx, psz, src_offset));
|
||||
sum_t src_value = convert_sum_t(*(__global const pixel_t *)(src + src_index));
|
||||
|
||||
int almostAvgDist = dists[i] >> almostTemplateWindowSizeSqBinShift;
|
||||
weight_t weight = convert_weight_t(almostDist2Weight[almostAvgDist]);
|
||||
|
||||
weights += weight;
|
||||
weighted_sum += (sum_t)weight * src_value;
|
||||
}
|
||||
|
||||
weights_local[id] = weights;
|
||||
weighted_sum_local[id] = weighted_sum;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int lsize = CTA_SIZE >> 1; lsize > 2; lsize >>= 1)
|
||||
{
|
||||
if (id < lsize)
|
||||
{
|
||||
int id2 = lsize + id;
|
||||
weights_local[id] += weights_local[id2];
|
||||
weighted_sum_local[id] += weighted_sum_local[id2];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
int dst_index = mad24(y, dst_step, mad24(psz, x, dst_offset));
|
||||
sum_t weighted_sum_local_0 = weighted_sum_local[0] + weighted_sum_local[1] +
|
||||
weighted_sum_local[2] + weighted_sum_local[3];
|
||||
weight_t weights_local_0 = weights_local[0] + weights_local[1] + weights_local[2] + weights_local[3];
|
||||
|
||||
*(__global pixel_t *)(dst + dst_index) = convert_pixel_t(weighted_sum_local_0 / (sum_t)weights_local_0);
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void fastNlMeansDenoising(__global const uchar * src, int src_step, int src_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__global const wlut_t * almostDist2Weight, __global uchar * buffer,
|
||||
int almostTemplateWindowSizeSqBinShift)
|
||||
{
|
||||
int block_x = get_group_id(0), nblocks_x = get_num_groups(0);
|
||||
int block_y = get_group_id(1);
|
||||
int id = get_local_id(0), first;
|
||||
|
||||
__local int dists[SEARCH_SIZE_SQ];
|
||||
__local weight_t weights[CTA_SIZE];
|
||||
__local sum_t weighted_sum[CTA_SIZE];
|
||||
|
||||
int x0 = block_x * BLOCK_COLS, x1 = min(x0 + BLOCK_COLS, dst_cols);
|
||||
int y0 = block_y * BLOCK_ROWS, y1 = min(y0 + BLOCK_ROWS, dst_rows);
|
||||
|
||||
// for each group we need SEARCH_SIZE_SQ * TEMPLATE_SIZE integer buffer for storing part column sum for current element
|
||||
// and SEARCH_SIZE_SQ * BLOCK_COLS integer buffer for storing last column sum for each element of search window of up row
|
||||
int block_data_start = SEARCH_SIZE_SQ * (mad24(block_y, dst_cols, x0) + mad24(block_y, nblocks_x, block_x) * TEMPLATE_SIZE);
|
||||
__global int * col_dists = (__global int *)(buffer + block_data_start * sizeof(int));
|
||||
__global int * up_col_dists = col_dists + SEARCH_SIZE_SQ * TEMPLATE_SIZE;
|
||||
|
||||
for (int y = y0; y < y1; ++y)
|
||||
for (int x = x0; x < x1; ++x)
|
||||
{
|
||||
if (x == x0)
|
||||
{
|
||||
calcFirstElementInRow(src, src_step, src_offset, dists, y, x, id, col_dists, up_col_dists);
|
||||
first = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y == y0)
|
||||
calcElementInFirstRow(src, src_step, src_offset, dists, y, x - x0, x, id, first, col_dists, up_col_dists);
|
||||
else
|
||||
calcElement(src, src_step, src_offset, dists, y, x - x0, x, id, first, col_dists, up_col_dists);
|
||||
|
||||
first = (first + 1) % TEMPLATE_SIZE;
|
||||
}
|
||||
|
||||
convolveWindow(src, src_step, src_offset, dists, almostDist2Weight, dst, dst_step, dst_offset,
|
||||
y, x, id, weights, weighted_sum, almostTemplateWindowSizeSqBinShift);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
52
3rdparty/opencv-4.5.4/modules/photo/src/precomp.hpp
vendored
Normal file
52
3rdparty/opencv-4.5.4/modules/photo/src/precomp.hpp
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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*/
|
||||
|
||||
#ifndef __OPENCV_PRECOMP_H__
|
||||
#define __OPENCV_PRECOMP_H__
|
||||
|
||||
#include "opencv2/core/private.hpp"
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#endif
|
||||
144
3rdparty/opencv-4.5.4/modules/photo/src/seamless_cloning.cpp
vendored
Normal file
144
3rdparty/opencv-4.5.4/modules/photo/src/seamless_cloning.cpp
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
|
||||
#include "seamless_cloning.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
static Mat checkMask(InputArray _mask, Size size)
|
||||
{
|
||||
Mat mask = _mask.getMat();
|
||||
Mat gray;
|
||||
if (mask.channels() > 1)
|
||||
cvtColor(mask, gray, COLOR_BGRA2GRAY);
|
||||
else
|
||||
{
|
||||
if (mask.empty())
|
||||
gray = Mat(size.height, size.width, CV_8UC1, Scalar(255));
|
||||
else
|
||||
mask.copyTo(gray);
|
||||
}
|
||||
|
||||
return gray;
|
||||
}
|
||||
|
||||
void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
const Mat src = _src.getMat();
|
||||
const Mat dest = _dst.getMat();
|
||||
Mat mask = checkMask(_mask, src.size());
|
||||
dest.copyTo(_blend);
|
||||
Mat blend = _blend.getMat();
|
||||
|
||||
Mat mask_inner = mask(Rect(1, 1, mask.cols - 2, mask.rows - 2));
|
||||
copyMakeBorder(mask_inner, mask, 1, 1, 1, 1, BORDER_ISOLATED | BORDER_CONSTANT, Scalar(0));
|
||||
|
||||
Rect roi_s = boundingRect(mask);
|
||||
if (roi_s.empty()) return;
|
||||
Rect roi_d(p.x - roi_s.width / 2, p.y - roi_s.height / 2, roi_s.width, roi_s.height);
|
||||
|
||||
Mat destinationROI = dest(roi_d).clone();
|
||||
|
||||
Mat sourceROI = Mat::zeros(roi_s.height, roi_s.width, src.type());
|
||||
src(roi_s).copyTo(sourceROI,mask(roi_s));
|
||||
|
||||
Mat maskROI = mask(roi_s);
|
||||
Mat recoveredROI = blend(roi_d);
|
||||
|
||||
Cloning obj;
|
||||
obj.normalClone(destinationROI,sourceROI,maskROI,recoveredROI,flags);
|
||||
}
|
||||
|
||||
void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float red, float green, float blue)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat mask = checkMask(_mask, src.size());
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat blend = _dst.getMat();
|
||||
|
||||
Mat cs_mask = Mat::zeros(src.size(), src.type());
|
||||
src.copyTo(cs_mask, mask);
|
||||
|
||||
Cloning obj;
|
||||
obj.localColorChange(src, cs_mask, mask, blend, red, green, blue);
|
||||
}
|
||||
|
||||
void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float alpha, float beta)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat mask = checkMask(_mask, src.size());
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat blend = _dst.getMat();
|
||||
|
||||
Mat cs_mask = Mat::zeros(src.size(), src.type());
|
||||
src.copyTo(cs_mask, mask);
|
||||
|
||||
Cloning obj;
|
||||
obj.illuminationChange(src, cs_mask, mask, blend, alpha, beta);
|
||||
|
||||
}
|
||||
|
||||
void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
|
||||
float low_threshold, float high_threshold, int kernel_size)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat mask = checkMask(_mask, src.size());
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat blend = _dst.getMat();
|
||||
|
||||
Mat cs_mask = Mat::zeros(src.size(), src.type());
|
||||
src.copyTo(cs_mask, mask);
|
||||
|
||||
Cloning obj;
|
||||
obj.textureFlatten(src, cs_mask, mask, low_threshold, high_threshold, kernel_size, blend);
|
||||
}
|
||||
89
3rdparty/opencv-4.5.4/modules/photo/src/seamless_cloning.hpp
vendored
Normal file
89
3rdparty/opencv-4.5.4/modules/photo/src/seamless_cloning.hpp
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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*/
|
||||
|
||||
#ifndef CV_SEAMLESS_CLONING_HPP___
|
||||
#define CV_SEAMLESS_CLONING_HPP___
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class Cloning
|
||||
{
|
||||
public:
|
||||
void normalClone(const cv::Mat& destination, const cv::Mat &mask, const cv::Mat &wmask, cv::Mat &cloned, int flag);
|
||||
void illuminationChange(cv::Mat &I, cv::Mat &mask, cv::Mat &wmask, cv::Mat &cloned, float alpha, float beta);
|
||||
void localColorChange(cv::Mat &I, cv::Mat &mask, cv::Mat &wmask, cv::Mat &cloned, float red_mul, float green_mul, float blue_mul);
|
||||
void textureFlatten(cv::Mat &I, cv::Mat &mask, cv::Mat &wmask, float low_threshold, float high_threhold, int kernel_size, cv::Mat &cloned);
|
||||
|
||||
protected:
|
||||
|
||||
void initVariables(const cv::Mat &destination, const cv::Mat &binaryMask);
|
||||
void computeDerivatives(const cv::Mat &destination, const cv::Mat &patch, const cv::Mat &binaryMask);
|
||||
void scalarProduct(cv::Mat mat, float r, float g, float b);
|
||||
void poisson(const cv::Mat &destination);
|
||||
void evaluate(const cv::Mat &I, const cv::Mat &wmask, const cv::Mat &cloned);
|
||||
void dst(const Mat& src, Mat& dest, bool invert = false);
|
||||
void solve(const Mat &img, Mat& mod_diff, Mat &result);
|
||||
|
||||
void poissonSolver(const cv::Mat &img, cv::Mat &gxx , cv::Mat &gyy, cv::Mat &result);
|
||||
|
||||
void arrayProduct(const cv::Mat& lhs, const cv::Mat& rhs, cv::Mat& result) const;
|
||||
|
||||
void computeGradientX(const cv::Mat &img, cv::Mat &gx);
|
||||
void computeGradientY(const cv::Mat &img, cv::Mat &gy);
|
||||
void computeLaplacianX(const cv::Mat &img, cv::Mat &gxx);
|
||||
void computeLaplacianY(const cv::Mat &img, cv::Mat &gyy);
|
||||
|
||||
private:
|
||||
std::vector <cv::Mat> rgbx_channel, rgby_channel, output;
|
||||
cv::Mat destinationGradientX, destinationGradientY;
|
||||
cv::Mat patchGradientX, patchGradientY;
|
||||
cv::Mat binaryMaskFloat, binaryMaskFloatInverted;
|
||||
|
||||
std::vector<float> filter_X, filter_Y;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
453
3rdparty/opencv-4.5.4/modules/photo/src/seamless_cloning_impl.cpp
vendored
Normal file
453
3rdparty/opencv-4.5.4/modules/photo/src/seamless_cloning_impl.cpp
vendored
Normal file
@ -0,0 +1,453 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "seamless_cloning.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
void Cloning::computeGradientX( const Mat &img, Mat &gx)
|
||||
{
|
||||
Mat kernel = Mat::zeros(1, 3, CV_8S);
|
||||
kernel.at<char>(0,2) = 1;
|
||||
kernel.at<char>(0,1) = -1;
|
||||
|
||||
if(img.channels() == 3)
|
||||
{
|
||||
filter2D(img, gx, CV_32F, kernel);
|
||||
}
|
||||
else if (img.channels() == 1)
|
||||
{
|
||||
filter2D(img, gx, CV_32F, kernel);
|
||||
cvtColor(gx, gx, COLOR_GRAY2BGR);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::computeGradientY( const Mat &img, Mat &gy)
|
||||
{
|
||||
Mat kernel = Mat::zeros(3, 1, CV_8S);
|
||||
kernel.at<char>(2,0) = 1;
|
||||
kernel.at<char>(1,0) = -1;
|
||||
|
||||
if(img.channels() == 3)
|
||||
{
|
||||
filter2D(img, gy, CV_32F, kernel);
|
||||
}
|
||||
else if (img.channels() == 1)
|
||||
{
|
||||
filter2D(img, gy, CV_32F, kernel);
|
||||
cvtColor(gy, gy, COLOR_GRAY2BGR);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::computeLaplacianX( const Mat &img, Mat &laplacianX)
|
||||
{
|
||||
Mat kernel = Mat::zeros(1, 3, CV_8S);
|
||||
kernel.at<char>(0,0) = -1;
|
||||
kernel.at<char>(0,1) = 1;
|
||||
filter2D(img, laplacianX, CV_32F, kernel);
|
||||
}
|
||||
|
||||
void Cloning::computeLaplacianY( const Mat &img, Mat &laplacianY)
|
||||
{
|
||||
Mat kernel = Mat::zeros(3, 1, CV_8S);
|
||||
kernel.at<char>(0,0) = -1;
|
||||
kernel.at<char>(1,0) = 1;
|
||||
filter2D(img, laplacianY, CV_32F, kernel);
|
||||
}
|
||||
|
||||
void Cloning::dst(const Mat& src, Mat& dest, bool invert)
|
||||
{
|
||||
Mat temp = Mat::zeros(src.rows, 2 * src.cols + 2, CV_32F);
|
||||
|
||||
int flag = invert ? DFT_ROWS + DFT_SCALE + DFT_INVERSE: DFT_ROWS;
|
||||
|
||||
src.copyTo(temp(Rect(1,0, src.cols, src.rows)));
|
||||
|
||||
for(int j = 0 ; j < src.rows ; ++j)
|
||||
{
|
||||
float * tempLinePtr = temp.ptr<float>(j);
|
||||
const float * srcLinePtr = src.ptr<float>(j);
|
||||
for(int i = 0 ; i < src.cols ; ++i)
|
||||
{
|
||||
tempLinePtr[src.cols + 2 + i] = - srcLinePtr[src.cols - 1 - i];
|
||||
}
|
||||
}
|
||||
|
||||
Mat planes[] = {temp, Mat::zeros(temp.size(), CV_32F)};
|
||||
Mat complex;
|
||||
|
||||
merge(planes, 2, complex);
|
||||
dft(complex, complex, flag);
|
||||
split(complex, planes);
|
||||
temp = Mat::zeros(src.cols, 2 * src.rows + 2, CV_32F);
|
||||
|
||||
for(int j = 0 ; j < src.cols ; ++j)
|
||||
{
|
||||
float * tempLinePtr = temp.ptr<float>(j);
|
||||
for(int i = 0 ; i < src.rows ; ++i)
|
||||
{
|
||||
float val = planes[1].ptr<float>(i)[j + 1];
|
||||
tempLinePtr[i + 1] = val;
|
||||
tempLinePtr[temp.cols - 1 - i] = - val;
|
||||
}
|
||||
}
|
||||
|
||||
Mat planes2[] = {temp, Mat::zeros(temp.size(), CV_32F)};
|
||||
|
||||
merge(planes2, 2, complex);
|
||||
dft(complex, complex, flag);
|
||||
split(complex, planes2);
|
||||
|
||||
temp = planes2[1].t();
|
||||
temp(Rect( 0, 1, src.cols, src.rows)).copyTo(dest);
|
||||
}
|
||||
|
||||
void Cloning::solve(const Mat &img, Mat& mod_diff, Mat &result)
|
||||
{
|
||||
const int w = img.cols;
|
||||
const int h = img.rows;
|
||||
|
||||
Mat res;
|
||||
dst(mod_diff, res);
|
||||
|
||||
for(int j = 0 ; j < h-2; j++)
|
||||
{
|
||||
float * resLinePtr = res.ptr<float>(j);
|
||||
for(int i = 0 ; i < w-2; i++)
|
||||
{
|
||||
resLinePtr[i] /= (filter_X[i] + filter_Y[j] - 4);
|
||||
}
|
||||
}
|
||||
|
||||
dst(res, mod_diff, true);
|
||||
|
||||
unsigned char * resLinePtr = result.ptr<unsigned char>(0);
|
||||
const unsigned char * imgLinePtr = img.ptr<unsigned char>(0);
|
||||
const float * interpLinePtr = NULL;
|
||||
|
||||
//first col
|
||||
for(int i = 0 ; i < w ; ++i)
|
||||
result.ptr<unsigned char>(0)[i] = img.ptr<unsigned char>(0)[i];
|
||||
|
||||
for(int j = 1 ; j < h-1 ; ++j)
|
||||
{
|
||||
resLinePtr = result.ptr<unsigned char>(j);
|
||||
imgLinePtr = img.ptr<unsigned char>(j);
|
||||
interpLinePtr = mod_diff.ptr<float>(j-1);
|
||||
|
||||
//first row
|
||||
resLinePtr[0] = imgLinePtr[0];
|
||||
|
||||
for(int i = 1 ; i < w-1 ; ++i)
|
||||
{
|
||||
//saturate cast is not used here, because it behaves differently from the previous implementation
|
||||
//most notable, saturate_cast rounds before truncating, here it's the opposite.
|
||||
float value = interpLinePtr[i-1];
|
||||
if(value < 0.)
|
||||
resLinePtr[i] = 0;
|
||||
else if (value > 255.0)
|
||||
resLinePtr[i] = 255;
|
||||
else
|
||||
resLinePtr[i] = static_cast<unsigned char>(value);
|
||||
}
|
||||
|
||||
//last row
|
||||
resLinePtr[w-1] = imgLinePtr[w-1];
|
||||
}
|
||||
|
||||
//last col
|
||||
resLinePtr = result.ptr<unsigned char>(h-1);
|
||||
imgLinePtr = img.ptr<unsigned char>(h-1);
|
||||
for(int i = 0 ; i < w ; ++i)
|
||||
resLinePtr[i] = imgLinePtr[i];
|
||||
}
|
||||
|
||||
void Cloning::poissonSolver(const Mat &img, Mat &laplacianX , Mat &laplacianY, Mat &result)
|
||||
{
|
||||
const int w = img.cols;
|
||||
const int h = img.rows;
|
||||
|
||||
Mat lap = laplacianX + laplacianY;
|
||||
|
||||
Mat bound = img.clone();
|
||||
|
||||
rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1);
|
||||
Mat boundary_points;
|
||||
Laplacian(bound, boundary_points, CV_32F);
|
||||
|
||||
boundary_points = lap - boundary_points;
|
||||
|
||||
Mat mod_diff = boundary_points(Rect(1, 1, w-2, h-2));
|
||||
|
||||
solve(img,mod_diff,result);
|
||||
}
|
||||
|
||||
void Cloning::initVariables(const Mat &destination, const Mat &binaryMask)
|
||||
{
|
||||
destinationGradientX = Mat(destination.size(),CV_32FC3);
|
||||
destinationGradientY = Mat(destination.size(),CV_32FC3);
|
||||
patchGradientX = Mat(destination.size(),CV_32FC3);
|
||||
patchGradientY = Mat(destination.size(),CV_32FC3);
|
||||
|
||||
binaryMaskFloat = Mat(binaryMask.size(),CV_32FC1);
|
||||
binaryMaskFloatInverted = Mat(binaryMask.size(),CV_32FC1);
|
||||
|
||||
//init of the filters used in the dst
|
||||
const int w = destination.cols;
|
||||
filter_X.resize(w - 2);
|
||||
double scale = CV_PI / (w - 1);
|
||||
for(int i = 0 ; i < w-2 ; ++i)
|
||||
filter_X[i] = 2.0f * (float)std::cos(scale * (i + 1));
|
||||
|
||||
const int h = destination.rows;
|
||||
filter_Y.resize(h - 2);
|
||||
scale = CV_PI / (h - 1);
|
||||
for(int j = 0 ; j < h - 2 ; ++j)
|
||||
filter_Y[j] = 2.0f * (float)std::cos(scale * (j + 1));
|
||||
}
|
||||
|
||||
void Cloning::computeDerivatives(const Mat& destination, const Mat &patch, const Mat &binaryMask)
|
||||
{
|
||||
initVariables(destination, binaryMask);
|
||||
|
||||
computeGradientX(destination, destinationGradientX);
|
||||
computeGradientY(destination, destinationGradientY);
|
||||
|
||||
computeGradientX(patch, patchGradientX);
|
||||
computeGradientY(patch, patchGradientY);
|
||||
|
||||
Mat Kernel(Size(3, 3), CV_8UC1);
|
||||
Kernel.setTo(Scalar(1));
|
||||
erode(binaryMask, binaryMask, Kernel, Point(-1,-1), 3);
|
||||
|
||||
binaryMask.convertTo(binaryMaskFloat, CV_32FC1, 1.0/255.0);
|
||||
}
|
||||
|
||||
void Cloning::scalarProduct(Mat mat, float r, float g, float b)
|
||||
{
|
||||
vector <Mat> channels;
|
||||
split(mat,channels);
|
||||
multiply(channels[2],r,channels[2]);
|
||||
multiply(channels[1],g,channels[1]);
|
||||
multiply(channels[0],b,channels[0]);
|
||||
merge(channels,mat);
|
||||
}
|
||||
|
||||
void Cloning::arrayProduct(const cv::Mat& lhs, const cv::Mat& rhs, cv::Mat& result) const
|
||||
{
|
||||
vector <Mat> lhs_channels;
|
||||
vector <Mat> result_channels;
|
||||
|
||||
split(lhs,lhs_channels);
|
||||
split(result,result_channels);
|
||||
|
||||
for(int chan = 0 ; chan < 3 ; ++chan)
|
||||
multiply(lhs_channels[chan],rhs,result_channels[chan]);
|
||||
|
||||
merge(result_channels,result);
|
||||
}
|
||||
|
||||
void Cloning::poisson(const Mat &destination)
|
||||
{
|
||||
Mat laplacianX = destinationGradientX + patchGradientX;
|
||||
Mat laplacianY = destinationGradientY + patchGradientY;
|
||||
|
||||
computeLaplacianX(laplacianX,laplacianX);
|
||||
computeLaplacianY(laplacianY,laplacianY);
|
||||
|
||||
split(laplacianX,rgbx_channel);
|
||||
split(laplacianY,rgby_channel);
|
||||
|
||||
split(destination,output);
|
||||
|
||||
for(int chan = 0 ; chan < 3 ; ++chan)
|
||||
{
|
||||
poissonSolver(output[chan], rgbx_channel[chan], rgby_channel[chan], output[chan]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::evaluate(const Mat &I, const Mat &wmask, const Mat &cloned)
|
||||
{
|
||||
bitwise_not(wmask,wmask);
|
||||
|
||||
wmask.convertTo(binaryMaskFloatInverted,CV_32FC1,1.0/255.0);
|
||||
|
||||
arrayProduct(destinationGradientX, binaryMaskFloatInverted, destinationGradientX);
|
||||
arrayProduct(destinationGradientY, binaryMaskFloatInverted, destinationGradientY);
|
||||
|
||||
poisson(I);
|
||||
|
||||
merge(output,cloned);
|
||||
}
|
||||
|
||||
void Cloning::normalClone(const Mat &destination, const Mat &patch, const Mat &binaryMask, Mat &cloned, int flag)
|
||||
{
|
||||
const int w = destination.cols;
|
||||
const int h = destination.rows;
|
||||
const int channel = destination.channels();
|
||||
const int n_elem_in_line = w * channel;
|
||||
|
||||
computeDerivatives(destination,patch,binaryMask);
|
||||
|
||||
switch(flag)
|
||||
{
|
||||
case NORMAL_CLONE:
|
||||
arrayProduct(patchGradientX, binaryMaskFloat, patchGradientX);
|
||||
arrayProduct(patchGradientY, binaryMaskFloat, patchGradientY);
|
||||
break;
|
||||
|
||||
case MIXED_CLONE:
|
||||
{
|
||||
AutoBuffer<int> maskIndices(n_elem_in_line);
|
||||
for (int i = 0; i < n_elem_in_line; ++i)
|
||||
maskIndices[i] = i / channel;
|
||||
|
||||
for(int i=0;i < h; i++)
|
||||
{
|
||||
float * patchXLinePtr = patchGradientX.ptr<float>(i);
|
||||
float * patchYLinePtr = patchGradientY.ptr<float>(i);
|
||||
const float * destinationXLinePtr = destinationGradientX.ptr<float>(i);
|
||||
const float * destinationYLinePtr = destinationGradientY.ptr<float>(i);
|
||||
const float * binaryMaskLinePtr = binaryMaskFloat.ptr<float>(i);
|
||||
|
||||
for(int j=0; j < n_elem_in_line; j++)
|
||||
{
|
||||
int maskIndex = maskIndices[j];
|
||||
|
||||
if(abs(patchXLinePtr[j] - patchYLinePtr[j]) >
|
||||
abs(destinationXLinePtr[j] - destinationYLinePtr[j]))
|
||||
{
|
||||
patchXLinePtr[j] *= binaryMaskLinePtr[maskIndex];
|
||||
patchYLinePtr[j] *= binaryMaskLinePtr[maskIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
patchXLinePtr[j] = destinationXLinePtr[j]
|
||||
* binaryMaskLinePtr[maskIndex];
|
||||
patchYLinePtr[j] = destinationYLinePtr[j]
|
||||
* binaryMaskLinePtr[maskIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MONOCHROME_TRANSFER:
|
||||
Mat gray;
|
||||
cvtColor(patch, gray, COLOR_BGR2GRAY );
|
||||
|
||||
computeGradientX(gray,patchGradientX);
|
||||
computeGradientY(gray,patchGradientY);
|
||||
|
||||
arrayProduct(patchGradientX, binaryMaskFloat, patchGradientX);
|
||||
arrayProduct(patchGradientY, binaryMaskFloat, patchGradientY);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
evaluate(destination,binaryMask,cloned);
|
||||
}
|
||||
|
||||
void Cloning::localColorChange(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul=1.0,
|
||||
float green_mul=1.0, float blue_mul=1.0)
|
||||
{
|
||||
computeDerivatives(I,mask,wmask);
|
||||
|
||||
arrayProduct(patchGradientX,binaryMaskFloat, patchGradientX);
|
||||
arrayProduct(patchGradientY,binaryMaskFloat, patchGradientY);
|
||||
scalarProduct(patchGradientX,red_mul,green_mul,blue_mul);
|
||||
scalarProduct(patchGradientY,red_mul,green_mul,blue_mul);
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
||||
|
||||
void Cloning::illuminationChange(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
computeDerivatives(I,mask,wmask);
|
||||
|
||||
arrayProduct(patchGradientX,binaryMaskFloat, patchGradientX);
|
||||
arrayProduct(patchGradientY,binaryMaskFloat, patchGradientY);
|
||||
|
||||
Mat mag;
|
||||
magnitude(patchGradientX,patchGradientY,mag);
|
||||
|
||||
Mat multX, multY, multx_temp, multy_temp;
|
||||
|
||||
multiply(patchGradientX,pow(alpha,beta),multX);
|
||||
pow(mag,-1*beta, multx_temp);
|
||||
multiply(multX,multx_temp, patchGradientX);
|
||||
patchNaNs(patchGradientX);
|
||||
|
||||
multiply(patchGradientY,pow(alpha,beta),multY);
|
||||
pow(mag,-1*beta, multy_temp);
|
||||
multiply(multY,multy_temp,patchGradientY);
|
||||
patchNaNs(patchGradientY);
|
||||
|
||||
Mat zeroMask = (patchGradientX != 0);
|
||||
|
||||
patchGradientX.copyTo(patchGradientX, zeroMask);
|
||||
patchGradientY.copyTo(patchGradientY, zeroMask);
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
||||
|
||||
void Cloning::textureFlatten(Mat &I, Mat &mask, Mat &wmask, float low_threshold,
|
||||
float high_threshold, int kernel_size, Mat &cloned)
|
||||
{
|
||||
computeDerivatives(I,mask,wmask);
|
||||
|
||||
Mat out;
|
||||
Canny(mask,out,low_threshold,high_threshold,kernel_size);
|
||||
|
||||
Mat zeros = Mat::zeros(patchGradientX.size(), CV_32FC3);
|
||||
Mat zerosMask = (out != 255);
|
||||
zeros.copyTo(patchGradientX, zerosMask);
|
||||
zeros.copyTo(patchGradientY, zerosMask);
|
||||
|
||||
arrayProduct(patchGradientX,binaryMaskFloat, patchGradientX);
|
||||
arrayProduct(patchGradientY,binaryMaskFloat, patchGradientY);
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
||||
472
3rdparty/opencv-4.5.4/modules/photo/src/tonemap.cpp
vendored
Normal file
472
3rdparty/opencv-4.5.4/modules/photo/src/tonemap.cpp
vendored
Normal file
@ -0,0 +1,472 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "precomp.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "hdr_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
inline void log_(const Mat& src, Mat& dst)
|
||||
{
|
||||
max(src, Scalar::all(1e-4), dst);
|
||||
log(dst, dst);
|
||||
}
|
||||
|
||||
class TonemapImpl CV_FINAL : public Tonemap
|
||||
{
|
||||
public:
|
||||
TonemapImpl(float _gamma) : name("Tonemap"), gamma(_gamma)
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArray _src, OutputArray _dst) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(!src.empty());
|
||||
CV_Assert(_src.dims() == 2 && _src.type() == CV_32FC3);
|
||||
_dst.create(src.size(), CV_32FC3);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
double min, max;
|
||||
minMaxLoc(src, &min, &max);
|
||||
if(max - min > DBL_EPSILON) {
|
||||
dst = (src - min) / (max - min);
|
||||
} else {
|
||||
src.copyTo(dst);
|
||||
}
|
||||
|
||||
pow(dst, 1.0f / gamma, dst);
|
||||
}
|
||||
|
||||
float getGamma() const CV_OVERRIDE { return gamma; }
|
||||
void setGamma(float val) CV_OVERRIDE { gamma = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "gamma" << gamma;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
gamma = fn["gamma"];
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
float gamma;
|
||||
};
|
||||
|
||||
Ptr<Tonemap> createTonemap(float gamma)
|
||||
{
|
||||
return makePtr<TonemapImpl>(gamma);
|
||||
}
|
||||
|
||||
class TonemapDragoImpl CV_FINAL : public TonemapDrago
|
||||
{
|
||||
public:
|
||||
TonemapDragoImpl(float _gamma, float _saturation, float _bias) :
|
||||
name("TonemapDrago"),
|
||||
gamma(_gamma),
|
||||
saturation(_saturation),
|
||||
bias(_bias)
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArray _src, OutputArray _dst) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(!src.empty());
|
||||
_dst.create(src.size(), CV_32FC3);
|
||||
Mat img = _dst.getMat();
|
||||
|
||||
Ptr<Tonemap> linear = createTonemap(1.0f);
|
||||
linear->process(src, img);
|
||||
|
||||
Mat gray_img;
|
||||
cvtColor(img, gray_img, COLOR_RGB2GRAY);
|
||||
Mat log_img;
|
||||
log_(gray_img, log_img);
|
||||
float mean = expf(static_cast<float>(sum(log_img)[0]) / log_img.total());
|
||||
gray_img /= mean;
|
||||
log_img.release();
|
||||
|
||||
double max;
|
||||
minMaxLoc(gray_img, NULL, &max);
|
||||
CV_Assert(max > 0);
|
||||
|
||||
Mat map;
|
||||
log(gray_img + 1.0f, map);
|
||||
Mat div;
|
||||
pow(gray_img / static_cast<float>(max), logf(bias) / logf(0.5f), div);
|
||||
log(2.0f + 8.0f * div, div);
|
||||
map = map.mul(1.0f / div);
|
||||
div.release();
|
||||
|
||||
mapLuminance(img, img, gray_img, map, saturation);
|
||||
|
||||
linear->setGamma(gamma);
|
||||
linear->process(img, img);
|
||||
}
|
||||
|
||||
float getGamma() const CV_OVERRIDE { return gamma; }
|
||||
void setGamma(float val) CV_OVERRIDE { gamma = val; }
|
||||
|
||||
float getSaturation() const CV_OVERRIDE { return saturation; }
|
||||
void setSaturation(float val) CV_OVERRIDE { saturation = val; }
|
||||
|
||||
float getBias() const CV_OVERRIDE { return bias; }
|
||||
void setBias(float val) CV_OVERRIDE { bias = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "gamma" << gamma
|
||||
<< "bias" << bias
|
||||
<< "saturation" << saturation;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
gamma = fn["gamma"];
|
||||
bias = fn["bias"];
|
||||
saturation = fn["saturation"];
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
float gamma, saturation, bias;
|
||||
};
|
||||
|
||||
Ptr<TonemapDrago> createTonemapDrago(float gamma, float saturation, float bias)
|
||||
{
|
||||
return makePtr<TonemapDragoImpl>(gamma, saturation, bias);
|
||||
}
|
||||
|
||||
class TonemapReinhardImpl CV_FINAL : public TonemapReinhard
|
||||
{
|
||||
public:
|
||||
TonemapReinhardImpl(float _gamma, float _intensity, float _light_adapt, float _color_adapt) :
|
||||
name("TonemapReinhard"),
|
||||
gamma(_gamma),
|
||||
intensity(_intensity),
|
||||
light_adapt(_light_adapt),
|
||||
color_adapt(_color_adapt)
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArray _src, OutputArray _dst) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(!src.empty());
|
||||
_dst.create(src.size(), CV_32FC3);
|
||||
Mat img = _dst.getMat();
|
||||
Ptr<Tonemap> linear = createTonemap(1.0f);
|
||||
linear->process(src, img);
|
||||
|
||||
Mat gray_img;
|
||||
cvtColor(img, gray_img, COLOR_RGB2GRAY);
|
||||
Mat log_img;
|
||||
log_(gray_img, log_img);
|
||||
|
||||
float log_mean = static_cast<float>(sum(log_img)[0] / log_img.total());
|
||||
double log_min, log_max;
|
||||
minMaxLoc(log_img, &log_min, &log_max);
|
||||
log_img.release();
|
||||
|
||||
double key = static_cast<float>((log_max - log_mean) / (log_max - log_min));
|
||||
float map_key = 0.3f + 0.7f * pow(static_cast<float>(key), 1.4f);
|
||||
intensity = exp(-intensity);
|
||||
Scalar chan_mean = mean(img);
|
||||
float gray_mean = static_cast<float>(mean(gray_img)[0]);
|
||||
|
||||
std::vector<Mat> channels(3);
|
||||
split(img, channels);
|
||||
|
||||
for(int i = 0; i < 3; i++) {
|
||||
float global = color_adapt * static_cast<float>(chan_mean[i]) + (1.0f - color_adapt) * gray_mean;
|
||||
Mat adapt = color_adapt * channels[i] + (1.0f - color_adapt) * gray_img;
|
||||
adapt = light_adapt * adapt + (1.0f - light_adapt) * global;
|
||||
pow(intensity * adapt, map_key, adapt);
|
||||
channels[i] = channels[i].mul(1.0f / (adapt + channels[i]));
|
||||
}
|
||||
gray_img.release();
|
||||
merge(channels, img);
|
||||
|
||||
linear->setGamma(gamma);
|
||||
linear->process(img, img);
|
||||
}
|
||||
|
||||
float getGamma() const CV_OVERRIDE { return gamma; }
|
||||
void setGamma(float val) CV_OVERRIDE { gamma = val; }
|
||||
|
||||
float getIntensity() const CV_OVERRIDE { return intensity; }
|
||||
void setIntensity(float val) CV_OVERRIDE { intensity = val; }
|
||||
|
||||
float getLightAdaptation() const CV_OVERRIDE { return light_adapt; }
|
||||
void setLightAdaptation(float val) CV_OVERRIDE { light_adapt = val; }
|
||||
|
||||
float getColorAdaptation() const CV_OVERRIDE { return color_adapt; }
|
||||
void setColorAdaptation(float val) CV_OVERRIDE { color_adapt = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "gamma" << gamma
|
||||
<< "intensity" << intensity
|
||||
<< "light_adapt" << light_adapt
|
||||
<< "color_adapt" << color_adapt;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
gamma = fn["gamma"];
|
||||
intensity = fn["intensity"];
|
||||
light_adapt = fn["light_adapt"];
|
||||
color_adapt = fn["color_adapt"];
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
float gamma, intensity, light_adapt, color_adapt;
|
||||
};
|
||||
|
||||
Ptr<TonemapReinhard> createTonemapReinhard(float gamma, float contrast, float sigma_color, float sigma_space)
|
||||
{
|
||||
return makePtr<TonemapReinhardImpl>(gamma, contrast, sigma_color, sigma_space);
|
||||
}
|
||||
|
||||
class TonemapMantiukImpl CV_FINAL : public TonemapMantiuk
|
||||
{
|
||||
public:
|
||||
TonemapMantiukImpl(float _gamma, float _scale, float _saturation) :
|
||||
name("TonemapMantiuk"),
|
||||
gamma(_gamma),
|
||||
scale(_scale),
|
||||
saturation(_saturation)
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArray _src, OutputArray _dst) CV_OVERRIDE
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(!src.empty());
|
||||
_dst.create(src.size(), CV_32FC3);
|
||||
Mat img = _dst.getMat();
|
||||
Ptr<Tonemap> linear = createTonemap(1.0f);
|
||||
linear->process(src, img);
|
||||
|
||||
Mat gray_img;
|
||||
cvtColor(img, gray_img, COLOR_RGB2GRAY);
|
||||
Mat log_img;
|
||||
log_(gray_img, log_img);
|
||||
|
||||
std::vector<Mat> x_contrast, y_contrast;
|
||||
getContrast(log_img, x_contrast, y_contrast);
|
||||
|
||||
for(size_t i = 0; i < x_contrast.size(); i++) {
|
||||
mapContrast(x_contrast[i]);
|
||||
mapContrast(y_contrast[i]);
|
||||
}
|
||||
|
||||
Mat right(src.size(), CV_32F);
|
||||
calculateSum(x_contrast, y_contrast, right);
|
||||
|
||||
Mat p, r, product, x = log_img;
|
||||
calculateProduct(x, r);
|
||||
r = right - r;
|
||||
r.copyTo(p);
|
||||
|
||||
const float target_error = 1e-3f;
|
||||
float target_norm = static_cast<float>(right.dot(right)) * powf(target_error, 2.0f);
|
||||
int max_iterations = 100;
|
||||
float rr = static_cast<float>(r.dot(r));
|
||||
|
||||
for(int i = 0; i < max_iterations; i++)
|
||||
{
|
||||
calculateProduct(p, product);
|
||||
double dprod = p.dot(product);
|
||||
CV_Assert(fabs(dprod) > 0);
|
||||
float alpha = rr / static_cast<float>(dprod);
|
||||
|
||||
r -= alpha * product;
|
||||
x += alpha * p;
|
||||
|
||||
float new_rr = static_cast<float>(r.dot(r));
|
||||
CV_Assert(fabs(rr) > 0);
|
||||
p = r + (new_rr / rr) * p;
|
||||
rr = new_rr;
|
||||
|
||||
if(rr < target_norm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
exp(x, x);
|
||||
mapLuminance(img, img, gray_img, x, saturation);
|
||||
|
||||
linear = createTonemap(gamma);
|
||||
linear->process(img, img);
|
||||
}
|
||||
|
||||
float getGamma() const CV_OVERRIDE { return gamma; }
|
||||
void setGamma(float val) CV_OVERRIDE { gamma = val; }
|
||||
|
||||
float getScale() const CV_OVERRIDE { return scale; }
|
||||
void setScale(float val) CV_OVERRIDE { scale = val; }
|
||||
|
||||
float getSaturation() const CV_OVERRIDE { return saturation; }
|
||||
void setSaturation(float val) CV_OVERRIDE { saturation = val; }
|
||||
|
||||
void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name
|
||||
<< "gamma" << gamma
|
||||
<< "scale" << scale
|
||||
<< "saturation" << saturation;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
gamma = fn["gamma"];
|
||||
scale = fn["scale"];
|
||||
saturation = fn["saturation"];
|
||||
}
|
||||
|
||||
protected:
|
||||
String name;
|
||||
float gamma, scale, saturation;
|
||||
|
||||
void signedPow(Mat src, float power, Mat& dst)
|
||||
{
|
||||
Mat sign = (src > 0);
|
||||
sign.convertTo(sign, CV_32F, 1.0f/255.0f);
|
||||
sign = sign * 2.0f - 1.0f;
|
||||
pow(abs(src), power, dst);
|
||||
dst = dst.mul(sign);
|
||||
}
|
||||
|
||||
void mapContrast(Mat& contrast)
|
||||
{
|
||||
const float response_power = 0.4185f;
|
||||
signedPow(contrast, response_power, contrast);
|
||||
contrast *= scale;
|
||||
signedPow(contrast, 1.0f / response_power, contrast);
|
||||
}
|
||||
|
||||
void getGradient(Mat src, Mat& dst, int pos)
|
||||
{
|
||||
dst = Mat::zeros(src.size(), CV_32F);
|
||||
Mat a, b;
|
||||
Mat grad = src.colRange(1, src.cols) - src.colRange(0, src.cols - 1);
|
||||
grad.copyTo(dst.colRange(pos, src.cols + pos - 1));
|
||||
if(pos == 1) {
|
||||
src.col(0).copyTo(dst.col(0));
|
||||
}
|
||||
}
|
||||
|
||||
void getContrast(Mat src, std::vector<Mat>& x_contrast, std::vector<Mat>& y_contrast)
|
||||
{
|
||||
int levels = static_cast<int>(logf(static_cast<float>(min(src.rows, src.cols))) / logf(2.0f));
|
||||
x_contrast.resize(levels);
|
||||
y_contrast.resize(levels);
|
||||
|
||||
Mat layer;
|
||||
src.copyTo(layer);
|
||||
for(int i = 0; i < levels; i++) {
|
||||
getGradient(layer, x_contrast[i], 0);
|
||||
getGradient(layer.t(), y_contrast[i], 0);
|
||||
resize(layer, layer, Size(layer.cols / 2, layer.rows / 2), 0, 0, INTER_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
void calculateSum(std::vector<Mat>& x_contrast, std::vector<Mat>& y_contrast, Mat& sum)
|
||||
{
|
||||
if (x_contrast.empty())
|
||||
return;
|
||||
const int last = (int)x_contrast.size() - 1;
|
||||
sum = Mat::zeros(x_contrast[last].size(), CV_32F);
|
||||
for(int i = last; i >= 0; i--)
|
||||
{
|
||||
Mat grad_x, grad_y;
|
||||
getGradient(x_contrast[i], grad_x, 1);
|
||||
getGradient(y_contrast[i], grad_y, 1);
|
||||
resize(sum, sum, x_contrast[i].size(), 0, 0, INTER_LINEAR);
|
||||
sum += grad_x + grad_y.t();
|
||||
}
|
||||
}
|
||||
|
||||
void calculateProduct(Mat src, Mat& dst)
|
||||
{
|
||||
std::vector<Mat> x_contrast, y_contrast;
|
||||
getContrast(src, x_contrast, y_contrast);
|
||||
calculateSum(x_contrast, y_contrast, dst);
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<TonemapMantiuk> createTonemapMantiuk(float gamma, float scale, float saturation)
|
||||
{
|
||||
return makePtr<TonemapMantiukImpl>(gamma, scale, saturation);
|
||||
}
|
||||
|
||||
}
|
||||
133
3rdparty/opencv-4.5.4/modules/photo/test/ocl/test_denoising.cpp
vendored
Normal file
133
3rdparty/opencv-4.5.4/modules/photo/test/ocl/test_denoising.cpp
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
// 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.
|
||||
|
||||
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(FastNlMeansDenoisingTestBase, Channels, int, bool, bool)
|
||||
{
|
||||
int cn, normType, templateWindowSize, searchWindowSize;
|
||||
std::vector<float> h;
|
||||
bool use_roi, use_image;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
cn = GET_PARAM(0);
|
||||
normType = GET_PARAM(1);
|
||||
use_roi = GET_PARAM(2);
|
||||
use_image = GET_PARAM(3);
|
||||
|
||||
templateWindowSize = 7;
|
||||
searchWindowSize = 21;
|
||||
|
||||
h.resize(cn);
|
||||
for (int i=0; i<cn; i++)
|
||||
h[i] = 3.0f + 0.5f*i;
|
||||
}
|
||||
|
||||
void generateTestData()
|
||||
{
|
||||
const int type = CV_8UC(cn);
|
||||
Mat image;
|
||||
|
||||
if (use_image) {
|
||||
image = readImage("denoising/lena_noised_gaussian_sigma=10.png",
|
||||
cn == 1 ? IMREAD_GRAYSCALE : IMREAD_COLOR);
|
||||
ASSERT_FALSE(image.empty());
|
||||
}
|
||||
|
||||
Size roiSize = use_image ? image.size() : randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 0, 255);
|
||||
if (use_image) {
|
||||
ASSERT_TRUE(cn > 0 && cn <= 4);
|
||||
if (cn == 2) {
|
||||
int from_to[] = { 0,0, 1,1 };
|
||||
src_roi.create(roiSize, type);
|
||||
mixChannels(&image, 1, &src_roi, 1, from_to, 2);
|
||||
}
|
||||
else if (cn == 4) {
|
||||
int from_to[] = { 0,0, 1,1, 2,2, 1,3};
|
||||
src_roi.create(roiSize, type);
|
||||
mixChannels(&image, 1, &src_roi, 1, from_to, 4);
|
||||
}
|
||||
else image.copyTo(src_roi);
|
||||
}
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 0, 255);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
typedef FastNlMeansDenoisingTestBase FastNlMeansDenoising;
|
||||
|
||||
OCL_TEST_P(FastNlMeansDenoising, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::fastNlMeansDenoising(src_roi, dst_roi, std::vector<float>(1, h[0]), templateWindowSize, searchWindowSize, normType));
|
||||
OCL_ON(cv::fastNlMeansDenoising(usrc_roi, udst_roi, std::vector<float>(1, h[0]), templateWindowSize, searchWindowSize, normType));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1);
|
||||
}
|
||||
}
|
||||
|
||||
typedef FastNlMeansDenoisingTestBase FastNlMeansDenoising_hsep;
|
||||
|
||||
OCL_TEST_P(FastNlMeansDenoising_hsep, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::fastNlMeansDenoising(src_roi, dst_roi, h, templateWindowSize, searchWindowSize, normType));
|
||||
OCL_ON(cv::fastNlMeansDenoising(usrc_roi, udst_roi, h, templateWindowSize, searchWindowSize, normType));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1);
|
||||
}
|
||||
}
|
||||
|
||||
typedef FastNlMeansDenoisingTestBase FastNlMeansDenoisingColored;
|
||||
|
||||
OCL_TEST_P(FastNlMeansDenoisingColored, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::fastNlMeansDenoisingColored(src_roi, dst_roi, h[0], h[0], templateWindowSize, searchWindowSize));
|
||||
OCL_ON(cv::fastNlMeansDenoisingColored(usrc_roi, udst_roi, h[0], h[0], templateWindowSize, searchWindowSize));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Photo, FastNlMeansDenoising,
|
||||
Combine(Values(1, 2, 3, 4), Values((int)NORM_L2, (int)NORM_L1),
|
||||
Bool(), Values(true)));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Photo, FastNlMeansDenoising_hsep,
|
||||
Combine(Values(1, 2, 3, 4), Values((int)NORM_L2, (int)NORM_L1),
|
||||
Bool(), Values(true)));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Photo, FastNlMeansDenoisingColored,
|
||||
Combine(Values(3, 4), Values((int)NORM_L2), Bool(), Values(false)));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
247
3rdparty/opencv-4.5.4/modules/photo/test/test_cloning.cpp
vendored
Normal file
247
3rdparty/opencv-4.5.4/modules/photo/test/test_cloning.cpp
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#define OUTPUT_SAVING 0
|
||||
#if OUTPUT_SAVING
|
||||
#define SAVE(x) std::vector<int> params;\
|
||||
params.push_back(16);\
|
||||
params.push_back(0);\
|
||||
imwrite(folder + "output.png", x ,params);
|
||||
#else
|
||||
#define SAVE(x)
|
||||
#endif
|
||||
|
||||
static const double numerical_precision = 0.05; // 95% of pixels should have exact values
|
||||
|
||||
TEST(Photo_SeamlessClone_normal, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Normal_Cloning/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "destination1.png";
|
||||
string original_path3 = folder + "mask.png";
|
||||
string reference_path = folder + "reference.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat destination = imread(original_path2, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path3, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3;
|
||||
|
||||
Mat result;
|
||||
Point p;
|
||||
p.x = destination.size().width/2;
|
||||
p.y = destination.size().height/2;
|
||||
seamlessClone(source, destination, mask, p, result, 1);
|
||||
|
||||
Mat reference = imread(reference_path);
|
||||
ASSERT_FALSE(reference.empty()) << "Could not load reference image " << reference_path;
|
||||
|
||||
SAVE(result);
|
||||
|
||||
double errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
double errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
|
||||
mask = Scalar(0, 0, 0);
|
||||
seamlessClone(source, destination, mask, p, result, 1);
|
||||
|
||||
reference = destination;
|
||||
errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_mixed, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Mixed_Cloning/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "destination1.png";
|
||||
string original_path3 = folder + "mask.png";
|
||||
string reference_path = folder + "reference.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat destination = imread(original_path2, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path3, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3;
|
||||
|
||||
Mat result;
|
||||
Point p;
|
||||
p.x = destination.size().width/2;
|
||||
p.y = destination.size().height/2;
|
||||
seamlessClone(source, destination, mask, p, result, 2);
|
||||
|
||||
SAVE(result);
|
||||
|
||||
Mat reference = imread(reference_path);
|
||||
ASSERT_FALSE(reference.empty()) << "Could not load reference image " << reference_path;
|
||||
|
||||
double errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
double errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_featureExchange, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Monochrome_Transfer/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "destination1.png";
|
||||
string original_path3 = folder + "mask.png";
|
||||
string reference_path = folder + "reference.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat destination = imread(original_path2, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path3, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3;
|
||||
|
||||
Mat result;
|
||||
Point p;
|
||||
p.x = destination.size().width/2;
|
||||
p.y = destination.size().height/2;
|
||||
seamlessClone(source, destination, mask, p, result, 3);
|
||||
|
||||
SAVE(result);
|
||||
|
||||
Mat reference = imread(reference_path);
|
||||
ASSERT_FALSE(reference.empty()) << "Could not load reference image " << reference_path;
|
||||
|
||||
double errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
double errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_colorChange, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/color_change/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "mask.png";
|
||||
string reference_path = folder + "reference.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||
|
||||
Mat result;
|
||||
colorChange(source, mask, result, 1.5, .5, .5);
|
||||
|
||||
SAVE(result);
|
||||
|
||||
Mat reference = imread(reference_path);
|
||||
ASSERT_FALSE(reference.empty()) << "Could not load reference image " << reference_path;
|
||||
|
||||
double errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
double errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_illuminationChange, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Illumination_Change/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "mask.png";
|
||||
string reference_path = folder + "reference.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||
|
||||
Mat result;
|
||||
illuminationChange(source, mask, result, 0.2f, 0.4f);
|
||||
|
||||
SAVE(result);
|
||||
|
||||
Mat reference = imread(reference_path);
|
||||
ASSERT_FALSE(reference.empty()) << "Could not load reference image " << reference_path;
|
||||
|
||||
double errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
double errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_textureFlattening, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "mask.png";
|
||||
string reference_path = folder + "reference.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||
|
||||
Mat result;
|
||||
textureFlattening(source, mask, result, 30, 45, 3);
|
||||
|
||||
SAVE(result);
|
||||
|
||||
Mat reference = imread(reference_path);
|
||||
ASSERT_FALSE(reference.empty()) << "Could not load reference image " << reference_path;
|
||||
|
||||
double errorINF = cvtest::norm(reference, result, NORM_INF);
|
||||
EXPECT_LE(errorINF, 1);
|
||||
double errorL1 = cvtest::norm(reference, result, NORM_L1);
|
||||
EXPECT_LE(errorL1, reference.total() * numerical_precision) << "size=" << reference.size();
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
68
3rdparty/opencv-4.5.4/modules/photo/test/test_decolor.cpp
vendored
Normal file
68
3rdparty/opencv-4.5.4/modules/photo/test/test_decolor.cpp
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Photo_Decolor, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/";
|
||||
string original_path = folder + "color_image_1.png";
|
||||
|
||||
Mat original = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_EQ(3, original.channels()) << "Load color input image " << original_path;
|
||||
|
||||
Mat grayscale, color_boost;
|
||||
decolor(original, grayscale, color_boost);
|
||||
|
||||
Mat reference_grayscale = imread(folder + "grayscale_reference.png", 0 /* == grayscale image*/);
|
||||
double gray_psnr = cvtest::PSNR(reference_grayscale, grayscale);
|
||||
EXPECT_GT(gray_psnr, 60.0);
|
||||
|
||||
Mat reference_boost = imread(folder + "boost_reference.png");
|
||||
double boost_psnr = cvtest::PSNR(reference_boost, color_boost);
|
||||
EXPECT_GT(boost_psnr, 60.0);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
129
3rdparty/opencv-4.5.4/modules/photo/test/test_denoise_tvl1.cpp
vendored
Normal file
129
3rdparty/opencv-4.5.4/modules/photo/test/test_denoise_tvl1.cpp
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 OpenCV Foundation 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
void make_noisy(const cv::Mat& img, cv::Mat& noisy, double sigma, double pepper_salt_ratio,cv::RNG& rng)
|
||||
{
|
||||
noisy.create(img.size(), img.type());
|
||||
cv::Mat noise(img.size(), img.type()), mask(img.size(), CV_8U);
|
||||
rng.fill(noise,cv::RNG::NORMAL,128.0,sigma);
|
||||
cv::addWeighted(img, 1, noise, 1, -128, noisy);
|
||||
cv::randn(noise, cv::Scalar::all(0), cv::Scalar::all(2));
|
||||
noise *= 255;
|
||||
cv::randu(mask, 0, cvRound(1./pepper_salt_ratio));
|
||||
cv::Mat half = mask.colRange(0, img.cols/2);
|
||||
half = cv::Scalar::all(1);
|
||||
noise.setTo(128, mask);
|
||||
cv::addWeighted(noisy, 1, noise, 1, -128, noisy);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void make_spotty(cv::Mat& img,cv::RNG& rng, int r=3,int n=1000)
|
||||
{
|
||||
for(int i=0;i<n;i++)
|
||||
{
|
||||
int x=rng(img.cols-r),y=rng(img.rows-r);
|
||||
if(rng(2)==0)
|
||||
img(cv::Range(y,y+r),cv::Range(x,x+r))=(uchar)0;
|
||||
else
|
||||
img(cv::Range(y,y+r),cv::Range(x,x+r))=(uchar)255;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool validate_pixel(const cv::Mat& image,int x,int y,uchar val)
|
||||
{
|
||||
bool ok = std::abs(image.at<uchar>(x,y) - val) < 10;
|
||||
printf("test: image(%d,%d)=%d vs %d - %s\n",x,y,(int)image.at<uchar>(x,y),val,ok?"ok":"bad");
|
||||
return ok;
|
||||
}
|
||||
|
||||
TEST(Optim_denoise_tvl1, regression_basic)
|
||||
{
|
||||
cv::RNG rng(42);
|
||||
cv::Mat img = cv::imread(cvtest::TS::ptr()->get_data_path() + "shared/lena.png", 0), noisy, res;
|
||||
|
||||
ASSERT_FALSE(img.empty()) << "Error: can't open 'lena.png'";
|
||||
|
||||
const int obs_num=5;
|
||||
std::vector<cv::Mat> images(obs_num, cv::Mat());
|
||||
for(int i=0;i<(int)images.size();i++)
|
||||
{
|
||||
make_noisy(img,images[i], 20, 0.02,rng);
|
||||
//make_spotty(images[i],rng);
|
||||
}
|
||||
|
||||
//cv::imshow("test", images[0]);
|
||||
cv::denoise_TVL1(images, res);
|
||||
//cv::imshow("denoised", res);
|
||||
//cv::waitKey();
|
||||
|
||||
#if 0
|
||||
ASSERT_TRUE(validate_pixel(res,248,334,179));
|
||||
ASSERT_TRUE(validate_pixel(res,489,333,172));
|
||||
ASSERT_TRUE(validate_pixel(res,425,507,104));
|
||||
ASSERT_TRUE(validate_pixel(res,489,486,105));
|
||||
ASSERT_TRUE(validate_pixel(res,223,208,64));
|
||||
ASSERT_TRUE(validate_pixel(res,418,3,78));
|
||||
ASSERT_TRUE(validate_pixel(res,63,76,97));
|
||||
ASSERT_TRUE(validate_pixel(res,29,134,126));
|
||||
ASSERT_TRUE(validate_pixel(res,219,291,174));
|
||||
ASSERT_TRUE(validate_pixel(res,384,124,76));
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
ASSERT_TRUE(validate_pixel(res,248,334,194));
|
||||
ASSERT_TRUE(validate_pixel(res,489,333,171));
|
||||
ASSERT_TRUE(validate_pixel(res,425,507,103));
|
||||
ASSERT_TRUE(validate_pixel(res,489,486,109));
|
||||
ASSERT_TRUE(validate_pixel(res,223,208,72));
|
||||
ASSERT_TRUE(validate_pixel(res,418,3,58));
|
||||
ASSERT_TRUE(validate_pixel(res,63,76,93));
|
||||
ASSERT_TRUE(validate_pixel(res,29,134,127));
|
||||
ASSERT_TRUE(validate_pixel(res,219,291,180));
|
||||
ASSERT_TRUE(validate_pixel(res,384,124,80));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
168
3rdparty/opencv-4.5.4/modules/photo/test/test_denoising.cpp
vendored
Normal file
168
3rdparty/opencv-4.5.4/modules/photo/test/test_denoising.cpp
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//#define DUMP_RESULTS
|
||||
|
||||
#ifdef DUMP_RESULTS
|
||||
# define DUMP(image, path) imwrite(path, image)
|
||||
#else
|
||||
# define DUMP(image, path)
|
||||
#endif
|
||||
|
||||
|
||||
TEST(Photo_DenoisingGrayscale, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/";
|
||||
string original_path = folder + "lena_noised_gaussian_sigma=10.png";
|
||||
string expected_path = folder + "lena_noised_denoised_grayscale_tw=7_sw=21_h=10.png";
|
||||
|
||||
Mat original = imread(original_path, IMREAD_GRAYSCALE);
|
||||
Mat expected = imread(expected_path, IMREAD_GRAYSCALE);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
Mat result;
|
||||
fastNlMeansDenoising(original, result, 10);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_EQ(0, cvtest::norm(result, expected, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Photo_DenoisingColored, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/";
|
||||
string original_path = folder + "lena_noised_gaussian_sigma=10.png";
|
||||
string expected_path = folder + "lena_noised_denoised_lab12_tw=7_sw=21_h=10_h2=10.png";
|
||||
|
||||
Mat original = imread(original_path, IMREAD_COLOR);
|
||||
Mat expected = imread(expected_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
Mat result;
|
||||
fastNlMeansDenoisingColored(original, result, 10, 10);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_EQ(0, cvtest::norm(result, expected, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Photo_DenoisingGrayscaleMulti, regression)
|
||||
{
|
||||
const int imgs_count = 3;
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/";
|
||||
|
||||
string expected_path = folder + "lena_noised_denoised_multi_tw=7_sw=21_h=15.png";
|
||||
Mat expected = imread(expected_path, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
vector<Mat> original(imgs_count);
|
||||
for (int i = 0; i < imgs_count; i++)
|
||||
{
|
||||
string original_path = format("%slena_noised_gaussian_sigma=20_multi_%d.png", folder.c_str(), i);
|
||||
original[i] = imread(original_path, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(original[i].empty()) << "Could not load input image " << original_path;
|
||||
}
|
||||
|
||||
Mat result;
|
||||
fastNlMeansDenoisingMulti(original, result, imgs_count / 2, imgs_count, 15);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_EQ(0, cvtest::norm(result, expected, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Photo_DenoisingColoredMulti, regression)
|
||||
{
|
||||
const int imgs_count = 3;
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/";
|
||||
|
||||
string expected_path = folder + "lena_noised_denoised_multi_lab12_tw=7_sw=21_h=10_h2=15.png";
|
||||
Mat expected = imread(expected_path, IMREAD_COLOR);
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
vector<Mat> original(imgs_count);
|
||||
for (int i = 0; i < imgs_count; i++)
|
||||
{
|
||||
string original_path = format("%slena_noised_gaussian_sigma=20_multi_%d.png", folder.c_str(), i);
|
||||
original[i] = imread(original_path, IMREAD_COLOR);
|
||||
ASSERT_FALSE(original[i].empty()) << "Could not load input image " << original_path;
|
||||
}
|
||||
|
||||
Mat result;
|
||||
fastNlMeansDenoisingColoredMulti(original, result, imgs_count / 2, imgs_count, 10, 15);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_EQ(0, cvtest::norm(result, expected, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Photo_White, issue_2646)
|
||||
{
|
||||
cv::Mat img(50, 50, CV_8UC1, cv::Scalar::all(255));
|
||||
cv::Mat filtered;
|
||||
cv::fastNlMeansDenoising(img, filtered);
|
||||
|
||||
int nonWhitePixelsCount = (int)img.total() - cv::countNonZero(filtered == img);
|
||||
|
||||
ASSERT_EQ(0, nonWhitePixelsCount);
|
||||
}
|
||||
|
||||
TEST(Photo_Denoising, speed)
|
||||
{
|
||||
string imgname = string(cvtest::TS::ptr()->get_data_path()) + "shared/5MP.png";
|
||||
Mat src = imread(imgname, 0), dst;
|
||||
|
||||
double t = (double)getTickCount();
|
||||
fastNlMeansDenoising(src, dst, 5, 7, 21);
|
||||
t = (double)getTickCount() - t;
|
||||
printf("execution time: %gms\n", t*1000./getTickFrequency());
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
120
3rdparty/opencv-4.5.4/modules/photo/test/test_denoising.cuda.cpp
vendored
Normal file
120
3rdparty/opencv-4.5.4/modules/photo/test/test_denoising.cuda.cpp
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
#include "opencv2/photo/cuda.hpp"
|
||||
#include "opencv2/ts/cuda_test.hpp"
|
||||
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
#include "cvconfig.h"
|
||||
|
||||
#if defined (HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAIMGPROC)
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Brute Force Non local means
|
||||
|
||||
TEST(CUDA_BruteForceNonLocalMeans, Regression)
|
||||
{
|
||||
using cv::cuda::GpuMat;
|
||||
|
||||
cv::Mat bgr = readImage("../gpu/denoising/lena_noised_gaussian_sigma=20_multi_0.png", cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(bgr.empty());
|
||||
cv::resize(bgr, bgr, cv::Size(256, 256));
|
||||
|
||||
cv::Mat gray;
|
||||
cv::cvtColor(bgr, gray, cv::COLOR_BGR2GRAY);
|
||||
|
||||
GpuMat dbgr, dgray;
|
||||
cv::cuda::nonLocalMeans(GpuMat(bgr), dbgr, 20);
|
||||
cv::cuda::nonLocalMeans(GpuMat(gray), dgray, 20);
|
||||
|
||||
#if 0
|
||||
dumpImage("../gpu/denoising/nlm_denoised_lena_bgr.png", cv::Mat(dbgr));
|
||||
dumpImage("../gpu/denoising/nlm_denoised_lena_gray.png", cv::Mat(dgray));
|
||||
#endif
|
||||
|
||||
cv::Mat bgr_gold = readImage("../gpu/denoising/nlm_denoised_lena_bgr.png", cv::IMREAD_COLOR);
|
||||
cv::Mat gray_gold = readImage("../gpu/denoising/nlm_denoised_lena_gray.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(bgr_gold.empty() || gray_gold.empty());
|
||||
cv::resize(bgr_gold, bgr_gold, cv::Size(256, 256));
|
||||
cv::resize(gray_gold, gray_gold, cv::Size(256, 256));
|
||||
|
||||
EXPECT_MAT_NEAR(bgr_gold, dbgr, 1);
|
||||
EXPECT_MAT_NEAR(gray_gold, dgray, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Fast Force Non local means
|
||||
|
||||
TEST(CUDA_FastNonLocalMeans, Regression)
|
||||
{
|
||||
using cv::cuda::GpuMat;
|
||||
|
||||
cv::Mat bgr = readImage("../gpu/denoising/lena_noised_gaussian_sigma=20_multi_0.png", cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(bgr.empty());
|
||||
|
||||
cv::Mat gray;
|
||||
cv::cvtColor(bgr, gray, cv::COLOR_BGR2GRAY);
|
||||
|
||||
GpuMat dbgr, dgray;
|
||||
|
||||
cv::cuda::fastNlMeansDenoising(GpuMat(gray), dgray, 20);
|
||||
cv::cuda::fastNlMeansDenoisingColored(GpuMat(bgr), dbgr, 20, 10);
|
||||
|
||||
#if 0
|
||||
dumpImage("../gpu/denoising/fnlm_denoised_lena_bgr.png", cv::Mat(dbgr));
|
||||
dumpImage("../gpu/denoising/fnlm_denoised_lena_gray.png", cv::Mat(dgray));
|
||||
#endif
|
||||
|
||||
cv::Mat bgr_gold = readImage("../gpu/denoising/fnlm_denoised_lena_bgr.png", cv::IMREAD_COLOR);
|
||||
cv::Mat gray_gold = readImage("../gpu/denoising/fnlm_denoised_lena_gray.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(bgr_gold.empty() || gray_gold.empty());
|
||||
|
||||
EXPECT_MAT_NEAR(bgr_gold, dbgr, 1);
|
||||
EXPECT_MAT_NEAR(gray_gold, dgray, 1);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
269
3rdparty/opencv-4.5.4/modules/photo/test/test_hdr.cpp
vendored
Normal file
269
3rdparty/opencv-4.5.4/modules/photo/test/test_hdr.cpp
vendored
Normal file
@ -0,0 +1,269 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
void loadImage(string path, Mat &img)
|
||||
{
|
||||
img = imread(path, -1);
|
||||
ASSERT_FALSE(img.empty()) << "Could not load input image " << path;
|
||||
}
|
||||
|
||||
void checkEqual(Mat img0, Mat img1, double threshold, const string& name)
|
||||
{
|
||||
double max = 1.0;
|
||||
minMaxLoc(abs(img0 - img1), NULL, &max);
|
||||
ASSERT_FALSE(max > threshold) << "max=" << max << " threshold=" << threshold << " method=" << name;
|
||||
}
|
||||
|
||||
static vector<float> DEFAULT_VECTOR;
|
||||
void loadExposureSeq(String path, vector<Mat>& images, vector<float>& times = DEFAULT_VECTOR)
|
||||
{
|
||||
std::ifstream list_file((path + "list.txt").c_str());
|
||||
ASSERT_TRUE(list_file.is_open());
|
||||
string name;
|
||||
float val;
|
||||
while(list_file >> name >> val) {
|
||||
Mat img = imread(path + name);
|
||||
ASSERT_FALSE(img.empty()) << "Could not load input image " << path + name;
|
||||
images.push_back(img);
|
||||
times.push_back(1 / val);
|
||||
}
|
||||
list_file.close();
|
||||
}
|
||||
|
||||
void loadResponseCSV(String path, Mat& response)
|
||||
{
|
||||
response = Mat(256, 1, CV_32FC3);
|
||||
std::ifstream resp_file(path.c_str());
|
||||
for(int i = 0; i < 256; i++) {
|
||||
for(int c = 0; c < 3; c++) {
|
||||
resp_file >> response.at<Vec3f>(i)[c];
|
||||
resp_file.ignore(1);
|
||||
}
|
||||
}
|
||||
resp_file.close();
|
||||
}
|
||||
|
||||
TEST(Photo_Tonemap, regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/tonemap/";
|
||||
|
||||
Mat img, expected, result;
|
||||
loadImage(test_path + "image.hdr", img);
|
||||
float gamma = 2.2f;
|
||||
|
||||
Ptr<Tonemap> linear = createTonemap(gamma);
|
||||
linear->process(img, result);
|
||||
loadImage(test_path + "linear.png", expected);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(result, expected, 3, "Simple");
|
||||
|
||||
Ptr<TonemapDrago> drago = createTonemapDrago(gamma);
|
||||
drago->process(img, result);
|
||||
loadImage(test_path + "drago.png", expected);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(result, expected, 3, "Drago");
|
||||
|
||||
Ptr<TonemapReinhard> reinhard = createTonemapReinhard(gamma);
|
||||
reinhard->process(img, result);
|
||||
loadImage(test_path + "reinhard.png", expected);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(result, expected, 3, "Reinhard");
|
||||
|
||||
Ptr<TonemapMantiuk> mantiuk = createTonemapMantiuk(gamma);
|
||||
mantiuk->process(img, result);
|
||||
loadImage(test_path + "mantiuk.png", expected);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(result, expected, 3, "Mantiuk");
|
||||
}
|
||||
|
||||
TEST(Photo_AlignMTB, regression)
|
||||
{
|
||||
const int TESTS_COUNT = 100;
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "shared/";
|
||||
|
||||
string file_name = folder + "lena.png";
|
||||
Mat img;
|
||||
loadImage(file_name, img);
|
||||
cvtColor(img, img, COLOR_RGB2GRAY);
|
||||
|
||||
int max_bits = 5;
|
||||
int max_shift = 32;
|
||||
srand(static_cast<unsigned>(time(0)));
|
||||
int errors = 0;
|
||||
|
||||
Ptr<AlignMTB> align = createAlignMTB(max_bits);
|
||||
RNG rng = theRNG();
|
||||
|
||||
for(int i = 0; i < TESTS_COUNT; i++) {
|
||||
Point shift(rng.uniform(0, max_shift), rng.uniform(0, max_shift));
|
||||
Mat res;
|
||||
align->shiftMat(img, res, shift);
|
||||
Point calc = align->calculateShift(img, res);
|
||||
errors += (calc != -shift);
|
||||
}
|
||||
ASSERT_TRUE(errors < 5) << errors << " errors";
|
||||
}
|
||||
|
||||
TEST(Photo_MergeMertens, regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
|
||||
|
||||
vector<Mat> images;
|
||||
loadExposureSeq((test_path + "exposures/").c_str() , images);
|
||||
|
||||
Ptr<MergeMertens> merge = createMergeMertens();
|
||||
|
||||
Mat result, expected;
|
||||
loadImage(test_path + "merge/mertens.png", expected);
|
||||
merge->process(images, result);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(expected, result, 3, "Mertens");
|
||||
|
||||
Mat uniform(100, 100, CV_8UC3);
|
||||
uniform = Scalar(0, 255, 0);
|
||||
|
||||
images.clear();
|
||||
images.push_back(uniform);
|
||||
|
||||
merge->process(images, result);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(uniform, result, 1e-2f, "Mertens");
|
||||
}
|
||||
|
||||
TEST(Photo_MergeDebevec, regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
|
||||
|
||||
vector<Mat> images;
|
||||
vector<float> times;
|
||||
Mat response;
|
||||
loadExposureSeq(test_path + "exposures/", images, times);
|
||||
loadResponseCSV(test_path + "exposures/response.csv", response);
|
||||
|
||||
Ptr<MergeDebevec> merge = createMergeDebevec();
|
||||
|
||||
Mat result, expected;
|
||||
loadImage(test_path + "merge/debevec.hdr", expected);
|
||||
merge->process(images, result, times, response);
|
||||
|
||||
Ptr<Tonemap> map = createTonemap();
|
||||
map->process(result, result);
|
||||
map->process(expected, expected);
|
||||
|
||||
checkEqual(expected, result, 1e-2f, "Debevec");
|
||||
}
|
||||
|
||||
TEST(Photo_MergeRobertson, regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
|
||||
|
||||
vector<Mat> images;
|
||||
vector<float> times;
|
||||
loadExposureSeq(test_path + "exposures/", images, times);
|
||||
Ptr<MergeRobertson> merge = createMergeRobertson();
|
||||
Mat result, expected;
|
||||
loadImage(test_path + "merge/robertson.hdr", expected);
|
||||
merge->process(images, result, times);
|
||||
|
||||
const float eps = 6.f;
|
||||
checkEqual(expected, result, eps, "MergeRobertson");
|
||||
}
|
||||
|
||||
TEST(Photo_CalibrateDebevec, regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
|
||||
|
||||
vector<Mat> images;
|
||||
vector<float> times;
|
||||
Mat response, expected;
|
||||
loadExposureSeq(test_path + "exposures/", images, times);
|
||||
loadResponseCSV(test_path + "calibrate/debevec.csv", expected);
|
||||
Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
|
||||
|
||||
calibrate->process(images, response, times);
|
||||
Mat diff = abs(response - expected);
|
||||
diff = diff.mul(1.0f / response);
|
||||
double max;
|
||||
minMaxLoc(diff, NULL, &max);
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
ASSERT_LT(max, 0.131);
|
||||
#else
|
||||
ASSERT_LT(max, 0.1);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Photo_CalibrateRobertson, regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
|
||||
|
||||
vector<Mat> images;
|
||||
vector<float> times;
|
||||
Mat response, expected;
|
||||
loadExposureSeq(test_path + "exposures/", images, times);
|
||||
loadResponseCSV(test_path + "calibrate/robertson.csv", expected);
|
||||
|
||||
Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson();
|
||||
calibrate->process(images, response, times);
|
||||
checkEqual(expected, response, 1e-1f, "CalibrateRobertson");
|
||||
}
|
||||
|
||||
TEST(Photo_CalibrateRobertson, bug_18180)
|
||||
{
|
||||
vector<Mat> images;
|
||||
vector<cv::String> fn;
|
||||
string test_path = cvtest::TS::ptr()->get_data_path() + "hdr/exposures/bug_18180/";
|
||||
for(int i = 1; i <= 4; ++i)
|
||||
images.push_back(imread(test_path + std::to_string(i) + ".jpg"));
|
||||
vector<float> times {15.0f, 2.5f, 0.25f, 0.33f};
|
||||
Mat response, expected;
|
||||
Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson(2, 0.01f);
|
||||
calibrate->process(images, response, times);
|
||||
Mat response_no_nans = response.clone();
|
||||
patchNaNs(response_no_nans);
|
||||
// since there should be no NaNs, original response vs. response with NaNs patched should be identical
|
||||
EXPECT_EQ(0.0, cv::norm(response, response_no_nans, NORM_L2));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
160
3rdparty/opencv-4.5.4/modules/photo/test/test_inpaint.cpp
vendored
Normal file
160
3rdparty/opencv-4.5.4/modules/photo/test/test_inpaint.cpp
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
/*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, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_InpaintTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_InpaintTest();
|
||||
~CV_InpaintTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_InpaintTest::CV_InpaintTest()
|
||||
{
|
||||
}
|
||||
CV_InpaintTest::~CV_InpaintTest() {}
|
||||
|
||||
void CV_InpaintTest::run( int )
|
||||
{
|
||||
string folder = string(ts->get_data_path()) + "inpaint/";
|
||||
Mat orig = imread(folder + "orig.png");
|
||||
Mat exp1 = imread(folder + "exp1.png");
|
||||
Mat exp2 = imread(folder + "exp2.png");
|
||||
Mat mask = imread(folder + "mask.png");
|
||||
|
||||
if (orig.empty() || exp1.empty() || exp2.empty() || mask.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat inv_mask;
|
||||
mask.convertTo(inv_mask, CV_8UC3, -1.0, 255.0);
|
||||
|
||||
Mat mask1ch;
|
||||
cv::cvtColor(mask, mask1ch, COLOR_BGR2GRAY);
|
||||
|
||||
Mat test = orig.clone();
|
||||
test.setTo(Scalar::all(255), mask1ch);
|
||||
|
||||
Mat res1, res2;
|
||||
inpaint( test, mask1ch, res1, 5, INPAINT_NS );
|
||||
inpaint( test, mask1ch, res2, 5, INPAINT_TELEA );
|
||||
|
||||
Mat diff1, diff2;
|
||||
absdiff( orig, res1, diff1 );
|
||||
absdiff( orig, res2, diff2 );
|
||||
|
||||
double n1 = cvtest::norm(diff1.reshape(1), NORM_INF, inv_mask.reshape(1));
|
||||
double n2 = cvtest::norm(diff2.reshape(1), NORM_INF, inv_mask.reshape(1));
|
||||
|
||||
if (n1 != 0 || n2 != 0)
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
|
||||
return;
|
||||
}
|
||||
|
||||
absdiff( exp1, res1, diff1 );
|
||||
absdiff( exp2, res2, diff2 );
|
||||
|
||||
n1 = cvtest::norm(diff1.reshape(1), NORM_INF, mask.reshape(1));
|
||||
n2 = cvtest::norm(diff2.reshape(1), NORM_INF, mask.reshape(1));
|
||||
|
||||
const int jpeg_thres = 3;
|
||||
if (n1 > jpeg_thres || n2 > jpeg_thres)
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Photo_Inpaint, regression) { CV_InpaintTest test; test.safe_run(); }
|
||||
|
||||
typedef testing::TestWithParam<tuple<int> > formats;
|
||||
|
||||
TEST_P(formats, 1c)
|
||||
{
|
||||
const int type = get<0>(GetParam());
|
||||
Mat src(100, 100, type);
|
||||
src.setTo(Scalar::all(128));
|
||||
Mat ref = src.clone();
|
||||
Mat dst, mask = Mat::zeros(src.size(), CV_8U);
|
||||
|
||||
circle(src, Point(50, 50), 5, Scalar(200), 6);
|
||||
circle(mask, Point(50, 50), 5, Scalar(200), 6);
|
||||
inpaint(src, mask, dst, 10, INPAINT_NS);
|
||||
|
||||
Mat dst2;
|
||||
inpaint(src, mask, dst2, 10, INPAINT_TELEA);
|
||||
|
||||
ASSERT_LE(cv::norm(dst, ref, NORM_INF), 3.);
|
||||
ASSERT_LE(cv::norm(dst2, ref, NORM_INF), 3.);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Photo_Inpaint, formats, testing::Values(CV_32F, CV_16U, CV_8U));
|
||||
|
||||
TEST(Photo_InpaintBorders, regression)
|
||||
{
|
||||
Mat img(64, 64, CV_8U);
|
||||
img = 128;
|
||||
img(Rect(0, 0, 16, 64)) = 0;
|
||||
|
||||
Mat mask(64, 64, CV_8U);
|
||||
mask = 0;
|
||||
mask(Rect(0, 0, 16, 64)) = 255;
|
||||
|
||||
Mat inpainted;
|
||||
inpaint(img, mask, inpainted, 1, INPAINT_TELEA);
|
||||
|
||||
Mat diff;
|
||||
cv::absdiff(inpainted, 128*Mat::ones(inpainted.size(), inpainted.type()), diff);
|
||||
ASSERT_TRUE(countNonZero(diff) == 0);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
10
3rdparty/opencv-4.5.4/modules/photo/test/test_main.cpp
vendored
Normal file
10
3rdparty/opencv-4.5.4/modules/photo/test/test_main.cpp
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// 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.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
CV_TEST_MAIN("cv")
|
||||
140
3rdparty/opencv-4.5.4/modules/photo/test/test_npr.cpp
vendored
Normal file
140
3rdparty/opencv-4.5.4/modules/photo/test/test_npr.cpp
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
/*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) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * 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 the copyright holders 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static const double numerical_precision = 100.;
|
||||
|
||||
TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
edgePreservingFilter(source,result,1);
|
||||
|
||||
Mat reference = imread(folder + "smoothened_RF_reference.png");
|
||||
|
||||
double psnr = cvtest::PSNR(reference, result);
|
||||
EXPECT_GT(psnr, 60.0);
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
edgePreservingFilter(source,result,2);
|
||||
|
||||
Mat reference = imread(folder + "smoothened_NCF_reference.png");
|
||||
|
||||
double psnr = cvtest::PSNR(reference, result);
|
||||
EXPECT_GT(psnr, 60.0);
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_DetailEnhance, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
detailEnhance(source,result);
|
||||
|
||||
Mat reference = imread(folder + "detail_enhanced_reference.png");
|
||||
double psnr = cvtest::PSNR(reference, result);
|
||||
EXPECT_GT(psnr, 60.0);
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_PencilSketch, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat pencil_result, color_pencil_result;
|
||||
pencilSketch(source,pencil_result, color_pencil_result, 10, 0.1f, 0.03f);
|
||||
|
||||
Mat pencil_reference = imread(folder + "pencil_sketch_reference.png", 0 /* == grayscale*/);
|
||||
double pencil_error = cvtest::norm(pencil_reference, pencil_result, NORM_L1);
|
||||
EXPECT_LE(pencil_error, numerical_precision);
|
||||
|
||||
Mat color_pencil_reference = imread(folder + "color_pencil_sketch_reference.png");
|
||||
double color_pencil_error = cvtest::norm(color_pencil_reference, color_pencil_result, NORM_L1);
|
||||
EXPECT_LE(color_pencil_error, numerical_precision);
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_Stylization, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
stylization(source,result);
|
||||
|
||||
Mat stylized_reference = imread(folder + "stylized_reference.png");
|
||||
double stylized_error = cvtest::norm(stylized_reference, result, NORM_L1);
|
||||
EXPECT_LE(stylized_error, numerical_precision);
|
||||
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
10
3rdparty/opencv-4.5.4/modules/photo/test/test_precomp.hpp
vendored
Normal file
10
3rdparty/opencv-4.5.4/modules/photo/test/test_precomp.hpp
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// 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_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/photo.hpp"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user