diff --git a/modules/fuzzy/CMakeLists.txt b/modules/fuzzy/CMakeLists.txt index cc04e1506..e4e9ca602 100644 --- a/modules/fuzzy/CMakeLists.txt +++ b/modules/fuzzy/CMakeLists.txt @@ -1,3 +1,3 @@ set(the_description "Fuzzy mathematical image processing") -ocv_define_module(fuzzy opencv_imgproc opencv_core) +ocv_define_module(fuzzy opencv_imgproc opencv_core WRAP python) diff --git a/modules/fuzzy/include/opencv2/fuzzy/fuzzy_F0_math.hpp b/modules/fuzzy/include/opencv2/fuzzy/fuzzy_F0_math.hpp index e0a2c488f..5b241575a 100644 --- a/modules/fuzzy/include/opencv2/fuzzy/fuzzy_F0_math.hpp +++ b/modules/fuzzy/include/opencv2/fuzzy/fuzzy_F0_math.hpp @@ -54,7 +54,7 @@ namespace ft //! @{ /** @brief Computes components of the array using direct F0-transform. - @param matrix Input 1-channel array. + @param matrix Input array. @param kernel Kernel used for processing. Function **createKernel** can be used. @param components Output 32-bit array for the components. @param mask Mask can be used for unwanted area marking. @@ -64,10 +64,10 @@ namespace ft @note F-transform technique is described in paper @cite Perf:FT. */ - CV_EXPORTS void FT02D_components(InputArray matrix, InputArray kernel, OutputArray components, InputArray mask); + CV_EXPORTS_AS(FT02D_components1) void FT02D_components(InputArray matrix, InputArray kernel, OutputArray components, InputArray mask); /** @brief Computes components of the array using direct F0-transform. - @param matrix Input 1-channel array. + @param matrix Input array. @param kernel Kernel used for processing. Function **createKernel** can be used. @param components Output 32-bit array for the components. @@ -76,10 +76,10 @@ namespace ft @note F-transform technique is described in paper @cite Perf:FT. */ - CV_EXPORTS void FT02D_components(InputArray matrix, InputArray kernel, OutputArray components); + CV_EXPORTS_W void FT02D_components(InputArray matrix, InputArray kernel, OutputArray components); /** @brief Computes inverse F0-transfrom. - @param components Input 32-bit array for the components. + @param components Input 32-bit single channel array for the components. @param kernel Kernel used for processing. Function **createKernel** can be used. @param output Output 32-bit array. @param width Width of the output array. @@ -88,29 +88,38 @@ namespace ft @note F-transform technique is described in paper @cite Perf:FT. */ - CV_EXPORTS void FT02D_inverseFT(InputArray components, InputArray kernel, OutputArray output, int width, int height); + CV_EXPORTS_W void FT02D_inverseFT(InputArray components, InputArray kernel, OutputArray output, int width, int height); /** @brief Computes F0-transfrom and inverse F0-transfrom at once. - @param image Input image. + @param matrix Input matrix. @param kernel Kernel used for processing. Function **createKernel** can be used. @param output Output 32-bit array. @param mask Mask used for unwanted area marking. This function computes F-transfrom and inverse F-transfotm in one step. It is fully sufficient and optimized for **Mat**. */ - CV_EXPORTS void FT02D_process(const Mat &image, const Mat &kernel, Mat &output, const Mat &mask); + CV_EXPORTS_AS(FT02D_process1) void FT02D_process(InputArray matrix, InputArray kernel, OutputArray output, InputArray mask); + + /** @brief Computes F0-transfrom and inverse F0-transfrom at once. + @param matrix Input matrix. + @param kernel Kernel used for processing. Function **createKernel** can be used. + @param output Output 32-bit array. + + This function computes F-transfrom and inverse F-transfotm in one step. It is fully sufficient and optimized for **Mat**. + */ + CV_EXPORTS_W void FT02D_process(InputArray matrix, InputArray kernel, OutputArray output); /** @brief Computes F0-transfrom and inverse F0-transfrom at once and return state. - @param image Input image. + @param matrix Input matrix. @param kernel Kernel used for processing. Function **createKernel** can be used. - @param imageOutput Output 32-bit array. + @param output Output 32-bit array. @param mask Mask used for unwanted area marking. @param maskOutput Mask after one iteration. @param firstStop If **true** function returns -1 when first problem appears. In case of **false**, the process is completed and summation of all problems returned. This function computes iteration of F-transfrom and inverse F-transfotm and handle image and mask change. The function is used in *inpaint* function. */ - CV_EXPORTS int FT02D_iteration(const Mat &image, const Mat &kernel, Mat &imageOutput, const Mat &mask, Mat &maskOutput, bool firstStop = true); + CV_EXPORTS_W int FT02D_iteration(InputArray matrix, InputArray kernel, OutputArray output, InputArray mask, OutputArray maskOutput, bool firstStop); //! @} } diff --git a/modules/fuzzy/include/opencv2/fuzzy/fuzzy_image.hpp b/modules/fuzzy/include/opencv2/fuzzy/fuzzy_image.hpp index 00a8efa31..e5287a9fc 100644 --- a/modules/fuzzy/include/opencv2/fuzzy/fuzzy_image.hpp +++ b/modules/fuzzy/include/opencv2/fuzzy/fuzzy_image.hpp @@ -61,7 +61,7 @@ namespace ft The function creates kernel usable for latter fuzzy image processing. */ - CV_EXPORTS void createKernel(cv::InputArray A, cv::InputArray B, cv::OutputArray kernel, const int chn = 1); + CV_EXPORTS_AS(createKernel1) void createKernel(InputArray A, InputArray B, OutputArray kernel, const int chn); /** @brief Creates kernel from general functions. @param function Function type could be one of the following: @@ -72,7 +72,7 @@ namespace ft The function creates kernel from predefined functions. */ - CV_EXPORTS void createKernel(int function, int radius, cv::OutputArray kernel, const int chn = 1); + CV_EXPORTS_W void createKernel(int function, int radius, OutputArray kernel, const int chn); /** @brief Image inpainting @param image Input image. @@ -91,16 +91,16 @@ namespace ft @note The algorithms are described in paper @cite Perf:rec. */ - CV_EXPORTS void inpaint(const cv::Mat &image, const cv::Mat &mask, cv::Mat &output, int radius = 2, int function = ft::LINEAR, int algorithm = ft::ONE_STEP); + CV_EXPORTS_W void inpaint(InputArray image, InputArray mask, OutputArray output, int radius, int function, int algorithm); /** @brief Image filtering @param image Input image. - @param kernel Final 32-b kernel. + @param kernel Final 32-bit kernel. @param output Output 32-bit image. Filtering of the input image by means of F-transform. */ - CV_EXPORTS void filter(const cv::Mat &image, const cv::Mat &kernel, cv::Mat &output); + CV_EXPORTS_W void filter(InputArray image, InputArray kernel, OutputArray output); //! @} } diff --git a/modules/fuzzy/src/fuzzy_F0_math.cpp b/modules/fuzzy/src/fuzzy_F0_math.cpp index 730f40834..892bcbe5c 100644 --- a/modules/fuzzy/src/fuzzy_F0_math.cpp +++ b/modules/fuzzy/src/fuzzy_F0_math.cpp @@ -45,24 +45,21 @@ using namespace cv; void ft::FT02D_components(InputArray matrix, InputArray kernel, OutputArray components, InputArray mask) { - Mat matrixMat = matrix.getMat(); - Mat kernelMat = kernel.getMat(); - Mat maskMat = mask.getMat(); + CV_Assert(matrix.channels() == kernel.channels() && mask.channels() == 1); - CV_Assert(matrixMat.channels() == 1 && kernelMat.channels() == 1 && maskMat.channels() == 1); - - int radiusX = (kernelMat.cols - 1) / 2; - int radiusY = (kernelMat.rows - 1) / 2; - int An = matrixMat.cols / radiusX + 1; - int Bn = matrixMat.rows / radiusY + 1; + int radiusX = (kernel.cols() - 1) / 2; + int radiusY = (kernel.rows() - 1) / 2; + int An = matrix.cols() / radiusX + 1; + int Bn = matrix.rows() / radiusY + 1; Mat matrixPadded; Mat maskPadded; - copyMakeBorder(matrixMat, matrixPadded, radiusY, kernelMat.rows, radiusX, kernelMat.cols, BORDER_CONSTANT, Scalar(0)); - copyMakeBorder(maskMat, maskPadded, radiusY, kernelMat.rows, radiusX, kernelMat.cols, BORDER_CONSTANT, Scalar(0)); + copyMakeBorder(matrix, matrixPadded, radiusY, kernel.rows(), radiusX, kernel.cols(), BORDER_CONSTANT, Scalar(0)); + copyMakeBorder(mask, maskPadded, radiusY, kernel.rows(), radiusX, kernel.cols(), BORDER_CONSTANT, Scalar(0)); + + components.create(Bn, An, CV_MAKETYPE(CV_32F, matrix.channels())); - components.create(Bn, An, CV_32F); Mat componentsMat = components.getMat(); for (int i = 0; i < An; i++) @@ -71,18 +68,21 @@ void ft::FT02D_components(InputArray matrix, InputArray kernel, OutputArray comp { int centerX = (i * radiusX) + radiusX; int centerY = (o * radiusY) + radiusY; - Rect area(centerX - radiusX, centerY - radiusY, kernelMat.cols, kernelMat.rows); + Rect area(centerX - radiusX, centerY - radiusY, kernel.cols(), kernel.rows()); Mat roiImage(matrixPadded, area); Mat roiMask(maskPadded, area); Mat kernelMasked; - kernelMat.copyTo(kernelMasked, roiMask); + kernel.copyTo(kernelMasked, roiMask); Mat numerator; multiply(roiImage, kernelMasked, numerator, 1, CV_32F); - componentsMat.row(o).col(i) = sum(numerator) / sum(kernelMasked); + Scalar value; + divide(sum(numerator), sum(kernelMasked), value, 1, CV_32F); + + componentsMat.row(o).col(i).setTo(value); } } } @@ -96,19 +96,18 @@ void ft::FT02D_components(InputArray matrix, InputArray kernel, OutputArray comp void ft::FT02D_inverseFT(InputArray components, InputArray kernel, OutputArray output, int width, int height) { - Mat componentsMat = components.getMat(); - Mat kernelMat = kernel.getMat(); + CV_Assert(components.channels() == 1 && kernel.channels() == 1); - CV_Assert(componentsMat.channels() == 1 && kernelMat.channels() == 1); + Mat componentsMat = components.getMat(); - int radiusX = (kernelMat.cols - 1) / 2; - int radiusY = (kernelMat.rows - 1) / 2; - int paddedOutputWidth = radiusX + width + kernelMat.cols; - int paddedOutputHeight = radiusY + height + kernelMat.rows; + int radiusX = (kernel.cols() - 1) / 2; + int radiusY = (kernel.rows() - 1) / 2; + int outputWidthPadded = radiusX + width + kernel.cols(); + int outputHeightPadded = radiusY + height + kernel.rows(); output.create(height, width, CV_32F); - Mat outputZeroes(paddedOutputHeight, paddedOutputWidth, CV_32F, Scalar(0)); + Mat outputZeroes(outputHeightPadded, outputWidthPadded, CV_32F, Scalar(0)); for (int i = 0; i < componentsMat.cols; i++) { @@ -116,34 +115,48 @@ void ft::FT02D_inverseFT(InputArray components, InputArray kernel, OutputArray o { int centerX = (i * radiusX) + radiusX; int centerY = (o * radiusY) + radiusY; - Rect area(centerX - radiusX, centerY - radiusY, kernelMat.cols, kernelMat.rows); + Rect area(centerX - radiusX, centerY - radiusY, kernel.cols(), kernel.rows()); + + float component = componentsMat.at(o, i); + + Mat inverse; + multiply(kernel, component, inverse, 1, CV_32F); Mat roiOutput(outputZeroes, area); - roiOutput += kernelMat.mul(componentsMat.at(o,i)); + add(roiOutput, inverse, roiOutput); } } outputZeroes(Rect(radiusX, radiusY, width, height)).copyTo(output); } -void ft::FT02D_process(const cv::Mat &image, const cv::Mat &kernel, cv::Mat &output, const cv::Mat &mask) +void ft::FT02D_process(InputArray matrix, InputArray kernel, OutputArray output) +{ + Mat mask = Mat::ones(matrix.size(), CV_8U); + + ft::FT02D_process(matrix, kernel, output, mask); +} + +void ft::FT02D_process(InputArray matrix, InputArray kernel, OutputArray output, InputArray mask) { - CV_Assert(image.channels() == kernel.channels()); + CV_Assert(matrix.channels() == kernel.channels() && mask.channels() == 1); - int radiusX = (kernel.cols - 1) / 2; - int radiusY = (kernel.rows - 1) / 2; - int An = image.cols / radiusX + 1; - int Bn = image.rows / radiusY + 1; - int outputWidthPadded = radiusX + image.cols + kernel.cols; - int outputHeightPadded = radiusY + image.rows + kernel.rows; + int radiusX = (kernel.cols() - 1) / 2; + int radiusY = (kernel.rows() - 1) / 2; + int An = matrix.cols() / radiusX + 1; + int Bn = matrix.rows() / radiusY + 1; + int outputWidthPadded = radiusX + matrix.cols() + kernel.cols(); + int outputHeightPadded = radiusY + matrix.rows() + kernel.rows(); - Mat imagePadded; + Mat matrixPadded; Mat maskPadded; - output = Mat::zeros(outputHeightPadded, outputWidthPadded, CV_MAKETYPE(CV_32F, image.channels())); + output.create(matrix.size(), CV_MAKETYPE(CV_32F, matrix.channels())); + + Mat outputZeroes(outputHeightPadded, outputWidthPadded, output.type(), Scalar(0)); - copyMakeBorder(image, imagePadded, radiusY, kernel.rows, radiusX, kernel.cols, BORDER_CONSTANT, Scalar(0)); - copyMakeBorder(mask, maskPadded, radiusY, kernel.rows, radiusX, kernel.cols, BORDER_CONSTANT, Scalar(0)); + copyMakeBorder(matrix, matrixPadded, radiusY, kernel.rows(), radiusX, kernel.cols(), BORDER_CONSTANT, Scalar(0)); + copyMakeBorder(mask, maskPadded, radiusY, kernel.rows(), radiusX, kernel.cols(), BORDER_CONSTANT, Scalar(0)); for (int i = 0; i < An; i++) { @@ -151,16 +164,16 @@ void ft::FT02D_process(const cv::Mat &image, const cv::Mat &kernel, cv::Mat &out { int centerX = (i * radiusX) + radiusX; int centerY = (o * radiusY) + radiusY; - Rect area(centerX - radiusX, centerY - radiusY, kernel.cols, kernel.rows); + Rect area(centerX - radiusX, centerY - radiusY, kernel.cols(), kernel.rows()); - Mat roiImage(imagePadded, area); + Mat roiMatrix(matrixPadded, area); Mat roiMask(maskPadded, area); Mat kernelMasked; kernel.copyTo(kernelMasked, roiMask); Mat numerator; - multiply(roiImage, kernelMasked, numerator, 1, CV_32F); + multiply(roiMatrix, kernelMasked, numerator, 1, CV_32F); Scalar component; divide(sum(numerator), sum(kernelMasked), component, 1, CV_32F); @@ -168,34 +181,43 @@ void ft::FT02D_process(const cv::Mat &image, const cv::Mat &kernel, cv::Mat &out Mat inverse; multiply(kernel, component, inverse, 1, CV_32F); - Mat roiOutput(output, area); + Mat roiOutput(outputZeroes, area); add(roiOutput, inverse, roiOutput); } } - output = output(Rect(radiusX, radiusY, image.cols, image.rows)); + outputZeroes(Rect(radiusX, radiusY, matrix.cols(), matrix.rows())).copyTo(output); } -int ft::FT02D_iteration(const Mat &image, const Mat &kernel, Mat &imageOutput, const Mat &mask, Mat &maskOutput, bool firstStop) +int ft::FT02D_iteration(InputArray matrix, InputArray kernel, OutputArray output, InputArray mask, OutputArray maskOutput, bool firstStop) { - CV_Assert(image.channels() == kernel.channels() && mask.channels() == 1); - - int radiusX = (kernel.cols - 1) / 2; - int radiusY = (kernel.rows - 1) / 2; - int An = image.cols / radiusX + 1; - int Bn = image.rows / radiusY + 1; - int outputWidthPadded = radiusX + image.cols + kernel.cols; - int outputHeightPadded = radiusY + image.rows + kernel.rows; + CV_Assert(matrix.channels() == kernel.channels() && mask.channels() == 1); + + int radiusX = (kernel.cols() - 1) / 2; + int radiusY = (kernel.rows() - 1) / 2; + int An = matrix.cols() / radiusX + 1; + int Bn = matrix.rows() / radiusY + 1; + int outputWidthPadded = radiusX + matrix.cols() + kernel.cols(); + int outputHeightPadded = radiusY + matrix.rows() + kernel.rows(); int undefinedComponents = 0; - Mat imagePadded; - Mat maskPadded; + output.create(matrix.size(), CV_MAKETYPE(CV_32F, matrix.channels())); + output.setTo(0); - imageOutput = Mat::zeros(outputHeightPadded, outputWidthPadded, CV_MAKETYPE(CV_32F, image.channels())); - maskOutput = Mat::ones(outputHeightPadded, outputWidthPadded, CV_8UC1); + if (maskOutput.needed()) + { + maskOutput.create(mask.rows(), mask.cols(), CV_8UC1); + maskOutput.setTo(1); + } - copyMakeBorder(image, imagePadded, radiusY, kernel.rows, radiusX, kernel.cols, BORDER_CONSTANT, Scalar(0)); - copyMakeBorder(mask, maskPadded, radiusY, kernel.rows, radiusX, kernel.cols, BORDER_CONSTANT, Scalar(0)); + Mat matrixOutputMat = Mat::zeros(outputHeightPadded, outputWidthPadded, CV_MAKETYPE(CV_32F, matrix.channels())); + Mat maskOutputMat = Mat::ones(outputHeightPadded, outputWidthPadded, CV_8UC1); + + Mat matrixPadded; + Mat maskPadded; + + copyMakeBorder(matrix, matrixPadded, radiusY, kernel.rows(), radiusX, kernel.cols(), BORDER_CONSTANT, Scalar(0)); + copyMakeBorder(mask, maskPadded, radiusY, kernel.rows(), radiusX, kernel.cols(), BORDER_CONSTANT, Scalar(0)); for (int i = 0; i < An; i++) { @@ -203,16 +225,16 @@ int ft::FT02D_iteration(const Mat &image, const Mat &kernel, Mat &imageOutput, c { int centerX = (i * radiusX) + radiusX; int centerY = (o * radiusY) + radiusY; - Rect area(centerX - radiusX, centerY - radiusY, kernel.cols, kernel.rows); + Rect area(centerX - radiusX, centerY - radiusY, kernel.cols(), kernel.rows()); - Mat roiImage(imagePadded, area); + Mat roiMatrix(matrixPadded, area); Mat roiMask(maskPadded, area); Mat kernelMasked; kernel.copyTo(kernelMasked, roiMask); Mat numerator; - multiply(roiImage, kernelMasked, numerator, 1, CV_32F); + multiply(roiMatrix, kernelMasked, numerator, 1, CV_32F); Scalar denominator = sum(kernelMasked); @@ -220,8 +242,8 @@ int ft::FT02D_iteration(const Mat &image, const Mat &kernel, Mat &imageOutput, c { if (firstStop) { - imageOutput = imageOutput(Rect(radiusX, radiusY, image.cols, image.rows)); - maskOutput = maskPadded(Rect(radiusX, radiusY, image.cols, image.rows)); + matrixOutputMat = matrixPadded(Rect(radiusX, radiusY, matrix.cols(), matrix.rows())); + maskOutputMat = maskPadded(Rect(radiusX, radiusY, matrix.cols(), matrix.rows())); return -1; } @@ -229,8 +251,8 @@ int ft::FT02D_iteration(const Mat &image, const Mat &kernel, Mat &imageOutput, c { undefinedComponents++; - Mat roiMaskOutput(maskOutput, Rect(centerX - radiusX + 1, centerY - radiusY + 1, kernel.cols - 2, kernel.rows - 2)); - roiMaskOutput = 0; + Mat roiMaskOutput(maskOutputMat, Rect(centerX - radiusX + 1, centerY - radiusY + 1, kernel.cols() - 2, kernel.rows() - 2)); + roiMaskOutput.setTo(0); continue; } @@ -242,13 +264,17 @@ int ft::FT02D_iteration(const Mat &image, const Mat &kernel, Mat &imageOutput, c Mat inverse; multiply(kernel, component, inverse, 1, CV_32F); - Mat roiImageOutput(imageOutput, area); - add(roiImageOutput, inverse, roiImageOutput); + Mat roiMatrixOutput(matrixOutputMat, area); + add(roiMatrixOutput, inverse, roiMatrixOutput); } } - imageOutput = imageOutput(Rect(radiusX, radiusY, image.cols, image.rows)); - maskOutput = maskOutput(Rect(radiusX, radiusY, image.cols, image.rows)); + matrixOutputMat(Rect(radiusX, radiusY, matrix.cols(), matrix.rows())).copyTo(output); + + if (maskOutput.needed()) + { + maskOutputMat(Rect(radiusX, radiusY, matrix.cols(), matrix.rows())).copyTo(maskOutput); + } return undefinedComponents; } diff --git a/modules/fuzzy/src/fuzzy_image.cpp b/modules/fuzzy/src/fuzzy_image.cpp index 3147383e8..c443a7041 100644 --- a/modules/fuzzy/src/fuzzy_image.cpp +++ b/modules/fuzzy/src/fuzzy_image.cpp @@ -58,7 +58,7 @@ void ft::createKernel(InputArray A, InputArray B, OutputArray kernel, const int merge(channels, kernel); } -void ft::createKernel(int function, int radius, cv::OutputArray kernel, const int chn) +void ft::createKernel(int function, int radius, OutputArray kernel, const int chn) { int basicFunctionWidth = 2 * radius + 1; Mat kernelOneChannel; @@ -91,7 +91,7 @@ void ft::createKernel(int function, int radius, cv::OutputArray kernel, const in merge(channels, kernel); } -void ft::inpaint(const cv::Mat &image, const cv::Mat &mask, cv::Mat &output, int radius, int function, int algorithm) +void ft::inpaint(InputArray image, InputArray mask, OutputArray output, int radius, int function, int algorithm) { if (algorithm == ft::ONE_STEP) { @@ -99,42 +99,32 @@ void ft::inpaint(const cv::Mat &image, const cv::Mat &mask, cv::Mat &output, int ft::createKernel(function, radius, kernel, image.channels()); Mat processingInput; - image.convertTo(processingInput, CV_32F); + image.getMat().convertTo(processingInput, CV_32F); - Mat processingOutput; - ft::FT02D_process(processingInput, kernel, processingOutput, mask); - - processingInput.copyTo(processingOutput, mask); + ft::FT02D_process(image, kernel, output, mask); - output = processingOutput; + processingInput.copyTo(output, mask); } else if (algorithm == ft::MULTI_STEP) { Mat kernel; - Mat processingOutput; - Mat outpuMask; int state = 0; int currentRadius = radius; Mat processingInput; - image.convertTo(processingInput, CV_32F); - - Mat processingMask; - cvtColor(mask, processingMask, COLOR_BGR2GRAY); + image.getMat().convertTo(processingInput, CV_32F); do { ft::createKernel(function, currentRadius, kernel, image.channels()); - state = ft::FT02D_iteration(processingInput, kernel, processingOutput, processingMask, outpuMask, true); + state = ft::FT02D_iteration(image, kernel, output, mask, noArray(), true); currentRadius++; } while(state != 0); - processingInput.copyTo(processingOutput, mask); - - output = processingOutput; + processingInput.copyTo(output, mask); } else if (algorithm == ft::ITERATIVE) { @@ -144,14 +134,11 @@ void ft::inpaint(const cv::Mat &image, const cv::Mat &mask, cv::Mat &output, int int state = 0; int currentRadius = radius; - Mat originalImage; - image.convertTo(originalImage, CV_32F); - Mat processingInput; - image.convertTo(processingInput, CV_32F); + image.getMat().convertTo(processingInput, CV_32F); Mat processingMask; - cvtColor(mask, processingMask, COLOR_BGR2GRAY); + mask.copyTo(processingMask); do { @@ -168,11 +155,11 @@ void ft::inpaint(const cv::Mat &image, const cv::Mat &mask, cv::Mat &output, int } while(state != 0); - output = processingInput; + processingInput.copyTo(output); } } -void ft::filter(const cv::Mat &image, const cv::Mat &kernel, cv::Mat &output) +void ft::filter(InputArray image, InputArray kernel, OutputArray output) { Mat mask = Mat::ones(image.size(), CV_8U); diff --git a/modules/fuzzy/test/test_f0.cpp b/modules/fuzzy/test/test_f0.cpp new file mode 100644 index 000000000..e9ff61ba0 --- /dev/null +++ b/modules/fuzzy/test/test_f0.cpp @@ -0,0 +1,164 @@ +/*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) 2015, University of Ostrava, Institute for Research and Applications of Fuzzy Modeling, +// Pavel Vlasanek, 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 + +using namespace std; +using namespace cv; + +TEST(fuzzy_f0, components) +{ + float arI[16][16] = + { + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 } + }; + Mat I = Mat(16, 16, CV_32F, arI); + + float arDemandedComp[9][9] = + { + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 } + }; + Mat demandedComp = Mat(9, 9, CV_32F, arDemandedComp); + + Mat kernel; + ft::createKernel(ft::LINEAR, 2, kernel, 1); + + Mat f0comp; + ft::FT02D_components(I, kernel, f0comp); + + double n1 = cvtest::norm(demandedComp, f0comp, NORM_INF); + + EXPECT_DOUBLE_EQ(n1, 0); +} + +TEST(fuzzy_f0, inversion) +{ + float arI[16][16] = + { + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 }, + { 0, 0, 0, 10, 34, 57, 80, 104, 127, 150, 174, 197, 221, 244, 255, 255 } + }; + Mat I = Mat(16, 16, CV_32F, arI); + + float arDemandedO[16][16] = + { + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 }, + { 0, 1.25, 2.5, 18.125, 33.75, 57, 80.25, 103.625, 127, 150.375, 173.75, 197.25, 220.75, 236.5, 252.25, 253.625 } + }; + Mat demandedO = Mat(16, 16, CV_32F, arDemandedO); + + float arComp[9][9] = + { + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 }, + { 0, 2.5, 33.75, 80.25, 127, 173.75, 220.75, 252.25, 255 } + }; + Mat comp = Mat(9, 9, CV_32F, arComp); + + Mat kernel; + ft::createKernel(ft::LINEAR, 2, kernel, 1); + + Mat O; + ft::FT02D_inverseFT(comp, kernel, O, 16, 16); + + double n1 = cvtest::norm(demandedO, O, NORM_INF); + + EXPECT_DOUBLE_EQ(n1, 0); +} \ No newline at end of file diff --git a/modules/fuzzy/test/test_image.cpp b/modules/fuzzy/test/test_image.cpp index 7924d2d5c..fd22e4719 100644 --- a/modules/fuzzy/test/test_image.cpp +++ b/modules/fuzzy/test/test_image.cpp @@ -40,84 +40,75 @@ //M*/ #include "test_precomp.hpp" + #include using namespace std; using namespace cv; -class CV_FuzzyImageTest : public cvtest::BaseTest -{ -public: - CV_FuzzyImageTest(); - ~CV_FuzzyImageTest(); -protected: - void run(int); -}; - -CV_FuzzyImageTest::CV_FuzzyImageTest() -{ -} -CV_FuzzyImageTest::~CV_FuzzyImageTest() {} - -void CV_FuzzyImageTest::run( int ) +TEST(fuzzy_image, inpainting) { - string folder = string(ts->get_data_path()) + "fuzzy/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "fuzzy/"; Mat orig = imread(folder + "orig.png"); Mat exp1 = imread(folder + "exp1.png"); Mat exp2 = imread(folder + "exp2.png"); Mat exp3 = imread(folder + "exp3.png"); - Mat mask1 = imread(folder + "mask1.png"); - Mat mask2 = imread(folder + "mask2.png"); - - if (orig.empty() || exp1.empty() || exp2.empty() || mask1.empty() || mask2.empty()) - { - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); - return; - } + Mat mask1 = imread(folder + "mask1.png", IMREAD_GRAYSCALE); + Mat mask2 = imread(folder + "mask2.png", IMREAD_GRAYSCALE); - // Conversion because of comparison. + EXPECT_TRUE(!orig.empty() && !exp1.empty() && !exp2.empty() && !exp3.empty() && !mask1.empty() && !mask2.empty()); - orig.convertTo(orig, CV_32F); - exp1.convertTo(exp1, CV_32F); - exp2.convertTo(exp2, CV_32F); - exp3.convertTo(exp3, CV_32F); - - Mat res1, res2,res3; + Mat res1, res2, res3; ft::inpaint(orig, mask1, res1, 2, ft::LINEAR, ft::ONE_STEP); ft::inpaint(orig, mask2, res2, 2, ft::LINEAR, ft::MULTI_STEP); ft::inpaint(orig, mask2, res3, 2, ft::LINEAR, ft::ITERATIVE); - Mat diff1, diff2, diff3; - absdiff(orig, res1, diff1); - absdiff(orig, res2, diff2); - absdiff(orig, res3, diff3); - - double n1 = cvtest::norm(diff1.reshape(1), NORM_INF, mask1.reshape(1)); - double n2 = cvtest::norm(diff2.reshape(1), NORM_INF, mask2.reshape(1)); - double n3 = cvtest::norm(diff3.reshape(1), NORM_INF, mask2.reshape(1)); - - if (n1 != 0 || n2 != 0 || n3 != 0) - { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - return; - } - - absdiff(exp1, res1, diff1); - absdiff(exp2, res2, diff2); - absdiff(exp3, res3, diff3); - - n1 = cvtest::norm(diff1.reshape(1), NORM_INF, mask1.reshape(1)); - n2 = cvtest::norm(diff2.reshape(1), NORM_INF, mask2.reshape(1)); - n3 = cvtest::norm(diff3.reshape(1), NORM_INF, mask2.reshape(1)); - - const int jpeg_thres = 3; - if (n1 > jpeg_thres || n2 > jpeg_thres || n3 > jpeg_thres) - { - ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); - return; - } - - ts->set_failed_test_info(cvtest::TS::OK); + res1.convertTo(res1, CV_8UC3); + res2.convertTo(res2, CV_8UC3); + res3.convertTo(res3, CV_8UC3); + + double n1 = cvtest::norm(exp1, res1, NORM_INF); + double n2 = cvtest::norm(exp2, res2, NORM_INF); + double n3 = cvtest::norm(exp3, res3, NORM_INF); + + EXPECT_LE(n1, 1); + EXPECT_LE(n2, 1); + EXPECT_LE(n3, 1); +} + +TEST(fuzzy_image, filtering) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "fuzzy/"; + Mat orig = imread(folder + "orig.png"); + Mat exp4 = imread(folder + "exp4.png"); + + EXPECT_TRUE(!orig.empty() && !exp4.empty()); + + Mat kernel; + ft::createKernel(ft::LINEAR, 20, kernel, 3); + + Mat res4; + ft::filter(orig, kernel, res4); + + res4.convertTo(res4, CV_8UC3); + + double n1 = cvtest::norm(exp4, res4, NORM_INF); + + EXPECT_LE(n1, 1); } -TEST(Fuzzy_image, regression) { CV_FuzzyImageTest test; test.safe_run(); } +TEST(fuzzy_image, kernel) +{ + Mat kernel1; + ft::createKernel(ft::LINEAR, 2, kernel1, 1); + + Mat vector1 = (Mat_(5, 1) << 0, 0.5, 1, 0.5, 0); + Mat vector2 = (Mat_(1, 5) << 0, 0.5, 1, 0.5, 0); + + Mat kernel2; + ft::createKernel(vector1, vector2, kernel2, 1); + + double diff = cvtest::norm(kernel1, kernel2, NORM_INF); + + EXPECT_DOUBLE_EQ(diff, 0); +} \ No newline at end of file