vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Nathan, liujun@multicorewareinc.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(AccumulateBase, std::pair<MatDepth, MatDepth>, Channels, bool)
|
||||
{
|
||||
int sdepth, ddepth, channels;
|
||||
bool useRoi;
|
||||
double alpha;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_INPUT_PARAMETER(mask);
|
||||
TEST_DECLARE_INPUT_PARAMETER(src2);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
const std::pair<MatDepth, MatDepth> depths = GET_PARAM(0);
|
||||
sdepth = depths.first, ddepth = depths.second;
|
||||
channels = GET_PARAM(1);
|
||||
useRoi = GET_PARAM(2);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
const int stype = CV_MAKE_TYPE(sdepth, channels),
|
||||
dtype = CV_MAKE_TYPE(ddepth, channels);
|
||||
|
||||
Size roiSize = randomSize(1, 10);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, stype, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border maskBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(mask, mask_roi, roiSize, maskBorder, CV_8UC1, -MAX_VALUE, MAX_VALUE);
|
||||
cvtest::threshold(mask, mask, 80, 255, THRESH_BINARY);
|
||||
|
||||
Border src2Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src2, src2_roi, roiSize, src2Border, stype, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, dtype, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(mask);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src2);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
|
||||
alpha = randomDouble(-5, 5);
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////// Accumulate ///////////////////////////////////
|
||||
|
||||
typedef AccumulateBase Accumulate;
|
||||
|
||||
OCL_TEST_P(Accumulate, Mat)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulate(src_roi, dst_roi));
|
||||
OCL_ON(cv::accumulate(usrc_roi, udst_roi));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Accumulate, Mask)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulate(src_roi, dst_roi, mask_roi));
|
||||
OCL_ON(cv::accumulate(usrc_roi, udst_roi, umask_roi));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////// AccumulateSquare ///////////////////////////////////
|
||||
|
||||
typedef AccumulateBase AccumulateSquare;
|
||||
|
||||
OCL_TEST_P(AccumulateSquare, Mat)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulateSquare(src_roi, dst_roi));
|
||||
OCL_ON(cv::accumulateSquare(usrc_roi, udst_roi));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-2);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(AccumulateSquare, Mask)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulateSquare(src_roi, dst_roi, mask_roi));
|
||||
OCL_ON(cv::accumulateSquare(usrc_roi, udst_roi, umask_roi));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-2);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////// AccumulateProduct ///////////////////////////////////
|
||||
|
||||
typedef AccumulateBase AccumulateProduct;
|
||||
|
||||
OCL_TEST_P(AccumulateProduct, Mat)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulateProduct(src_roi, src2_roi, dst_roi));
|
||||
OCL_ON(cv::accumulateProduct(usrc_roi, usrc2_roi, udst_roi));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-2);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(AccumulateProduct, Mask)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulateProduct(src_roi, src2_roi, dst_roi, mask_roi));
|
||||
OCL_ON(cv::accumulateProduct(usrc_roi, usrc2_roi, udst_roi, umask_roi));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-2);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////// AccumulateWeighted ///////////////////////////////////
|
||||
|
||||
typedef AccumulateBase AccumulateWeighted;
|
||||
|
||||
OCL_TEST_P(AccumulateWeighted, Mat)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulateWeighted(src_roi, dst_roi, alpha));
|
||||
OCL_ON(cv::accumulateWeighted(usrc_roi, udst_roi, alpha));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-2);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(AccumulateWeighted, Mask)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::accumulateWeighted(src_roi, dst_roi, alpha));
|
||||
OCL_ON(cv::accumulateWeighted(usrc_roi, udst_roi, alpha));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 1e-2);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////// Instantiation ///////////////////////////////////
|
||||
|
||||
#define OCL_DEPTH_ALL_COMBINATIONS \
|
||||
testing::Values(std::make_pair<MatDepth, MatDepth>(CV_8U, CV_32F), \
|
||||
std::make_pair<MatDepth, MatDepth>(CV_16U, CV_32F), \
|
||||
std::make_pair<MatDepth, MatDepth>(CV_32F, CV_32F), \
|
||||
std::make_pair<MatDepth, MatDepth>(CV_8U, CV_64F), \
|
||||
std::make_pair<MatDepth, MatDepth>(CV_16U, CV_64F), \
|
||||
std::make_pair<MatDepth, MatDepth>(CV_32F, CV_64F), \
|
||||
std::make_pair<MatDepth, MatDepth>(CV_64F, CV_64F))
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, Accumulate, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, AccumulateSquare, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, AccumulateProduct, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, AccumulateWeighted, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool()));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Nathan, liujun@multicorewareinc.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(BlendLinear, MatDepth, Channels, bool)
|
||||
{
|
||||
int depth, channels;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src1);
|
||||
TEST_DECLARE_INPUT_PARAMETER(src2);
|
||||
TEST_DECLARE_INPUT_PARAMETER(weights2);
|
||||
TEST_DECLARE_INPUT_PARAMETER(weights1);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
channels = GET_PARAM(1);
|
||||
useRoi = GET_PARAM(2);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
const double upValue = 256;
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border src1Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src1, src1_roi, roiSize, src1Border, type, -upValue, upValue);
|
||||
|
||||
Border src2Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src2, src2_roi, roiSize, src2Border, type, -upValue, upValue);
|
||||
|
||||
Border weights1Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(weights1, weights1_roi, roiSize, weights1Border, CV_32FC1, -upValue, upValue);
|
||||
|
||||
Border weights2Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(weights2, weights2_roi, roiSize, weights2Border, CV_32FC1, 1e-2, upValue);
|
||||
|
||||
weights2_roi -= weights1_roi;
|
||||
CV_Assert(checkNorm2(weights2_roi, weights2(Rect(weights2Border.lef, weights2Border.top,
|
||||
roiSize.width, roiSize.height))) < 1e-6);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src1);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src2);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(weights1);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(weights2);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double eps = 0.0)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, eps);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(BlendLinear, Accuracy)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::blendLinear(src1_roi, src2_roi, weights1_roi, weights2_roi, dst_roi));
|
||||
OCL_ON(cv::blendLinear(usrc1_roi, usrc2_roi, uweights1_roi, uweights2_roi, udst_roi));
|
||||
|
||||
Near(depth <= CV_32S ? 1.0 : 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, BlendLinear, Combine(testing::Values(CV_8U, CV_32F), OCL_ALL_CHANNELS, Bool()));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,236 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
////////////////////////////////////////// boxFilter ///////////////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(BoxFilterBase, MatDepth, Channels, BorderType, bool, bool)
|
||||
{
|
||||
static const int kernelMinSize = 2;
|
||||
static const int kernelMaxSize = 10;
|
||||
|
||||
int depth, cn, borderType;
|
||||
Size ksize, dsize;
|
||||
Point anchor;
|
||||
bool normalize, useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
cn = GET_PARAM(1);
|
||||
borderType = GET_PARAM(2); // only not isolated border tested, because CPU module doesn't support isolated border case.
|
||||
normalize = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
int type = CV_MAKE_TYPE(depth, cn);
|
||||
ksize = randomSize(kernelMinSize, kernelMaxSize);
|
||||
|
||||
Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
anchor.x = randomInt(-1, ksize.width);
|
||||
anchor.y = randomInt(-1, ksize.height);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
typedef BoxFilterBase BoxFilter;
|
||||
|
||||
OCL_TEST_P(BoxFilter, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::boxFilter(src_roi, dst_roi, -1, ksize, anchor, normalize, borderType));
|
||||
OCL_ON(cv::boxFilter(usrc_roi, udst_roi, -1, ksize, anchor, normalize, borderType));
|
||||
|
||||
Near(depth <= CV_32S ? 1 : 3e-3);
|
||||
}
|
||||
}
|
||||
|
||||
typedef BoxFilterBase SqrBoxFilter;
|
||||
|
||||
OCL_TEST_P(SqrBoxFilter, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
int ddepth = depth == CV_8U ? CV_32S : CV_64F;
|
||||
|
||||
OCL_OFF(cv::sqrBoxFilter(src_roi, dst_roi, ddepth, ksize, anchor, normalize, borderType));
|
||||
OCL_ON(cv::sqrBoxFilter(usrc_roi, udst_roi, ddepth, ksize, anchor, normalize, borderType));
|
||||
|
||||
Near(depth <= CV_32S ? 1 : 7e-2);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, BoxFilter,
|
||||
Combine(
|
||||
Values(CV_8U, CV_16U, CV_16S, CV_32S, CV_32F),
|
||||
OCL_ALL_CHANNELS,
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool(),
|
||||
Bool() // ROI
|
||||
)
|
||||
);
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, SqrBoxFilter,
|
||||
Combine(
|
||||
Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F),
|
||||
OCL_ALL_CHANNELS,
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool(),
|
||||
Bool() // ROI
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
PARAM_TEST_CASE(BoxFilter3x3_cols16_rows2_Base, MatDepth, Channels, BorderType, bool, bool)
|
||||
{
|
||||
int depth, cn, borderType;
|
||||
Size ksize, dsize;
|
||||
Point anchor;
|
||||
bool normalize, useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
cn = GET_PARAM(1);
|
||||
borderType = GET_PARAM(2); // only not isolated border tested, because CPU module doesn't support isolated border case.
|
||||
normalize = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
int type = CV_MAKE_TYPE(depth, cn);
|
||||
ksize = Size(3,3);
|
||||
|
||||
Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE);
|
||||
roiSize.width = std::max(ksize.width + 13, roiSize.width & (~0xf));
|
||||
roiSize.height = std::max(ksize.height + 1, roiSize.height & (~0x1));
|
||||
Border srcBorder = {0, 0, 0, 0};
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = {0, 0, 0, 0};
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
anchor.x = -1;
|
||||
anchor.y = -1;
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
typedef BoxFilter3x3_cols16_rows2_Base BoxFilter3x3_cols16_rows2;
|
||||
|
||||
OCL_TEST_P(BoxFilter3x3_cols16_rows2, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::boxFilter(src_roi, dst_roi, -1, ksize, anchor, normalize, borderType));
|
||||
OCL_ON(cv::boxFilter(usrc_roi, udst_roi, -1, ksize, anchor, normalize, borderType));
|
||||
|
||||
Near(depth <= CV_32S ? 1 : 3e-3);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, BoxFilter3x3_cols16_rows2,
|
||||
Combine(
|
||||
Values((MatDepth)CV_8U),
|
||||
Values((Channels)1),
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool(),
|
||||
Values(false) // ROI
|
||||
)
|
||||
);
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Peng Xiao, pengxiao@multicorewareinc.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Canny
|
||||
|
||||
IMPLEMENT_PARAM_CLASS(ApertureSize, int)
|
||||
IMPLEMENT_PARAM_CLASS(L2gradient, bool)
|
||||
IMPLEMENT_PARAM_CLASS(UseRoi, bool)
|
||||
|
||||
PARAM_TEST_CASE(Canny, Channels, ApertureSize, L2gradient, UseRoi)
|
||||
{
|
||||
int cn, aperture_size;
|
||||
bool useL2gradient, use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
cn = GET_PARAM(0);
|
||||
aperture_size = GET_PARAM(1);
|
||||
useL2gradient = GET_PARAM(2);
|
||||
use_roi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
void generateTestData()
|
||||
{
|
||||
Mat img = readImageType("shared/fruits.png", CV_8UC(cn));
|
||||
ASSERT_FALSE(img.empty()) << "can't load shared/fruits.png";
|
||||
|
||||
Size roiSize = img.size();
|
||||
int type = img.type();
|
||||
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 2, 100);
|
||||
img.copyTo(src_roi);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Canny, Accuracy)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
const double low_thresh = 50.0, high_thresh = 100.0;
|
||||
double eps = 0.03;
|
||||
|
||||
OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient));
|
||||
OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, aperture_size, useL2gradient));
|
||||
|
||||
EXPECT_MAT_SIMILAR(dst_roi, udst_roi, eps);
|
||||
EXPECT_MAT_SIMILAR(dst, udst, eps);
|
||||
}
|
||||
|
||||
OCL_TEST_P(Canny, AccuracyCustomGradient)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
const double low_thresh = 50.0, high_thresh = 100.0;
|
||||
double eps = 0.03;
|
||||
|
||||
OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient));
|
||||
OCL_ON(
|
||||
UMat dx, dy;
|
||||
Sobel(usrc_roi, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(usrc_roi, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
cv::Canny(dx, dy, udst_roi, low_thresh, high_thresh, useL2gradient);
|
||||
);
|
||||
|
||||
EXPECT_MAT_SIMILAR(dst_roi, udst_roi, eps);
|
||||
EXPECT_MAT_SIMILAR(dst, udst, eps);
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, Canny, testing::Combine(
|
||||
testing::Values(1, 3),
|
||||
testing::Values(ApertureSize(3), ApertureSize(5)),
|
||||
testing::Values(L2gradient(false), L2gradient(true)),
|
||||
testing::Values(UseRoi(false), UseRoi(true))));
|
||||
|
||||
} // namespace ocl
|
||||
|
||||
} // namespace opencv_test
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,532 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Peng Xiao, pengxiao@multicorewareinc.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cvtColor
|
||||
|
||||
PARAM_TEST_CASE(CvtColor, MatDepth, bool)
|
||||
{
|
||||
int depth;
|
||||
bool use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
use_roi = GET_PARAM(1);
|
||||
}
|
||||
|
||||
virtual void generateTestData(int channelsIn, int channelsOut)
|
||||
{
|
||||
const int srcType = CV_MAKE_TYPE(depth, channelsIn);
|
||||
const int dstType = CV_MAKE_TYPE(depth, channelsOut);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
|
||||
void performTest(int channelsIn, int channelsOut, int code, double threshold = 1e-3)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData(channelsIn, channelsOut);
|
||||
|
||||
OCL_OFF(cv::cvtColor(src_roi, dst_roi, code, channelsOut));
|
||||
OCL_ON(cv::cvtColor(usrc_roi, udst_roi, code, channelsOut));
|
||||
|
||||
int h_limit = 256;
|
||||
switch (code)
|
||||
{
|
||||
case COLOR_RGB2HLS: case COLOR_BGR2HLS:
|
||||
h_limit = 180;
|
||||
/* fallthrough */
|
||||
case COLOR_RGB2HLS_FULL: case COLOR_BGR2HLS_FULL:
|
||||
{
|
||||
ASSERT_EQ(dst_roi.type(), udst_roi.type());
|
||||
ASSERT_EQ(dst_roi.size(), udst_roi.size());
|
||||
Mat gold, actual;
|
||||
dst_roi.convertTo(gold, CV_32FC3);
|
||||
udst_roi.getMat(ACCESS_READ).convertTo(actual, CV_32FC3);
|
||||
Mat absdiff1, absdiff2, absdiff3;
|
||||
cv::absdiff(gold, actual, absdiff1);
|
||||
cv::absdiff(gold, actual + h_limit, absdiff2);
|
||||
cv::absdiff(gold, actual - h_limit, absdiff3);
|
||||
Mat diff = cv::min(cv::min(absdiff1, absdiff2), absdiff3);
|
||||
EXPECT_LE(cvtest::norm(diff, NORM_INF), threshold);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Near(threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define CVTCODE(name) COLOR_ ## name
|
||||
|
||||
// RGB[A] <-> BGR[A]
|
||||
|
||||
OCL_TEST_P(CvtColor, BGR2BGRA) { performTest(3, 4, CVTCODE(BGR2BGRA)); }
|
||||
OCL_TEST_P(CvtColor, RGB2RGBA) { performTest(3, 4, CVTCODE(RGB2RGBA)); }
|
||||
OCL_TEST_P(CvtColor, BGRA2BGR) { performTest(4, 3, CVTCODE(BGRA2BGR)); }
|
||||
OCL_TEST_P(CvtColor, RGBA2RGB) { performTest(4, 3, CVTCODE(RGBA2RGB)); }
|
||||
OCL_TEST_P(CvtColor, BGR2RGBA) { performTest(3, 4, CVTCODE(BGR2RGBA)); }
|
||||
OCL_TEST_P(CvtColor, RGB2BGRA) { performTest(3, 4, CVTCODE(RGB2BGRA)); }
|
||||
OCL_TEST_P(CvtColor, RGBA2BGR) { performTest(4, 3, CVTCODE(RGBA2BGR)); }
|
||||
OCL_TEST_P(CvtColor, BGRA2RGB) { performTest(4, 3, CVTCODE(BGRA2RGB)); }
|
||||
OCL_TEST_P(CvtColor, BGR2RGB) { performTest(3, 3, CVTCODE(BGR2RGB)); }
|
||||
OCL_TEST_P(CvtColor, RGB2BGR) { performTest(3, 3, CVTCODE(RGB2BGR)); }
|
||||
OCL_TEST_P(CvtColor, BGRA2RGBA) { performTest(4, 4, CVTCODE(BGRA2RGBA)); }
|
||||
OCL_TEST_P(CvtColor, RGBA2BGRA) { performTest(4, 4, CVTCODE(RGBA2BGRA)); }
|
||||
|
||||
// RGB <-> Gray
|
||||
|
||||
OCL_TEST_P(CvtColor, RGB2GRAY) { performTest(3, 1, CVTCODE(RGB2GRAY)); }
|
||||
OCL_TEST_P(CvtColor, GRAY2RGB) { performTest(1, 3, CVTCODE(GRAY2RGB)); }
|
||||
OCL_TEST_P(CvtColor, BGR2GRAY) { performTest(3, 1, CVTCODE(BGR2GRAY)); }
|
||||
OCL_TEST_P(CvtColor, GRAY2BGR) { performTest(1, 3, CVTCODE(GRAY2BGR)); }
|
||||
OCL_TEST_P(CvtColor, RGBA2GRAY) { performTest(4, 1, CVTCODE(RGBA2GRAY)); }
|
||||
OCL_TEST_P(CvtColor, GRAY2RGBA) { performTest(1, 4, CVTCODE(GRAY2RGBA)); }
|
||||
OCL_TEST_P(CvtColor, BGRA2GRAY) { performTest(4, 1, CVTCODE(BGRA2GRAY), cv::ocl::Device::getDefault().isNVidia() ? 1 : 1e-3); }
|
||||
OCL_TEST_P(CvtColor, GRAY2BGRA) { performTest(1, 4, CVTCODE(GRAY2BGRA)); }
|
||||
|
||||
// RGB <-> YUV
|
||||
|
||||
OCL_TEST_P(CvtColor, RGB2YUV) { performTest(3, 3, CVTCODE(RGB2YUV)); }
|
||||
OCL_TEST_P(CvtColor, BGR2YUV) { performTest(3, 3, CVTCODE(BGR2YUV)); }
|
||||
OCL_TEST_P(CvtColor, RGBA2YUV) { performTest(4, 3, CVTCODE(RGB2YUV)); }
|
||||
OCL_TEST_P(CvtColor, BGRA2YUV) { performTest(4, 3, CVTCODE(BGR2YUV)); }
|
||||
OCL_TEST_P(CvtColor, YUV2RGB) { performTest(3, 3, CVTCODE(YUV2RGB)); }
|
||||
OCL_TEST_P(CvtColor, YUV2BGR) { performTest(3, 3, CVTCODE(YUV2BGR)); }
|
||||
OCL_TEST_P(CvtColor, YUV2RGBA) { performTest(3, 4, CVTCODE(YUV2RGB)); }
|
||||
OCL_TEST_P(CvtColor, YUV2BGRA) { performTest(3, 4, CVTCODE(YUV2BGR)); }
|
||||
|
||||
// RGB <-> YCrCb
|
||||
|
||||
#define EPS_FOR_FLOATING_POINT(e) (CV_32F <= depth ? e : 1)
|
||||
|
||||
OCL_TEST_P(CvtColor, RGB2YCrCb) { performTest(3, 3, CVTCODE(RGB2YCrCb), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor, BGR2YCrCb) { performTest(3, 3, CVTCODE(BGR2YCrCb), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor, RGBA2YCrCb) { performTest(4, 3, CVTCODE(RGB2YCrCb), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor, BGRA2YCrCb) { performTest(4, 3, CVTCODE(BGR2YCrCb), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor, YCrCb2RGB) { performTest(3, 3, CVTCODE(YCrCb2RGB)); }
|
||||
OCL_TEST_P(CvtColor, YCrCb2BGR) { performTest(3, 3, CVTCODE(YCrCb2BGR)); }
|
||||
OCL_TEST_P(CvtColor, YCrCb2RGBA) { performTest(3, 4, CVTCODE(YCrCb2RGB)); }
|
||||
OCL_TEST_P(CvtColor, YCrCb2BGRA) { performTest(3, 4, CVTCODE(YCrCb2BGR)); }
|
||||
|
||||
// RGB <-> XYZ
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#define IPP_EPS depth <= CV_32S ? 1 : 5e-5
|
||||
#else
|
||||
#define IPP_EPS 1e-3
|
||||
#endif
|
||||
|
||||
OCL_TEST_P(CvtColor, RGB2XYZ) { performTest(3, 3, CVTCODE(RGB2XYZ), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor, BGR2XYZ) { performTest(3, 3, CVTCODE(BGR2XYZ), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor, RGBA2XYZ) { performTest(4, 3, CVTCODE(RGB2XYZ), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor, BGRA2XYZ) { performTest(4, 3, CVTCODE(BGR2XYZ), IPP_EPS); }
|
||||
|
||||
OCL_TEST_P(CvtColor, XYZ2RGB) { performTest(3, 3, CVTCODE(XYZ2RGB), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor, XYZ2BGR) { performTest(3, 3, CVTCODE(XYZ2BGR), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor, XYZ2RGBA) { performTest(3, 4, CVTCODE(XYZ2RGB), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor, XYZ2BGRA) { performTest(3, 4, CVTCODE(XYZ2BGR), IPP_EPS); }
|
||||
|
||||
#undef IPP_EPS
|
||||
|
||||
// RGB <-> HSV
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#define IPP_EPS depth <= CV_32S ? 1 : 4e-5
|
||||
#else
|
||||
#define IPP_EPS EPS_FOR_FLOATING_POINT(1e-3)
|
||||
#endif
|
||||
|
||||
typedef CvtColor CvtColor8u32f;
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, RGB2HSV) { performTest(3, 3, CVTCODE(RGB2HSV), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGR2HSV) { performTest(3, 3, CVTCODE(BGR2HSV), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGBA2HSV) { performTest(4, 3, CVTCODE(RGB2HSV), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGRA2HSV) { performTest(4, 3, CVTCODE(BGR2HSV), IPP_EPS); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, RGB2HSV_FULL) { performTest(3, 3, CVTCODE(RGB2HSV_FULL), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGR2HSV_FULL) { performTest(3, 3, CVTCODE(BGR2HSV_FULL), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGBA2HSV_FULL) { performTest(4, 3, CVTCODE(RGB2HSV_FULL), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGRA2HSV_FULL) { performTest(4, 3, CVTCODE(BGR2HSV_FULL), IPP_EPS); }
|
||||
|
||||
#undef IPP_EPS
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2RGB) { performTest(3, 3, CVTCODE(HSV2RGB), depth == CV_8U ? 1 : 4e-1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2BGR) { performTest(3, 3, CVTCODE(HSV2BGR), depth == CV_8U ? 1 : 4e-1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2RGBA) { performTest(3, 4, CVTCODE(HSV2RGB), depth == CV_8U ? 1 : 4e-1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2BGRA) { performTest(3, 4, CVTCODE(HSV2BGR), depth == CV_8U ? 1 : 4e-1); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2RGB_FULL) { performTest(3, 3, CVTCODE(HSV2RGB_FULL), depth == CV_8U ? 1 : 4e-1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2BGR_FULL) { performTest(3, 3, CVTCODE(HSV2BGR_FULL), depth == CV_8U ? 1 : 4e-1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2RGBA_FULL) { performTest(3, 4, CVTCODE(HSV2BGR_FULL), depth == CV_8U ? 1 : 4e-1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HSV2BGRA_FULL) { performTest(3, 4, CVTCODE(HSV2BGR_FULL), depth == CV_8U ? 1 : 4e-1); }
|
||||
|
||||
// RGB <-> HLS
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#define IPP_EPS depth == CV_8U ? 2 : 1e-3
|
||||
#else
|
||||
#define IPP_EPS depth == CV_8U ? 1 : 1e-3
|
||||
#endif
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, RGB2HLS) { performTest(3, 3, CVTCODE(RGB2HLS), depth == CV_8U ? 1 : 1e-3); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGR2HLS) { performTest(3, 3, CVTCODE(BGR2HLS), depth == CV_8U ? 1 : 1e-3); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGBA2HLS) { performTest(4, 3, CVTCODE(RGB2HLS), depth == CV_8U ? 1 : 1e-3); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGRA2HLS) { performTest(4, 3, CVTCODE(BGR2HLS), depth == CV_8U ? 1 : 1e-3); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, RGB2HLS_FULL) { performTest(3, 3, CVTCODE(RGB2HLS_FULL), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGR2HLS_FULL) { performTest(3, 3, CVTCODE(BGR2HLS_FULL), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGBA2HLS_FULL) { performTest(4, 3, CVTCODE(RGB2HLS_FULL), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGRA2HLS_FULL) { performTest(4, 3, CVTCODE(BGR2HLS_FULL), IPP_EPS); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2RGB) { performTest(3, 3, CVTCODE(HLS2RGB), 1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2BGR) { performTest(3, 3, CVTCODE(HLS2BGR), 1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2RGBA) { performTest(3, 4, CVTCODE(HLS2RGB), 1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2BGRA) { performTest(3, 4, CVTCODE(HLS2BGR), 1); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2RGB_FULL) { performTest(3, 3, CVTCODE(HLS2RGB_FULL), 1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2BGR_FULL) { performTest(3, 3, CVTCODE(HLS2BGR_FULL), 1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2RGBA_FULL) { performTest(3, 4, CVTCODE(HLS2RGB_FULL), 1); }
|
||||
OCL_TEST_P(CvtColor8u32f, HLS2BGRA_FULL) { performTest(3, 4, CVTCODE(HLS2BGR_FULL), 1); }
|
||||
|
||||
#undef IPP_EPS
|
||||
|
||||
// RGB5x5 <-> RGB
|
||||
|
||||
typedef CvtColor CvtColor8u;
|
||||
|
||||
OCL_TEST_P(CvtColor8u, BGR5652BGR) { performTest(2, 3, CVTCODE(BGR5652BGR)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5652RGB) { performTest(2, 3, CVTCODE(BGR5652RGB)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5652BGRA) { performTest(2, 4, CVTCODE(BGR5652BGRA)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5652RGBA) { performTest(2, 4, CVTCODE(BGR5652RGBA)); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u, BGR5552BGR) { performTest(2, 3, CVTCODE(BGR5552BGR)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5552RGB) { performTest(2, 3, CVTCODE(BGR5552RGB)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5552BGRA) { performTest(2, 4, CVTCODE(BGR5552BGRA)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5552RGBA) { performTest(2, 4, CVTCODE(BGR5552RGBA)); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u, BGR2BGR565) { performTest(3, 2, CVTCODE(BGR2BGR565)); }
|
||||
OCL_TEST_P(CvtColor8u, RGB2BGR565) { performTest(3, 2, CVTCODE(RGB2BGR565)); }
|
||||
OCL_TEST_P(CvtColor8u, BGRA2BGR565) { performTest(4, 2, CVTCODE(BGRA2BGR565)); }
|
||||
OCL_TEST_P(CvtColor8u, RGBA2BGR565) { performTest(4, 2, CVTCODE(RGBA2BGR565)); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u, BGR2BGR555) { performTest(3, 2, CVTCODE(BGR2BGR555)); }
|
||||
OCL_TEST_P(CvtColor8u, RGB2BGR555) { performTest(3, 2, CVTCODE(RGB2BGR555)); }
|
||||
OCL_TEST_P(CvtColor8u, BGRA2BGR555) { performTest(4, 2, CVTCODE(BGRA2BGR555)); }
|
||||
OCL_TEST_P(CvtColor8u, RGBA2BGR555) { performTest(4, 2, CVTCODE(RGBA2BGR555)); }
|
||||
|
||||
// RGB5x5 <-> Gray
|
||||
|
||||
OCL_TEST_P(CvtColor8u, BGR5652GRAY) { performTest(2, 1, CVTCODE(BGR5652GRAY)); }
|
||||
OCL_TEST_P(CvtColor8u, BGR5552GRAY) { performTest(2, 1, CVTCODE(BGR5552GRAY)); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u, GRAY2BGR565) { performTest(1, 2, CVTCODE(GRAY2BGR565)); }
|
||||
OCL_TEST_P(CvtColor8u, GRAY2BGR555) { performTest(1, 2, CVTCODE(GRAY2BGR555)); }
|
||||
|
||||
// RGBA <-> mRGBA
|
||||
|
||||
#if defined(HAVE_IPP) || defined(__arm__)
|
||||
#define IPP_EPS depth <= CV_32S ? 1 : 1e-3
|
||||
#else
|
||||
#define IPP_EPS 1e-3
|
||||
#endif
|
||||
|
||||
OCL_TEST_P(CvtColor8u, RGBA2mRGBA) { performTest(4, 4, CVTCODE(RGBA2mRGBA), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u, mRGBA2RGBA) { performTest(4, 4, CVTCODE(mRGBA2RGBA), IPP_EPS); }
|
||||
|
||||
// RGB <-> Lab
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, BGR2Lab) { performTest(3, 3, CVTCODE(BGR2Lab)); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGB2Lab) { performTest(3, 3, CVTCODE(RGB2Lab)); }
|
||||
OCL_TEST_P(CvtColor8u32f, LBGR2Lab) { performTest(3, 3, CVTCODE(LBGR2Lab), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, LRGB2Lab) { performTest(3, 3, CVTCODE(LRGB2Lab), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGRA2Lab) { performTest(4, 3, CVTCODE(BGR2Lab)); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGBA2Lab) { performTest(4, 3, CVTCODE(RGB2Lab)); }
|
||||
OCL_TEST_P(CvtColor8u32f, LBGRA2Lab) { performTest(4, 3, CVTCODE(LBGR2Lab), IPP_EPS); }
|
||||
OCL_TEST_P(CvtColor8u32f, LRGBA2Lab) { performTest(4, 3, CVTCODE(LRGB2Lab), IPP_EPS); }
|
||||
|
||||
#undef IPP_EPS
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2BGR) { performTest(3, 3, CVTCODE(Lab2BGR), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2RGB) { performTest(3, 3, CVTCODE(Lab2RGB), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2LBGR) { performTest(3, 3, CVTCODE(Lab2LBGR), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2LRGB) { performTest(3, 3, CVTCODE(Lab2LRGB), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2BGRA) { performTest(3, 4, CVTCODE(Lab2BGR), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2RGBA) { performTest(3, 4, CVTCODE(Lab2RGB), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2LBGRA) { performTest(3, 4, CVTCODE(Lab2LBGR), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Lab2LRGBA) { performTest(3, 4, CVTCODE(Lab2LRGB), depth == CV_8U ? 1 : 1e-5); }
|
||||
|
||||
// RGB -> Luv
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, BGR2Luv) { performTest(3, 3, CVTCODE(BGR2Luv), depth == CV_8U ? 1 : 1.5e-2); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGB2Luv) { performTest(3, 3, CVTCODE(RGB2Luv), depth == CV_8U ? 1 : 1.5e-2); }
|
||||
OCL_TEST_P(CvtColor8u32f, LBGR2Luv) { performTest(3, 3, CVTCODE(LBGR2Luv), depth == CV_8U ? 1 : 6e-3); }
|
||||
OCL_TEST_P(CvtColor8u32f, LRGB2Luv) { performTest(3, 3, CVTCODE(LRGB2Luv), depth == CV_8U ? 1 : 6e-3); }
|
||||
OCL_TEST_P(CvtColor8u32f, BGRA2Luv) { performTest(4, 3, CVTCODE(BGR2Luv), depth == CV_8U ? 1 : 2e-2); }
|
||||
OCL_TEST_P(CvtColor8u32f, RGBA2Luv) { performTest(4, 3, CVTCODE(RGB2Luv), depth == CV_8U ? 1 : 2e-2); }
|
||||
OCL_TEST_P(CvtColor8u32f, LBGRA2Luv) { performTest(4, 3, CVTCODE(LBGR2Luv), depth == CV_8U ? 1 : 6e-3); }
|
||||
OCL_TEST_P(CvtColor8u32f, LRGBA2Luv) { performTest(4, 3, CVTCODE(LRGB2Luv), depth == CV_8U ? 1 : 6e-3); }
|
||||
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2BGR) { performTest(3, 3, CVTCODE(Luv2BGR), depth == CV_8U ? 1 : 7e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2RGB) { performTest(3, 3, CVTCODE(Luv2RGB), depth == CV_8U ? 1 : 7e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2LBGR) { performTest(3, 3, CVTCODE(Luv2LBGR), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2LRGB) { performTest(3, 3, CVTCODE(Luv2LRGB), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2BGRA) { performTest(3, 4, CVTCODE(Luv2BGR), depth == CV_8U ? 1 : 7e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2RGBA) { performTest(3, 4, CVTCODE(Luv2RGB), depth == CV_8U ? 1 : 7e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2LBGRA) { performTest(3, 4, CVTCODE(Luv2LBGR), depth == CV_8U ? 1 : 1e-5); }
|
||||
OCL_TEST_P(CvtColor8u32f, Luv2LRGBA) { performTest(3, 4, CVTCODE(Luv2LRGB), depth == CV_8U ? 1 : 1e-5); }
|
||||
|
||||
// YUV420 -> RGBA
|
||||
|
||||
struct CvtColor_YUV2RGB_420 :
|
||||
public CvtColor
|
||||
{
|
||||
void generateTestData(int channelsIn, int channelsOut)
|
||||
{
|
||||
const int srcType = CV_MAKE_TYPE(depth, channelsIn);
|
||||
const int dstType = CV_MAKE_TYPE(depth, channelsOut);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
roiSize.width *= 2;
|
||||
roiSize.height *= 3;
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGBA_NV12) { performTest(1, 4, CVTCODE(YUV2RGBA_NV12), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGRA_NV12) { performTest(1, 4, CVTCODE(YUV2BGRA_NV12), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGB_NV12) { performTest(1, 3, CVTCODE(YUV2RGB_NV12), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGR_NV12) { performTest(1, 3, CVTCODE(YUV2BGR_NV12), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGBA_NV21) { performTest(1, 4, CVTCODE(YUV2RGBA_NV21), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGRA_NV21) { performTest(1, 4, CVTCODE(YUV2BGRA_NV21), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGB_NV21) { performTest(1, 3, CVTCODE(YUV2RGB_NV21), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGR_NV21) { performTest(1, 3, CVTCODE(YUV2BGR_NV21), EPS_FOR_FLOATING_POINT(1e-3)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGBA_YV12) { performTest(1, 4, CVTCODE(YUV2RGBA_YV12)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGRA_YV12) { performTest(1, 4, CVTCODE(YUV2BGRA_YV12)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGB_YV12) { performTest(1, 3, CVTCODE(YUV2RGB_YV12)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGR_YV12) { performTest(1, 3, CVTCODE(YUV2BGR_YV12)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGBA_IYUV) { performTest(1, 4, CVTCODE(YUV2RGBA_IYUV)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGRA_IYUV) { performTest(1, 4, CVTCODE(YUV2BGRA_IYUV)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2RGB_IYUV) { performTest(1, 3, CVTCODE(YUV2RGB_IYUV)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2BGR_IYUV) { performTest(1, 3, CVTCODE(YUV2BGR_IYUV)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_420, YUV2GRAY_420) { performTest(1, 1, CVTCODE(YUV2GRAY_420)); }
|
||||
|
||||
// RGBA -> YUV420
|
||||
|
||||
struct CvtColor_RGB2YUV_420 :
|
||||
public CvtColor
|
||||
{
|
||||
void generateTestData(int channelsIn, int channelsOut)
|
||||
{
|
||||
const int srcType = CV_MAKE_TYPE(depth, channelsIn);
|
||||
const int dstType = CV_MAKE_TYPE(depth, channelsOut);
|
||||
|
||||
Size srcRoiSize = randomSize(1, MAX_VALUE);
|
||||
srcRoiSize.width *= 2;
|
||||
srcRoiSize.height *= 2;
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, srcRoiSize, srcBorder, srcType, 2, 100);
|
||||
|
||||
Size dstRoiSize(srcRoiSize.width, srcRoiSize.height / 2 * 3);
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dstRoiSize, dstBorder, dstType, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, RGBA2YUV_YV12) { performTest(4, 1, CVTCODE(RGBA2YUV_YV12), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, BGRA2YUV_YV12) { performTest(4, 1, CVTCODE(BGRA2YUV_YV12), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, RGB2YUV_YV12) { performTest(3, 1, CVTCODE(RGB2YUV_YV12), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, BGR2YUV_YV12) { performTest(3, 1, CVTCODE(BGR2YUV_YV12), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, RGBA2YUV_IYUV) { performTest(4, 1, CVTCODE(RGBA2YUV_IYUV), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, BGRA2YUV_IYUV) { performTest(4, 1, CVTCODE(BGRA2YUV_IYUV), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, RGB2YUV_IYUV) { performTest(3, 1, CVTCODE(RGB2YUV_IYUV), 1); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_420, BGR2YUV_IYUV) { performTest(3, 1, CVTCODE(BGR2YUV_IYUV), 1); }
|
||||
|
||||
// YUV422 -> RGBA
|
||||
|
||||
struct CvtColor_YUV2RGB_422 :
|
||||
public CvtColor
|
||||
{
|
||||
void generateTestData(int channelsIn, int channelsOut)
|
||||
{
|
||||
const int srcType = CV_MAKE_TYPE(depth, channelsIn);
|
||||
const int dstType = CV_MAKE_TYPE(depth, channelsOut);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
roiSize.width *= 2;
|
||||
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGB_UYVY) { performTest(2, 3, CVTCODE(YUV2RGB_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGR_UYVY) { performTest(2, 3, CVTCODE(YUV2BGR_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGBA_UYVY) { performTest(2, 4, CVTCODE(YUV2RGBA_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGRA_UYVY) { performTest(2, 4, CVTCODE(YUV2BGRA_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGB_YUY2) { performTest(2, 3, CVTCODE(YUV2RGB_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGR_YUY2) { performTest(2, 3, CVTCODE(YUV2BGR_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGBA_YUY2) { performTest(2, 4, CVTCODE(YUV2RGBA_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGRA_YUY2) { performTest(2, 4, CVTCODE(YUV2BGRA_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGB_YVYU) { performTest(2, 3, CVTCODE(YUV2RGB_YVYU)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGR_YVYU) { performTest(2, 3, CVTCODE(YUV2BGR_YVYU)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGBA_YVYU) { performTest(2, 4, CVTCODE(YUV2RGBA_YVYU)); }
|
||||
OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGRA_YVYU) { performTest(2, 4, CVTCODE(YUV2BGRA_YVYU)); }
|
||||
|
||||
// RGBA -> YUV422
|
||||
|
||||
struct CvtColor_RGB2YUV_422 :
|
||||
public CvtColor
|
||||
{
|
||||
void generateTestData(int channelsIn, int channelsOut)
|
||||
{
|
||||
const int srcType = CV_MAKE_TYPE(depth, channelsIn);
|
||||
const int dstType = CV_MAKE_TYPE(depth, channelsOut);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
roiSize.width *= 2;
|
||||
roiSize.height *= 2;
|
||||
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 6, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, RGB2YUV_UYVY) { performTest(3, 2, CVTCODE(RGB2YUV_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, BGR2YUV_UYVY) { performTest(3, 2, CVTCODE(BGR2YUV_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, RGBA2YUV_UYVY) { performTest(4, 2, CVTCODE(RGBA2YUV_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, BGRA2YUV_UYVY) { performTest(4, 2, CVTCODE(BGRA2YUV_UYVY)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, RGB2YUV_YUY2) { performTest(3, 2, CVTCODE(RGB2YUV_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, BGR2YUV_YUY2) { performTest(3, 2, CVTCODE(BGR2YUV_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, RGBA2YUV_YUY2) { performTest(4, 2, CVTCODE(RGBA2YUV_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, BGRA2YUV_YUY2) { performTest(4, 2, CVTCODE(BGRA2YUV_YUY2)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, RGB2YUV_YVYU) { performTest(3, 2, CVTCODE(RGB2YUV_YVYU)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, BGR2YUV_YVYU) { performTest(3, 2, CVTCODE(BGR2YUV_YVYU)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, RGBA2YUV_YVYU) { performTest(4, 2, CVTCODE(RGBA2YUV_YVYU)); }
|
||||
OCL_TEST_P(CvtColor_RGB2YUV_422, BGRA2YUV_YVYU) { performTest(4, 2, CVTCODE(BGRA2YUV_YVYU)); }
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor8u,
|
||||
testing::Combine(testing::Values(MatDepth(CV_8U)), Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor8u32f,
|
||||
testing::Combine(testing::Values(MatDepth(CV_8U), MatDepth(CV_32F)), Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor,
|
||||
testing::Combine(
|
||||
testing::Values(MatDepth(CV_8U), MatDepth(CV_16U), MatDepth(CV_32F)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor_YUV2RGB_420,
|
||||
testing::Combine(
|
||||
testing::Values(MatDepth(CV_8U)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor_RGB2YUV_420,
|
||||
testing::Combine(
|
||||
testing::Values(MatDepth(CV_8U)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor_YUV2RGB_422,
|
||||
testing::Combine(
|
||||
testing::Values(MatDepth(CV_8U)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor_RGB2YUV_422,
|
||||
testing::Combine(
|
||||
testing::Values(MatDepth(CV_8U)),
|
||||
Bool()));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,142 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Filter2D
|
||||
PARAM_TEST_CASE(Filter2D, MatDepth, Channels, int, int, BorderType, bool, bool)
|
||||
{
|
||||
static const int kernelMinSize = 2;
|
||||
static const int kernelMaxSize = 10;
|
||||
|
||||
int type;
|
||||
Size size;
|
||||
Point anchor;
|
||||
int borderType;
|
||||
int widthMultiple;
|
||||
bool useRoi;
|
||||
Mat kernel;
|
||||
double delta;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
Size ksize(GET_PARAM(2), GET_PARAM(2));
|
||||
widthMultiple = GET_PARAM(3);
|
||||
borderType = GET_PARAM(4) | (GET_PARAM(5) ? BORDER_ISOLATED : 0);
|
||||
useRoi = GET_PARAM(6);
|
||||
Mat temp = randomMat(ksize, CV_MAKE_TYPE(((CV_64F == CV_MAT_DEPTH(type)) ? CV_64F : CV_32F), 1), -MAX_VALUE, MAX_VALUE);
|
||||
cv::normalize(temp, kernel, 1.0, 0.0, NORM_L1);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
size = randomSize(1, MAX_VALUE);
|
||||
// Make sure the width is a multiple of the requested value, and no more.
|
||||
size.width &= ~((widthMultiple * 2) - 1);
|
||||
size.width += widthMultiple;
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, size, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, size, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
anchor.x = randomInt(-1, kernel.size[0]);
|
||||
anchor.y = randomInt(-1, kernel.size[1]);
|
||||
|
||||
delta = randomDouble(-100, 100);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Filter2D, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::filter2D(src_roi, dst_roi, -1, kernel, anchor, delta, borderType));
|
||||
OCL_ON(cv::filter2D(usrc_roi, udst_roi, -1, kernel, anchor, delta, borderType));
|
||||
|
||||
Near(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, Filter2D,
|
||||
Combine(
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
OCL_ALL_CHANNELS,
|
||||
Values(3, 5, 7), // Kernel size
|
||||
Values(1, 4, 8), // Width multiple
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool(), // BORDER_ISOLATED
|
||||
Bool() // ROI
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,766 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Zero Lin, Zero.Lin@amd.com
|
||||
// Zhang Ying, zhangying913@gmail.com
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
//
|
||||
// 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 "cvconfig.h"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(FilterTestBase, MatType,
|
||||
int, // kernel size
|
||||
Size, // dx, dy
|
||||
BorderType, // border type
|
||||
double, // optional parameter
|
||||
bool, // roi or not
|
||||
int) // width multiplier
|
||||
{
|
||||
int type, borderType, ksize;
|
||||
Size size;
|
||||
double param;
|
||||
bool useRoi;
|
||||
int widthMultiple;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
ksize = GET_PARAM(1);
|
||||
size = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
param = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
widthMultiple = GET_PARAM(6);
|
||||
}
|
||||
|
||||
void random_roi(int minSize = 1)
|
||||
{
|
||||
if (minSize == 0)
|
||||
minSize = ksize;
|
||||
|
||||
Size roiSize = randomSize(minSize, MAX_VALUE);
|
||||
roiSize.width &= ~((widthMultiple * 2) - 1);
|
||||
roiSize.width += widthMultiple;
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
bool isFP = depth >= CV_32F;
|
||||
|
||||
if (isFP)
|
||||
Near(1e-6, true);
|
||||
else
|
||||
Near(1, false);
|
||||
}
|
||||
|
||||
void Near(double threshold, bool relative)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Bilateral
|
||||
|
||||
typedef FilterTestBase Bilateral;
|
||||
|
||||
OCL_TEST_P(Bilateral, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double sigmacolor = rng.uniform(20, 100);
|
||||
double sigmaspace = rng.uniform(10, 40);
|
||||
|
||||
OCL_OFF(cv::bilateralFilter(src_roi, dst_roi, ksize, sigmacolor, sigmaspace, borderType));
|
||||
OCL_ON(cv::bilateralFilter(usrc_roi, udst_roi, ksize, sigmacolor, sigmaspace, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Laplacian
|
||||
|
||||
typedef FilterTestBase LaplacianTest;
|
||||
|
||||
OCL_TEST_P(LaplacianTest, Accuracy)
|
||||
{
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Laplacian(src_roi, dst_roi, -1, ksize, scale, 10, borderType));
|
||||
OCL_ON(cv::Laplacian(usrc_roi, udst_roi, -1, ksize, scale, 10, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(Deriv3x3_cols16_rows2_Base, MatType,
|
||||
int, // kernel size
|
||||
Size, // dx, dy
|
||||
BorderType, // border type
|
||||
double, // optional parameter
|
||||
bool, // roi or not
|
||||
int) // width multiplier
|
||||
{
|
||||
int type, borderType, ksize;
|
||||
Size size;
|
||||
double param;
|
||||
bool useRoi;
|
||||
int widthMultiple;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
ksize = GET_PARAM(1);
|
||||
size = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
param = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
widthMultiple = GET_PARAM(6);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
size = Size(3, 3);
|
||||
|
||||
Size roiSize = randomSize(size.width, MAX_VALUE, size.height, MAX_VALUE);
|
||||
roiSize.width = std::max(size.width + 13, roiSize.width & (~0xf));
|
||||
roiSize.height = std::max(size.height + 1, roiSize.height & (~0x1));
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
Near(1, false);
|
||||
}
|
||||
|
||||
void Near(double threshold, bool relative)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Deriv3x3_cols16_rows2_Base Laplacian3_cols16_rows2;
|
||||
|
||||
OCL_TEST_P(Laplacian3_cols16_rows2, Accuracy)
|
||||
{
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Laplacian(src_roi, dst_roi, -1, ksize, scale, 10, borderType));
|
||||
OCL_ON(cv::Laplacian(usrc_roi, udst_roi, -1, ksize, scale, 10, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sobel
|
||||
|
||||
typedef FilterTestBase SobelTest;
|
||||
|
||||
OCL_TEST_P(SobelTest, Mat)
|
||||
{
|
||||
int dx = size.width, dy = size.height;
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Sobel(src_roi, dst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType));
|
||||
OCL_ON(cv::Sobel(usrc_roi, udst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
typedef Deriv3x3_cols16_rows2_Base Sobel3x3_cols16_rows2;
|
||||
|
||||
OCL_TEST_P(Sobel3x3_cols16_rows2, Mat)
|
||||
{
|
||||
int dx = size.width, dy = size.height;
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Sobel(src_roi, dst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType));
|
||||
OCL_ON(cv::Sobel(usrc_roi, udst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Scharr
|
||||
|
||||
typedef FilterTestBase ScharrTest;
|
||||
|
||||
OCL_TEST_P(ScharrTest, Mat)
|
||||
{
|
||||
int dx = size.width, dy = size.height;
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Scharr(src_roi, dst_roi, -1, dx, dy, scale, /* delta */ 0, borderType));
|
||||
OCL_ON(cv::Scharr(usrc_roi, udst_roi, -1, dx, dy, scale, /* delta */ 0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
typedef Deriv3x3_cols16_rows2_Base Scharr3x3_cols16_rows2;
|
||||
|
||||
OCL_TEST_P(Scharr3x3_cols16_rows2, Mat)
|
||||
{
|
||||
int dx = size.width, dy = size.height;
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Scharr(src_roi, dst_roi, -1, dx, dy, scale, /* delta */ 0, borderType));
|
||||
OCL_ON(cv::Scharr(usrc_roi, udst_roi, -1, dx, dy, scale, /* delta */ 0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GaussianBlur
|
||||
|
||||
typedef FilterTestBase GaussianBlurTest;
|
||||
|
||||
OCL_TEST_P(GaussianBlurTest, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times + 1; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double sigma1 = rng.uniform(0.1, 1.0);
|
||||
double sigma2 = j % 2 == 0 ? sigma1 : rng.uniform(0.1, 1.0);
|
||||
|
||||
OCL_OFF(cv::GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType));
|
||||
OCL_ON(cv::GaussianBlur(usrc_roi, udst_roi, Size(ksize, ksize), sigma1, sigma2, borderType));
|
||||
|
||||
Near(CV_MAT_DEPTH(type) >= CV_32F ? 1e-3 : 4, CV_MAT_DEPTH(type) >= CV_32F);
|
||||
}
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(GaussianBlur_multicols_Base, MatType,
|
||||
int, // kernel size
|
||||
Size, // dx, dy
|
||||
BorderType, // border type
|
||||
double, // optional parameter
|
||||
bool, // roi or not
|
||||
int) // width multiplier
|
||||
{
|
||||
int type, borderType, ksize;
|
||||
Size size;
|
||||
double param;
|
||||
bool useRoi;
|
||||
int widthMultiple;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
ksize = GET_PARAM(1);
|
||||
size = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
param = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
widthMultiple = GET_PARAM(6);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
size = Size(ksize, ksize);
|
||||
|
||||
Size roiSize = randomSize(size.width, MAX_VALUE, size.height, MAX_VALUE);
|
||||
if (ksize == 3)
|
||||
{
|
||||
roiSize.width = std::max((size.width + 15) & 0x10, roiSize.width & (~0xf));
|
||||
roiSize.height = std::max(size.height + 1, roiSize.height & (~0x1));
|
||||
}
|
||||
else if (ksize == 5)
|
||||
{
|
||||
roiSize.width = std::max((size.width + 3) & 0x4, roiSize.width & (~0x3));
|
||||
}
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
Near(1, false);
|
||||
}
|
||||
|
||||
void Near(double threshold, bool relative)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
typedef GaussianBlur_multicols_Base GaussianBlur_multicols;
|
||||
|
||||
OCL_TEST_P(GaussianBlur_multicols, Mat)
|
||||
{
|
||||
Size kernelSize(ksize, ksize);
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double sigma1 = rng.uniform(0.1, 1.0);
|
||||
double sigma2 = j % 2 == 0 ? sigma1 : rng.uniform(0.1, 1.0);
|
||||
|
||||
OCL_OFF(cv::GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType));
|
||||
OCL_ON(cv::GaussianBlur(usrc_roi, udst_roi, Size(ksize, ksize), sigma1, sigma2, borderType));
|
||||
|
||||
Near(CV_MAT_DEPTH(type) >= CV_32F ? 1e-3 : 4, CV_MAT_DEPTH(type) >= CV_32F);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Erode
|
||||
|
||||
typedef FilterTestBase Erode;
|
||||
|
||||
OCL_TEST_P(Erode, Mat)
|
||||
{
|
||||
Size kernelSize(ksize, ksize);
|
||||
int iterations = (int)param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
Mat kernel = ksize==0 ? Mat() : randomMat(kernelSize, CV_8UC1, 0, 2);
|
||||
|
||||
OCL_OFF(cv::erode(src_roi, dst_roi, kernel, Point(-1, -1), iterations) );
|
||||
OCL_ON(cv::erode(usrc_roi, udst_roi, kernel, Point(-1, -1), iterations) );
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dilate
|
||||
|
||||
typedef FilterTestBase Dilate;
|
||||
|
||||
OCL_TEST_P(Dilate, Mat)
|
||||
{
|
||||
Size kernelSize(ksize, ksize);
|
||||
int iterations = (int)param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
Mat kernel = ksize==0 ? Mat() : randomMat(kernelSize, CV_8UC1, 0, 2);
|
||||
|
||||
OCL_OFF(cv::dilate(src_roi, dst_roi, kernel, Point(-1, -1), iterations) );
|
||||
OCL_ON(cv::dilate(usrc_roi, udst_roi, kernel, Point(-1, -1), iterations) );
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(MorphFilter3x3_cols16_rows2_Base, MatType,
|
||||
int, // kernel size
|
||||
Size, // dx, dy
|
||||
BorderType, // border type
|
||||
double, // optional parameter
|
||||
bool, // roi or not
|
||||
int) // width multiplier
|
||||
{
|
||||
int type, borderType, ksize;
|
||||
Size size;
|
||||
double param;
|
||||
bool useRoi;
|
||||
int widthMultiple;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
ksize = GET_PARAM(1);
|
||||
size = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
param = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
widthMultiple = GET_PARAM(6);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
size = Size(3, 3);
|
||||
|
||||
Size roiSize = randomSize(size.width, MAX_VALUE, size.height, MAX_VALUE);
|
||||
roiSize.width = std::max(size.width + 13, roiSize.width & (~0xf));
|
||||
roiSize.height = std::max(size.height + 1, roiSize.height & (~0x1));
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
Near(1, false);
|
||||
}
|
||||
|
||||
void Near(double threshold, bool relative)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
typedef MorphFilter3x3_cols16_rows2_Base MorphFilter3x3_cols16_rows2;
|
||||
|
||||
OCL_TEST_P(MorphFilter3x3_cols16_rows2, Mat)
|
||||
{
|
||||
Size kernelSize(ksize, ksize);
|
||||
int iterations = (int)param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
Mat kernel = ksize==0 ? Mat() : randomMat(kernelSize, CV_8UC1, 0, 3);
|
||||
|
||||
OCL_OFF(cv::dilate(src_roi, dst_roi, kernel, Point(-1, -1), iterations) );
|
||||
OCL_ON(cv::dilate(usrc_roi, udst_roi, kernel, Point(-1, -1), iterations) );
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MorphologyEx
|
||||
IMPLEMENT_PARAM_CLASS(MorphOp, int)
|
||||
PARAM_TEST_CASE(MorphologyEx, MatType,
|
||||
int, // kernel size
|
||||
MorphOp, // MORPH_OP
|
||||
int, // iterations
|
||||
bool)
|
||||
{
|
||||
int type, ksize, op, iterations;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
ksize = GET_PARAM(1);
|
||||
op = GET_PARAM(2);
|
||||
iterations = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi(int minSize = 1)
|
||||
{
|
||||
if (minSize == 0)
|
||||
minSize = ksize;
|
||||
|
||||
Size roiSize = randomSize(minSize, MAX_VALUE);
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
bool isFP = depth >= CV_32F;
|
||||
|
||||
if (isFP)
|
||||
Near(1e-6, true);
|
||||
else
|
||||
Near(1, false);
|
||||
}
|
||||
|
||||
void Near(double threshold, bool relative)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(MorphologyEx, Mat)
|
||||
{
|
||||
Size kernelSize(ksize, ksize);
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
Mat kernel = randomMat(kernelSize, CV_8UC1, 0, 3);
|
||||
|
||||
OCL_OFF(cv::morphologyEx(src_roi, dst_roi, op, kernel, Point(-1, -1), iterations) );
|
||||
OCL_ON(cv::morphologyEx(usrc_roi, udst_roi, op, kernel, Point(-1, -1), iterations) );
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define FILTER_BORDER_SET_NO_ISOLATED \
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, (BorderType)BORDER_WRAP, (BorderType)BORDER_REFLECT_101/*, \
|
||||
(int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version
|
||||
|
||||
#define FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED \
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (BorderType)BORDER_REFLECT_101/*, \
|
||||
(int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version
|
||||
|
||||
#define FILTER_TYPES Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16UC1, CV_16UC3, CV_16UC4, CV_32FC1, CV_32FC3, CV_32FC4)
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Bilateral, Combine(
|
||||
Values(CV_8UC1, CV_8UC3),
|
||||
Values(5, 9), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool(),
|
||||
Values(1, 4)));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, LaplacianTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(1, 3, 5), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(1.0, 0.2, 3.0), // kernel scale
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Laplacian3_cols16_rows2, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values(3), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(1.0, 0.2, 3.0), // kernel scale
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, SobelTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(3, 5), // kernel size
|
||||
Values(Size(1, 0), Size(1, 1), Size(2, 0), Size(2, 1)), // dx, dy
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Sobel3x3_cols16_rows2, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values(3), // kernel size
|
||||
Values(Size(1, 0), Size(1, 1), Size(2, 0), Size(2, 1)), // dx, dy
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, ScharrTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(0), // not used
|
||||
Values(Size(0, 1), Size(1, 0)), // dx, dy
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(1.0, 0.2), // kernel scale
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Scharr3x3_cols16_rows2, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(0), // not used
|
||||
Values(Size(0, 1), Size(1, 0)), // dx, dy
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(1.0, 0.2), // kernel scale
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, GaussianBlurTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(3, 5), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, GaussianBlur_multicols, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values(3, 5), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Erode, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC4),
|
||||
Values(0, 5, 7, 9), // kernel size, 0 means kernel = Mat()
|
||||
Values(Size(0, 0)), //not used
|
||||
Values((BorderType)BORDER_CONSTANT),
|
||||
Values(1.0, 2.0, 3.0, 4.0),
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Dilate, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC4),
|
||||
Values(0, 3, 5, 7, 9), // kernel size, 0 means kernel = Mat()
|
||||
Values(Size(0, 0)), // not used
|
||||
Values((BorderType)BORDER_CONSTANT),
|
||||
Values(1.0, 2.0, 3.0, 4.0),
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, MorphFilter3x3_cols16_rows2, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values(0, 3), // kernel size, 0 means kernel = Mat()
|
||||
Values(Size(0, 0)), // not used
|
||||
Values((BorderType)BORDER_CONSTANT),
|
||||
Values(1.0, 2.0, 3.0),
|
||||
Bool(),
|
||||
Values(1))); // not used
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, MorphologyEx, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4),
|
||||
Values(3, 5, 7), // kernel size
|
||||
Values((MorphOp)MORPH_OPEN, (MorphOp)MORPH_CLOSE, (MorphOp)MORPH_GRADIENT, (MorphOp)MORPH_TOPHAT, (MorphOp)MORPH_BLACKHAT), // used as generator of operations
|
||||
Values(1, 2, 3),
|
||||
Bool()));
|
||||
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,304 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2014, Itseez, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Shengen Yan, yanshengen@gmail.com
|
||||
// Jiang Liyuan, lyuan001.good@163.com
|
||||
// Rock Li, Rock.Li@amd.com
|
||||
// Wu Zailong, bullet@yeah.net
|
||||
// Xu Pang, pangxu010@163.com
|
||||
// Sen Liu, swjtuls1987@126.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(CalcBackProject, MatDepth, int, bool)
|
||||
{
|
||||
int depth, N;
|
||||
bool useRoi;
|
||||
|
||||
std::vector<float> ranges;
|
||||
std::vector<int> channels;
|
||||
double scale;
|
||||
|
||||
std::vector<Mat> images;
|
||||
std::vector<Mat> images_roi;
|
||||
std::vector<UMat> uimages;
|
||||
std::vector<UMat> uimages_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(hist);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
N = GET_PARAM(1);
|
||||
useRoi = GET_PARAM(2);
|
||||
|
||||
ASSERT_GE(2, N);
|
||||
|
||||
images.resize(N);
|
||||
images_roi.resize(N);
|
||||
uimages.resize(N);
|
||||
uimages_roi.resize(N);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
|
||||
int totalChannels = 0;
|
||||
|
||||
ranges.clear();
|
||||
channels.clear();
|
||||
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
int cn = randomInt(1, 5);
|
||||
randomSubMat(images[i], images_roi[i], roiSize, srcBorder, CV_MAKE_TYPE(depth, cn), 0, 125);
|
||||
|
||||
ranges.push_back(10);
|
||||
ranges.push_back(100);
|
||||
|
||||
channels.push_back(randomInt(0, cn) + totalChannels);
|
||||
totalChannels += cn;
|
||||
}
|
||||
|
||||
Mat tmpHist;
|
||||
{
|
||||
std::vector<int> hist_size(N);
|
||||
for (int i = 0 ; i < N; ++i)
|
||||
hist_size[i] = randomInt(10, 50);
|
||||
|
||||
cv::calcHist(images_roi, channels, noArray(), tmpHist, hist_size, ranges);
|
||||
ASSERT_EQ(CV_32FC1, tmpHist.type());
|
||||
}
|
||||
|
||||
Border histBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(hist, hist_roi, tmpHist.size(), histBorder, tmpHist.type(), 0, MAX_VALUE);
|
||||
tmpHist.copyTo(hist_roi);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_MAKE_TYPE(depth, 1), 5, 16);
|
||||
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
images[i].copyTo(uimages[i]);
|
||||
|
||||
Size _wholeSize;
|
||||
Point ofs;
|
||||
images_roi[i].locateROI(_wholeSize, ofs);
|
||||
|
||||
uimages_roi[i] = uimages[i](Rect(ofs.x, ofs.y, images_roi[i].cols, images_roi[i].rows));
|
||||
}
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(hist);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
|
||||
scale = randomDouble(0.1, 1);
|
||||
}
|
||||
|
||||
void test_by_pict()
|
||||
{
|
||||
Mat frame1 = readImage("optflow/RubberWhale1.png", IMREAD_GRAYSCALE);
|
||||
|
||||
UMat usrc;
|
||||
frame1.copyTo(usrc);
|
||||
int histSize = randomInt(3, 29);
|
||||
float hue_range[] = { 0, 180 };
|
||||
const float* ranges1 = { hue_range };
|
||||
Mat hist1;
|
||||
|
||||
//compute histogram
|
||||
calcHist(&frame1, 1, 0, Mat(), hist1, 1, &histSize, &ranges1, true, false);
|
||||
normalize(hist1, hist1, 0, 255, NORM_MINMAX, -1, Mat());
|
||||
|
||||
Mat dst1;
|
||||
UMat udst1, src, uhist1;
|
||||
hist1.copyTo(uhist1);
|
||||
std::vector<UMat> uims;
|
||||
uims.push_back(usrc);
|
||||
std::vector<float> urngs;
|
||||
urngs.push_back(0);
|
||||
urngs.push_back(180);
|
||||
std::vector<int> chs;
|
||||
chs.push_back(0);
|
||||
|
||||
OCL_OFF(calcBackProject(&frame1, 1, 0, hist1, dst1, &ranges1, 1, true));
|
||||
OCL_ON(calcBackProject(uims, chs, uhist1, udst1, urngs, 1.0));
|
||||
|
||||
if (cv::ocl::useOpenCL() && cv::ocl::Device::getDefault().isAMD())
|
||||
{
|
||||
Size dstSize = dst1.size();
|
||||
int nDiffs = (int)(0.03f*dstSize.height*dstSize.width);
|
||||
|
||||
//check if the dst mats are the same except 3% difference
|
||||
EXPECT_MAT_N_DIFF(dst1, udst1, nDiffs);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst1, udst1, 0.0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////// CalcBackProject //////////////////////////////////////////////
|
||||
|
||||
OCL_TEST_P(CalcBackProject, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::calcBackProject(images_roi, channels, hist_roi, dst_roi, ranges, scale));
|
||||
OCL_ON(cv::calcBackProject(uimages_roi, channels, uhist_roi, udst_roi, ranges, scale));
|
||||
|
||||
Size dstSize = dst_roi.size();
|
||||
int nDiffs = std::max((int)(0.07f*dstSize.area()), 1);
|
||||
|
||||
//check if the dst mats are the same except 7% difference
|
||||
EXPECT_MAT_N_DIFF(dst_roi, udst_roi, nDiffs);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(CalcBackProject, Mat_RealImage)
|
||||
{
|
||||
//check on given image
|
||||
test_by_pict();
|
||||
}
|
||||
|
||||
//////////////////////////////// CalcHist //////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(CalcHist, bool)
|
||||
{
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(hist);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
useRoi = GET_PARAM(0);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, CV_8UC1, 0, 256);
|
||||
|
||||
Border histBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(hist, hist_roi, Size(256, 1), histBorder, CV_32SC1, 0, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(hist);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CalcHist, Mat)
|
||||
{
|
||||
const std::vector<int> channels(1, 0);
|
||||
std::vector<float> ranges(2);
|
||||
std::vector<int> histSize(1, 256);
|
||||
ranges[0] = 0;
|
||||
ranges[1] = 256;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::calcHist(std::vector<Mat>(1, src_roi), channels, noArray(), hist_roi, histSize, ranges, false));
|
||||
OCL_ON(cv::calcHist(std::vector<UMat>(1, usrc_roi), channels, noArray(), uhist_roi, histSize, ranges, false));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(hist, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CalcHistMask, CheckMask)
|
||||
{
|
||||
Mat gray = imread(cvtest::findDataFile("shared/baboon.png"), IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(gray.empty());
|
||||
|
||||
cv::Rect roi(gray.cols/4, gray.rows/4, gray.cols/2, gray.rows/2);
|
||||
Mat mask = Mat::zeros(gray.size(), CV_8UC1);
|
||||
mask(roi).setTo(255);
|
||||
|
||||
Mat mask_bool = Mat::zeros(gray.size(), CV_BoolC1);
|
||||
mask_bool(roi).setTo(1);
|
||||
Mat gray_roi = gray(roi);
|
||||
|
||||
const std::vector<int> channels(1, 0);
|
||||
std::vector<int> histSize(1, 256);
|
||||
std::vector<float> ranges(2);
|
||||
ranges[0] = 0;
|
||||
ranges[1] = 256;
|
||||
|
||||
Mat hist_mask, hist_bool, hist_roi;
|
||||
cv::calcHist(std::vector<Mat>(1, gray_roi), channels, Mat(), hist_roi, histSize, ranges, false);
|
||||
cv::calcHist(std::vector<Mat>(1, gray), channels, mask, hist_mask, histSize, ranges, false);
|
||||
cv::calcHist(std::vector<Mat>(1, gray), channels, mask_bool, hist_bool, histSize, ranges, false);
|
||||
|
||||
EXPECT_MAT_NEAR(hist_roi, hist_mask, 0.0);
|
||||
EXPECT_MAT_NEAR(hist_mask, hist_bool, 0.0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CalcBackProject, Combine(Values((MatDepth)CV_8U), Values(1, 2), Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CalcHist, Values(true, false));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,184 @@
|
||||
// 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, Itseez, 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 {
|
||||
|
||||
struct Vec2fComparator
|
||||
{
|
||||
bool operator()(const Vec2f& a, const Vec2f b) const
|
||||
{
|
||||
if(a[0] != b[0]) return a[0] < b[0];
|
||||
else return a[1] < b[1];
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////// HoughLines ////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(HoughLines, double, double, int)
|
||||
{
|
||||
double rhoStep, thetaStep;
|
||||
int threshold;
|
||||
|
||||
Size src_size;
|
||||
Mat src, dst;
|
||||
UMat usrc, udst;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
rhoStep = GET_PARAM(0);
|
||||
thetaStep = GET_PARAM(1);
|
||||
threshold = GET_PARAM(2);
|
||||
}
|
||||
|
||||
void generateTestData()
|
||||
{
|
||||
src_size = randomSize(500, 1920);
|
||||
src.create(src_size, CV_8UC1);
|
||||
src.setTo(Scalar::all(0));
|
||||
line(src, Point(0, 100), Point(100, 100), Scalar::all(255), 1);
|
||||
line(src, Point(0, 200), Point(100, 200), Scalar::all(255), 1);
|
||||
line(src, Point(0, 400), Point(100, 400), Scalar::all(255), 1);
|
||||
line(src, Point(100, 0), Point(100, 200), Scalar::all(255), 1);
|
||||
line(src, Point(200, 0), Point(200, 200), Scalar::all(255), 1);
|
||||
line(src, Point(400, 0), Point(400, 200), Scalar::all(255), 1);
|
||||
|
||||
src.copyTo(usrc);
|
||||
}
|
||||
|
||||
void readRealTestData()
|
||||
{
|
||||
Mat img = readImage("shared/pic5.png", IMREAD_GRAYSCALE);
|
||||
Canny(img, src, 100, 150, 3);
|
||||
|
||||
src.copyTo(usrc);
|
||||
}
|
||||
|
||||
void Near(double eps = 0.)
|
||||
{
|
||||
EXPECT_EQ(dst.size(), udst.size());
|
||||
|
||||
if (dst.total() > 0)
|
||||
{
|
||||
Mat lines_cpu, lines_gpu;
|
||||
dst.copyTo(lines_cpu);
|
||||
udst.copyTo(lines_gpu);
|
||||
|
||||
std::sort(lines_cpu.begin<Vec2f>(), lines_cpu.end<Vec2f>(), Vec2fComparator());
|
||||
std::sort(lines_gpu.begin<Vec2f>(), lines_gpu.end<Vec2f>(), Vec2fComparator());
|
||||
|
||||
EXPECT_LE(TestUtils::checkNorm2(lines_cpu, lines_gpu), eps);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(HoughLines, RealImage)
|
||||
{
|
||||
readRealTestData();
|
||||
|
||||
OCL_OFF(cv::HoughLines(src, dst, rhoStep, thetaStep, threshold));
|
||||
OCL_ON(cv::HoughLines(usrc, udst, rhoStep, thetaStep, threshold));
|
||||
|
||||
Near(1e-5);
|
||||
}
|
||||
|
||||
OCL_TEST_P(HoughLines, GeneratedImage)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::HoughLines(src, dst, rhoStep, thetaStep, threshold));
|
||||
OCL_ON(cv::HoughLines(usrc, udst, rhoStep, thetaStep, threshold));
|
||||
|
||||
Near(1e-5);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////// HoughLinesP ///////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(HoughLinesP, int, double, double)
|
||||
{
|
||||
double rhoStep, thetaStep, minLineLength, maxGap;
|
||||
int threshold;
|
||||
|
||||
Size src_size;
|
||||
Mat src, dst;
|
||||
UMat usrc, udst;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
rhoStep = 1.0;
|
||||
thetaStep = CV_PI / 180;
|
||||
threshold = GET_PARAM(0);
|
||||
minLineLength = GET_PARAM(1);
|
||||
maxGap = GET_PARAM(2);
|
||||
}
|
||||
|
||||
void readRealTestData()
|
||||
{
|
||||
Mat img = readImage("shared/pic5.png", IMREAD_GRAYSCALE);
|
||||
Canny(img, src, 50, 200, 3);
|
||||
|
||||
src.copyTo(usrc);
|
||||
}
|
||||
|
||||
void Near(double eps = 0.)
|
||||
{
|
||||
Mat lines_gpu = udst.getMat(ACCESS_READ);
|
||||
|
||||
if (dst.total() > 0 && lines_gpu.total() > 0)
|
||||
{
|
||||
Mat result_cpu(src.size(), CV_8UC1, Scalar::all(0));
|
||||
Mat result_gpu(src.size(), CV_8UC1, Scalar::all(0));
|
||||
|
||||
MatConstIterator_<Vec4i> it = dst.begin<Vec4i>(), end = dst.end<Vec4i>();
|
||||
for ( ; it != end; it++)
|
||||
{
|
||||
Vec4i p = *it;
|
||||
line(result_cpu, Point(p[0], p[1]), Point(p[2], p[3]), Scalar(255));
|
||||
}
|
||||
|
||||
it = lines_gpu.begin<Vec4i>(), end = lines_gpu.end<Vec4i>();
|
||||
for ( ; it != end; it++)
|
||||
{
|
||||
Vec4i p = *it;
|
||||
line(result_gpu, Point(p[0], p[1]), Point(p[2], p[3]), Scalar(255));
|
||||
}
|
||||
|
||||
EXPECT_MAT_SIMILAR(result_cpu, result_gpu, eps);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
OCL_TEST_P(HoughLinesP, RealImage)
|
||||
{
|
||||
readRealTestData();
|
||||
|
||||
OCL_OFF(cv::HoughLinesP(src, dst, rhoStep, thetaStep, threshold, minLineLength, maxGap));
|
||||
OCL_ON(cv::HoughLinesP(usrc, udst, rhoStep, thetaStep, threshold, minLineLength, maxGap));
|
||||
|
||||
Near(0.25);
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, HoughLines, Combine(Values(1, 0.5), // rhoStep
|
||||
Values(CV_PI / 180.0, CV_PI / 360.0), // thetaStep
|
||||
Values(85, 150))); // threshold
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, HoughLinesP, Combine(Values(100, 150), // threshold
|
||||
Values(50, 100), // minLineLength
|
||||
Values(5, 10))); // maxLineGap
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,596 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Shengen Yan, yanshengen@gmail.com
|
||||
// Jiang Liyuan, lyuan001.good@163.com
|
||||
// Rock Li, Rock.Li@amd.com
|
||||
// Wu Zailong, bullet@yeah.net
|
||||
// Xu Pang, pangxu010@163.com
|
||||
// Sen Liu, swjtuls1987@126.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(ImgprocTestBase, MatType,
|
||||
int, // blockSize
|
||||
int, // border type
|
||||
bool) // roi or not
|
||||
{
|
||||
int type, borderType, blockSize;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
blockSize = GET_PARAM(1);
|
||||
borderType = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0, bool relative = false)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////// copyMakeBorder ////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(CopyMakeBorder, MatDepth, // depth
|
||||
Channels, // channels
|
||||
bool, // isolated or not
|
||||
BorderType, // border type
|
||||
bool) // roi or not
|
||||
{
|
||||
int type, borderType;
|
||||
bool useRoi;
|
||||
|
||||
TestUtils::Border border;
|
||||
Scalar val;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
borderType = GET_PARAM(3);
|
||||
|
||||
if (GET_PARAM(2))
|
||||
borderType |= BORDER_ISOLATED;
|
||||
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
border = randomBorder(0, MAX_VALUE << 2);
|
||||
val = randomScalar(-MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
dstBorder.top += border.top;
|
||||
dstBorder.lef += border.lef;
|
||||
dstBorder.rig += border.rig;
|
||||
dstBorder.bot += border.bot;
|
||||
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, 0);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CopyMakeBorder, Mat)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::copyMakeBorder(src_roi, dst_roi, border.top, border.bot, border.lef, border.rig, borderType, val));
|
||||
OCL_ON(cv::copyMakeBorder(usrc_roi, udst_roi, border.top, border.bot, border.lef, border.rig, borderType, val));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// equalizeHist //////////////////////////////////////////////
|
||||
|
||||
typedef ImgprocTestBase EqualizeHist;
|
||||
|
||||
OCL_TEST_P(EqualizeHist, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::equalizeHist(src_roi, dst_roi));
|
||||
OCL_ON(cv::equalizeHist(usrc_roi, udst_roi));
|
||||
|
||||
Near(1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// Corners test //////////////////////////////////////////
|
||||
|
||||
struct CornerTestBase :
|
||||
public ImgprocTestBase
|
||||
{
|
||||
void random_roi()
|
||||
{
|
||||
Mat image = readImageType("../gpu/stereobm/aloe-L.png", type);
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
bool isFP = CV_MAT_DEPTH(type) >= CV_32F;
|
||||
float val = 255.0f;
|
||||
if (isFP)
|
||||
{
|
||||
image.convertTo(image, -1, 1.0 / 255);
|
||||
val /= 255.0f;
|
||||
}
|
||||
|
||||
Size roiSize = image.size();
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
|
||||
Size wholeSize = Size(roiSize.width + srcBorder.lef + srcBorder.rig, roiSize.height + srcBorder.top + srcBorder.bot);
|
||||
src = randomMat(wholeSize, type, -val, val, false);
|
||||
src_roi = src(Rect(srcBorder.lef, srcBorder.top, roiSize.width, roiSize.height));
|
||||
image.copyTo(src_roi);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_32FC1, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
typedef CornerTestBase CornerMinEigenVal;
|
||||
|
||||
OCL_TEST_P(CornerMinEigenVal, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
int apertureSize = 3;
|
||||
|
||||
OCL_OFF(cv::cornerMinEigenVal(src_roi, dst_roi, blockSize, apertureSize, borderType));
|
||||
OCL_ON(cv::cornerMinEigenVal(usrc_roi, udst_roi, blockSize, apertureSize, borderType));
|
||||
|
||||
// The corner kernel uses native_sqrt() which has implementation defined accuracy.
|
||||
// If we're using a CL implementation that isn't intel, test with relaxed accuracy.
|
||||
if (!ocl::useOpenCL() || ocl::Device::getDefault().isIntel())
|
||||
Near(1e-5, true);
|
||||
else
|
||||
Near(0.1, true);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// cornerHarris //////////////////////////////////////////
|
||||
|
||||
typedef CornerTestBase CornerHarris;
|
||||
|
||||
OCL_TEST_P(CornerHarris, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
int apertureSize = 3;
|
||||
double k = randomDouble(0.01, 0.9);
|
||||
|
||||
OCL_OFF(cv::cornerHarris(src_roi, dst_roi, blockSize, apertureSize, k, borderType));
|
||||
OCL_ON(cv::cornerHarris(usrc_roi, udst_roi, blockSize, apertureSize, k, borderType));
|
||||
|
||||
Near(1e-6, true);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// preCornerDetect //////////////////////////////////////////
|
||||
|
||||
typedef ImgprocTestBase PreCornerDetect;
|
||||
|
||||
OCL_TEST_P(PreCornerDetect, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
const int apertureSize = blockSize;
|
||||
|
||||
OCL_OFF(cv::preCornerDetect(src_roi, dst_roi, apertureSize, borderType));
|
||||
OCL_ON(cv::preCornerDetect(usrc_roi, udst_roi, apertureSize, borderType));
|
||||
|
||||
Near(1e-6, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////// integral /////////////////////////////////////////////////
|
||||
|
||||
struct Integral :
|
||||
public ImgprocTestBase
|
||||
{
|
||||
int sdepth, sqdepth;
|
||||
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst2);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
sdepth = GET_PARAM(1);
|
||||
sqdepth = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
ASSERT_EQ(CV_MAT_CN(type), 1);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE), isize = Size(roiSize.width + 1, roiSize.height + 1);
|
||||
Border srcBorder = randomBorder(0, useRoi ? 2 : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? 2 : 0);
|
||||
randomSubMat(dst, dst_roi, isize, dstBorder, sdepth, 5, 16);
|
||||
|
||||
Border dst2Border = randomBorder(0, useRoi ? 2 : 0);
|
||||
randomSubMat(dst2, dst2_roi, isize, dst2Border, sqdepth, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst2);
|
||||
}
|
||||
|
||||
void Near2(double threshold = 0.0, bool relative = false)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst2, threshold);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst2, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Integral, Mat1)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::integral(src_roi, dst_roi, sdepth));
|
||||
OCL_ON(cv::integral(usrc_roi, udst_roi, sdepth));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Integral, Mat2)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::integral(src_roi, dst_roi, dst2_roi, sdepth, sqdepth));
|
||||
OCL_ON(cv::integral(usrc_roi, udst_roi, udst2_roi, sdepth, sqdepth));
|
||||
|
||||
Near();
|
||||
sqdepth == CV_32F ? Near2(1e-6, true) : Near2();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////// threshold //////////////////////////////////////////////
|
||||
|
||||
struct Threshold :
|
||||
public ImgprocTestBase
|
||||
{
|
||||
int thresholdType;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
thresholdType = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Threshold, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double maxVal = randomDouble(20.0, 127.0);
|
||||
double thresh = randomDouble(0.0, maxVal);
|
||||
|
||||
OCL_OFF(cv::threshold(src_roi, dst_roi, thresh, maxVal, thresholdType));
|
||||
OCL_ON(cv::threshold(usrc_roi, udst_roi, thresh, maxVal, thresholdType));
|
||||
|
||||
Near(1);
|
||||
}
|
||||
}
|
||||
|
||||
struct Threshold_Dryrun :
|
||||
public ImgprocTestBase
|
||||
{
|
||||
int thresholdType;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
thresholdType = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Threshold_Dryrun, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double maxVal = randomDouble(20.0, 127.0);
|
||||
double thresh = randomDouble(0.0, maxVal);
|
||||
|
||||
const int _thresholdType = thresholdType | THRESH_DRYRUN;
|
||||
|
||||
src_roi.copyTo(dst_roi);
|
||||
usrc_roi.copyTo(udst_roi);
|
||||
|
||||
OCL_OFF(cv::threshold(src_roi, dst_roi, thresh, maxVal, _thresholdType));
|
||||
OCL_ON(cv::threshold(usrc_roi, udst_roi, thresh, maxVal, _thresholdType));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct Threshold_masked :
|
||||
public ImgprocTestBase
|
||||
{
|
||||
int thresholdType;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
thresholdType = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Threshold_masked, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double maxVal = randomDouble(20.0, 127.0);
|
||||
double thresh = randomDouble(0.0, maxVal);
|
||||
|
||||
const int _thresholdType = thresholdType;
|
||||
|
||||
cv::Size sz = src_roi.size();
|
||||
cv::Mat mask_roi = cv::Mat::zeros(sz, CV_8UC1);
|
||||
cv::RotatedRect ellipseRect((cv::Point2f)cv::Point(sz.width/2, sz.height/2), (cv::Size2f)sz, 0);
|
||||
cv::ellipse(mask_roi, ellipseRect, cv::Scalar::all(255), cv::FILLED);//for very different mask alignments
|
||||
|
||||
cv::UMat umask_roi(mask_roi.size(), mask_roi.type());
|
||||
mask_roi.copyTo(umask_roi.getMat(cv::AccessFlag::ACCESS_WRITE));
|
||||
|
||||
src_roi.copyTo(dst_roi);
|
||||
usrc_roi.copyTo(udst_roi);
|
||||
|
||||
OCL_OFF(cv::thresholdWithMask(src_roi, dst_roi, mask_roi, thresh, maxVal, _thresholdType));
|
||||
OCL_ON(cv::thresholdWithMask(usrc_roi, udst_roi, umask_roi, thresh, maxVal, _thresholdType));
|
||||
|
||||
OCL_EXPECT_MATS_NEAR(dst, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////// CLAHE //////////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(CLAHETest, Size, double, bool)
|
||||
{
|
||||
Size gridSize;
|
||||
double clipLimit;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
gridSize = GET_PARAM(0);
|
||||
clipLimit = GET_PARAM(1);
|
||||
useRoi = GET_PARAM(2);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
Size roiSize = randomSize(std::max(gridSize.height, gridSize.width), MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, CV_8UC1, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_8UC1, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(CLAHETest, Accuracy)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
Ptr<CLAHE> clahe = cv::createCLAHE(clipLimit, gridSize);
|
||||
|
||||
OCL_OFF(clahe->apply(src_roi, dst_roi));
|
||||
OCL_ON(clahe->apply(usrc_roi, udst_roi));
|
||||
|
||||
Near(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, EqualizeHist, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values(0), // not used
|
||||
Values(0), // not used
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerMinEigenVal, Combine(
|
||||
Values((MatType)CV_8UC1, (MatType)CV_32FC1),
|
||||
Values(3, 5),
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerHarris, Combine(
|
||||
Values((MatType)CV_8UC1, CV_32FC1),
|
||||
Values(3, 5),
|
||||
Values( (BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, PreCornerDetect, Combine(
|
||||
Values((MatType)CV_8UC1, CV_32FC1),
|
||||
Values(3, 5),
|
||||
Values( (BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Integral, Combine(
|
||||
Values((MatType)CV_8UC1), // TODO does not work with CV_32F, CV_64F
|
||||
Values(CV_32SC1, CV_32FC1), // desired sdepth
|
||||
Values(CV_32FC1, CV_64FC1), // desired sqdepth
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Threshold, Combine(
|
||||
Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4,
|
||||
CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4,
|
||||
CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4),
|
||||
Values(0),
|
||||
Values(ThreshOp(THRESH_BINARY),
|
||||
ThreshOp(THRESH_BINARY_INV), ThreshOp(THRESH_TRUNC),
|
||||
ThreshOp(THRESH_TOZERO), ThreshOp(THRESH_TOZERO_INV)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Threshold_Dryrun, Combine(
|
||||
Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4,
|
||||
CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4,
|
||||
CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4),
|
||||
Values(0),
|
||||
Values(ThreshOp(THRESH_BINARY),
|
||||
ThreshOp(THRESH_BINARY_INV), ThreshOp(THRESH_TRUNC),
|
||||
ThreshOp(THRESH_TOZERO), ThreshOp(THRESH_TOZERO_INV)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Threshold_masked, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_16SC3, CV_16UC1, CV_16UC3, CV_32FC1, CV_32FC3, CV_64FC1, CV_64FC3),
|
||||
Values(0),
|
||||
Values(ThreshOp(THRESH_BINARY),
|
||||
ThreshOp(THRESH_BINARY_INV), ThreshOp(THRESH_TRUNC),
|
||||
ThreshOp(THRESH_TOZERO), ThreshOp(THRESH_TOZERO_INV)),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CLAHETest, Combine(
|
||||
Values(Size(4, 4), Size(32, 8), Size(8, 64)),
|
||||
Values(0.0, 10.0, 62.0, 300.0),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocTestBase, CopyMakeBorder, Combine(
|
||||
testing::Values((MatDepth)CV_8U, (MatDepth)CV_16S, (MatDepth)CV_32S, (MatDepth)CV_32F),
|
||||
testing::Values(Channels(1), Channels(3), (Channels)4),
|
||||
Bool(), // border isolated or not
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_WRAP, (BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,133 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////////////////////////////////////// matchTemplate //////////////////////////////////////////////////////////
|
||||
|
||||
CV_ENUM(MatchTemplType, cv::TM_CCORR, cv::TM_CCORR_NORMED, cv::TM_SQDIFF, cv::TM_SQDIFF_NORMED, cv::TM_CCOEFF, cv::TM_CCOEFF_NORMED)
|
||||
|
||||
PARAM_TEST_CASE(MatchTemplate, MatDepth, Channels, MatchTemplType, bool)
|
||||
{
|
||||
int type;
|
||||
int depth;
|
||||
int method;
|
||||
bool use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(image);
|
||||
TEST_DECLARE_INPUT_PARAMETER(templ);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(result);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
depth = GET_PARAM(0);
|
||||
method = GET_PARAM(2);
|
||||
use_roi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
void generateTestData()
|
||||
{
|
||||
Size image_roiSize = randomSize(2, 100);
|
||||
Size templ_roiSize = Size(randomInt(1, image_roiSize.width), randomInt(1, image_roiSize.height));
|
||||
Size result_roiSize = Size(image_roiSize.width - templ_roiSize.width + 1,
|
||||
image_roiSize.height - templ_roiSize.height + 1);
|
||||
|
||||
const double upValue = 256;
|
||||
|
||||
Border imageBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(image, image_roi, image_roiSize, imageBorder, type, -upValue, upValue);
|
||||
|
||||
Border templBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(templ, templ_roi, templ_roiSize, templBorder, type, -upValue, upValue);
|
||||
|
||||
Border resultBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(result, result_roi, result_roiSize, resultBorder, CV_32FC1, -upValue, upValue);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(image);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(templ);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(result);
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
bool isNormed =
|
||||
method == TM_CCORR_NORMED ||
|
||||
method == TM_SQDIFF_NORMED ||
|
||||
method == TM_CCOEFF_NORMED;
|
||||
|
||||
if (isNormed)
|
||||
OCL_EXPECT_MATS_NEAR(result, 3e-2);
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE_SPARSE(result, 1.5e-2);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(MatchTemplate, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::matchTemplate(image_roi, templ_roi, result_roi, method));
|
||||
OCL_ON(cv::matchTemplate(uimage_roi, utempl_roi, uresult_roi, method));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, MatchTemplate, Combine(
|
||||
Values(CV_8U, CV_32F),
|
||||
Values(1, 2, 3, 4),
|
||||
MatchTemplType::all(),
|
||||
Bool())
|
||||
);
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
/////////////////////////////////////////////medianFilter//////////////////////////////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(MedianFilter, MatDepth, Channels, int, bool)
|
||||
{
|
||||
int type;
|
||||
int ksize;
|
||||
bool use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
ksize = GET_PARAM(2);
|
||||
use_roi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
void generateTestData()
|
||||
{
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(MedianFilter, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::medianBlur(src_roi, dst_roi, ksize));
|
||||
OCL_ON(cv::medianBlur(usrc_roi, udst_roi, ksize));
|
||||
|
||||
Near(0);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, MedianFilter, Combine(
|
||||
Values(CV_8U, CV_16U, CV_16S, CV_32F),
|
||||
OCL_ALL_CHANNELS,
|
||||
Values(3, 5),
|
||||
Bool())
|
||||
);
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Yao Wang yao@multicorewareinc.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(PyrTestBase, MatDepth, Channels, BorderType, bool)
|
||||
{
|
||||
int depth, channels, borderType;
|
||||
bool use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
channels = GET_PARAM(1);
|
||||
borderType = GET_PARAM(2);
|
||||
use_roi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
void generateTestData(Size src_roiSize, Size dst_roiSize)
|
||||
{
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, src_roiSize, srcBorder, CV_MAKETYPE(depth, channels), -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dst_roiSize, dstBorder, CV_MAKETYPE(depth, channels), -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////// PyrDown //////////////////////////
|
||||
|
||||
typedef PyrTestBase PyrDown;
|
||||
|
||||
OCL_TEST_P(PyrDown, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
Size src_roiSize = randomSize(1, MAX_VALUE);
|
||||
Size dst_roiSize = Size(randomInt((src_roiSize.width - 1) / 2, (src_roiSize.width + 3) / 2),
|
||||
randomInt((src_roiSize.height - 1) / 2, (src_roiSize.height + 3) / 2));
|
||||
dst_roiSize = dst_roiSize.empty() ? Size((src_roiSize.width + 1) / 2, (src_roiSize.height + 1) / 2) : dst_roiSize;
|
||||
generateTestData(src_roiSize, dst_roiSize);
|
||||
|
||||
OCL_OFF(pyrDown(src_roi, dst_roi, dst_roiSize, borderType));
|
||||
OCL_ON(pyrDown(usrc_roi, udst_roi, dst_roiSize, borderType));
|
||||
|
||||
Near(depth == CV_32F ? 1e-4f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocPyr, PyrDown, Combine(
|
||||
Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F),
|
||||
Values(1, 2, 3, 4),
|
||||
Values((BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101),
|
||||
Bool()
|
||||
));
|
||||
|
||||
/////////////////////// PyrUp //////////////////////////
|
||||
|
||||
typedef PyrTestBase PyrUp;
|
||||
|
||||
OCL_TEST_P(PyrUp, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
Size src_roiSize = randomSize(1, MAX_VALUE);
|
||||
Size dst_roiSize = Size(2 * src_roiSize.width, 2 * src_roiSize.height);
|
||||
generateTestData(src_roiSize, dst_roiSize);
|
||||
|
||||
OCL_OFF(pyrUp(src_roi, dst_roi, dst_roiSize, borderType));
|
||||
OCL_ON(pyrUp(usrc_roi, udst_roi, dst_roiSize, borderType));
|
||||
|
||||
Near(depth == CV_32F ? 1e-4f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
typedef PyrTestBase PyrUp_cols2;
|
||||
|
||||
OCL_TEST_P(PyrUp_cols2, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
Size src_roiSize = randomSize(1, MAX_VALUE);
|
||||
src_roiSize.width += (src_roiSize.width % 2);
|
||||
Size dst_roiSize = Size(2 * src_roiSize.width, 2 * src_roiSize.height);
|
||||
generateTestData(src_roiSize, dst_roiSize);
|
||||
|
||||
OCL_OFF(pyrUp(src_roi, dst_roi, dst_roiSize, borderType));
|
||||
OCL_ON(pyrUp(usrc_roi, udst_roi, dst_roiSize, borderType));
|
||||
|
||||
Near(depth == CV_32F ? 1e-4f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocPyr, PyrUp, Combine(
|
||||
Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F),
|
||||
Values(1, 2, 3, 4),
|
||||
Values((BorderType)BORDER_REFLECT_101),
|
||||
Bool()
|
||||
));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocPyr, PyrUp_cols2, Combine(
|
||||
Values((MatDepth)CV_8U),
|
||||
Values((Channels)1),
|
||||
Values((BorderType)BORDER_REFLECT_101),
|
||||
Bool()
|
||||
));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// sepFilter2D
|
||||
PARAM_TEST_CASE(SepFilter2D, MatDepth, Channels, BorderType, bool, bool)
|
||||
{
|
||||
static const int kernelMinSize = 2;
|
||||
static const int kernelMaxSize = 10;
|
||||
|
||||
int type;
|
||||
Point anchor;
|
||||
int borderType;
|
||||
bool useRoi;
|
||||
Mat kernelX, kernelY;
|
||||
double delta;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
borderType = GET_PARAM(2) | (GET_PARAM(3) ? BORDER_ISOLATED : 0);
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi(bool bitExact)
|
||||
{
|
||||
Size ksize = randomSize(kernelMinSize, kernelMaxSize);
|
||||
if (1 != ksize.width % 2)
|
||||
ksize.width++;
|
||||
if (1 != ksize.height % 2)
|
||||
ksize.height++;
|
||||
|
||||
Mat temp = randomMat(Size(ksize.width, 1), CV_32FC1, -0.5, 1.0);
|
||||
cv::normalize(temp, kernelX, 1.0, 0.0, NORM_L1);
|
||||
temp = randomMat(Size(1, ksize.height), CV_32FC1, -0.5, 1.0);
|
||||
cv::normalize(temp, kernelY, 1.0, 0.0, NORM_L1);
|
||||
|
||||
if (bitExact)
|
||||
{
|
||||
kernelX.convertTo(temp, CV_32S, 256);
|
||||
temp.convertTo(kernelX, CV_32F, 1.0 / 256);
|
||||
kernelY.convertTo(temp, CV_32S, 256);
|
||||
temp.convertTo(kernelY, CV_32F, 1.0 / 256);
|
||||
}
|
||||
|
||||
Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
anchor.x = anchor.y = -1;
|
||||
delta = randomDouble(-100, 100);
|
||||
|
||||
if (bitExact)
|
||||
{
|
||||
delta = (int)(delta * 256) / 256.0;
|
||||
}
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(SepFilter2D, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times + 3; j++)
|
||||
{
|
||||
random_roi(false);
|
||||
|
||||
OCL_OFF(cv::sepFilter2D(src_roi, dst_roi, -1, kernelX, kernelY, anchor, delta, borderType));
|
||||
OCL_ON(cv::sepFilter2D(usrc_roi, udst_roi, -1, kernelX, kernelY, anchor, delta, borderType));
|
||||
|
||||
Near(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(SepFilter2D, Mat_BitExact)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times + 3; j++)
|
||||
{
|
||||
random_roi(true);
|
||||
|
||||
OCL_OFF(cv::sepFilter2D(src_roi, dst_roi, -1, kernelX, kernelY, anchor, delta, borderType));
|
||||
OCL_ON(cv::sepFilter2D(usrc_roi, udst_roi, -1, kernelX, kernelY, anchor, delta, borderType));
|
||||
|
||||
if (src_roi.depth() < CV_32F)
|
||||
Near(0.0);
|
||||
else
|
||||
Near(1e-3);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, SepFilter2D,
|
||||
Combine(
|
||||
Values(CV_8U, CV_32F),
|
||||
OCL_ALL_CHANNELS,
|
||||
Values(
|
||||
(BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool(), // BORDER_ISOLATED
|
||||
Bool() // ROI
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,649 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Shengen Yan, yanshengen@gmail.com
|
||||
// Jiang Liyuan, lyuan001.good@163.com
|
||||
// Rock Li, Rock.Li@amd.com
|
||||
// Wu Zailong, bullet@yeah.net
|
||||
// Xu Pang, pangxu010@163.com
|
||||
// Sen Liu, swjtuls1987@126.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
enum
|
||||
{
|
||||
noType = -1
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// warpAffine & warpPerspective
|
||||
|
||||
PARAM_TEST_CASE(WarpTestBase, MatType, Interpolation, bool, bool)
|
||||
{
|
||||
int type, interpolation;
|
||||
Size dsize;
|
||||
bool useRoi, mapInverse;
|
||||
int depth;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
interpolation = GET_PARAM(1);
|
||||
mapInverse = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
depth = CV_MAT_DEPTH(type);
|
||||
|
||||
if (mapInverse)
|
||||
interpolation |= WARP_INVERSE_MAP;
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
dsize = randomSize(1, MAX_VALUE);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
if (depth < CV_32F)
|
||||
EXPECT_MAT_N_DIFF_EPS(dst_roi, udst_roi, 1, cvRound(dst_roi.total()*threshold));
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
PARAM_TEST_CASE(WarpTest_cols4_Base, MatType, Interpolation, bool, bool)
|
||||
{
|
||||
int type, interpolation;
|
||||
Size dsize;
|
||||
bool useRoi, mapInverse;
|
||||
int depth;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
interpolation = GET_PARAM(1);
|
||||
mapInverse = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
depth = CV_MAT_DEPTH(type);
|
||||
|
||||
if (mapInverse)
|
||||
interpolation |= WARP_INVERSE_MAP;
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
dsize = randomSize(1, MAX_VALUE);
|
||||
dsize.width = ((dsize.width >> 2) + 1) * 4;
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
if (depth < CV_32F)
|
||||
EXPECT_MAT_N_DIFF(dst_roi, udst_roi, cvRound(dst_roi.total()*threshold));
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
/////warpAffine
|
||||
|
||||
typedef WarpTestBase WarpAffine;
|
||||
|
||||
/////warpAffine
|
||||
|
||||
typedef WarpTestBase WarpAffine;
|
||||
|
||||
OCL_TEST_P(WarpAffine, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
double eps = depth < CV_32F ? ( depth < CV_16U ? 0.09 : 0.04 ) : 0.06;
|
||||
random_roi();
|
||||
|
||||
Mat M = getRotationMatrix2D(Point2f(src_roi.cols / 2.0f, src_roi.rows / 2.0f),
|
||||
rng.uniform(-180.f, 180.f), rng.uniform(0.4f, 2.0f));
|
||||
|
||||
OCL_OFF(cv::warpAffine(src_roi, dst_roi, M, dsize, interpolation));
|
||||
OCL_ON(cv::warpAffine(usrc_roi, udst_roi, M, dsize, interpolation));
|
||||
|
||||
Near(eps);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(WarpAffine, inplace_25853) // when src and dst are the same variable, ocl on/off should produce consistent and correct results
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
double eps = depth < CV_32F ? ( depth < CV_16U ? 0.09 : 0.04 ) : 0.06;
|
||||
random_roi();
|
||||
|
||||
Mat M = getRotationMatrix2D(Point2f(src_roi.cols / 2.0f, src_roi.rows / 2.0f),
|
||||
rng.uniform(-180.f, 180.f), rng.uniform(0.4f, 2.0f));
|
||||
|
||||
OCL_OFF(cv::warpAffine(src_roi, src_roi, M, dsize, interpolation));
|
||||
OCL_ON(cv::warpAffine(usrc_roi, usrc_roi, M, dsize, interpolation));
|
||||
|
||||
dst_roi = src_roi.clone();
|
||||
udst_roi = usrc_roi.clone();
|
||||
|
||||
Near(eps);
|
||||
}
|
||||
}
|
||||
|
||||
typedef WarpTest_cols4_Base WarpAffine_cols4;
|
||||
|
||||
OCL_TEST_P(WarpAffine_cols4, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
double eps = depth < CV_32F ? 0.04 : 0.06;
|
||||
random_roi();
|
||||
|
||||
Mat M = getRotationMatrix2D(Point2f(src_roi.cols / 2.0f, src_roi.rows / 2.0f),
|
||||
rng.uniform(-180.f, 180.f), rng.uniform(0.4f, 2.0f));
|
||||
|
||||
OCL_OFF(cv::warpAffine(src_roi, dst_roi, M, dsize, interpolation));
|
||||
OCL_ON(cv::warpAffine(usrc_roi, udst_roi, M, dsize, interpolation));
|
||||
|
||||
Near(eps);
|
||||
}
|
||||
}
|
||||
|
||||
//// warpPerspective
|
||||
|
||||
typedef WarpTestBase WarpPerspective;
|
||||
|
||||
OCL_TEST_P(WarpPerspective, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
double eps = depth < CV_32F ? 0.03 : 0.06;
|
||||
random_roi();
|
||||
|
||||
float cols = static_cast<float>(src_roi.cols), rows = static_cast<float>(src_roi.rows);
|
||||
float cols2 = cols / 2.0f, rows2 = rows / 2.0f;
|
||||
Point2f sp[] = { Point2f(0.0f, 0.0f), Point2f(cols, 0.0f), Point2f(0.0f, rows), Point2f(cols, rows) };
|
||||
Point2f dp[] = { Point2f(rng.uniform(0.0f, cols2), rng.uniform(0.0f, rows2)),
|
||||
Point2f(rng.uniform(cols2, cols), rng.uniform(0.0f, rows2)),
|
||||
Point2f(rng.uniform(0.0f, cols2), rng.uniform(rows2, rows)),
|
||||
Point2f(rng.uniform(cols2, cols), rng.uniform(rows2, rows)) };
|
||||
Mat M = getPerspectiveTransform(sp, dp);
|
||||
|
||||
OCL_OFF(cv::warpPerspective(src_roi, dst_roi, M, dsize, interpolation));
|
||||
OCL_ON(cv::warpPerspective(usrc_roi, udst_roi, M, dsize, interpolation));
|
||||
|
||||
Near(eps);
|
||||
}
|
||||
}
|
||||
|
||||
typedef WarpTest_cols4_Base WarpPerspective_cols4;
|
||||
|
||||
OCL_TEST_P(WarpPerspective_cols4, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
double eps = depth < CV_32F ? 0.03 : 0.06;
|
||||
random_roi();
|
||||
|
||||
float cols = static_cast<float>(src_roi.cols), rows = static_cast<float>(src_roi.rows);
|
||||
float cols2 = cols / 2.0f, rows2 = rows / 2.0f;
|
||||
Point2f sp[] = { Point2f(0.0f, 0.0f), Point2f(cols, 0.0f), Point2f(0.0f, rows), Point2f(cols, rows) };
|
||||
Point2f dp[] = { Point2f(rng.uniform(0.0f, cols2), rng.uniform(0.0f, rows2)),
|
||||
Point2f(rng.uniform(cols2, cols), rng.uniform(0.0f, rows2)),
|
||||
Point2f(rng.uniform(0.0f, cols2), rng.uniform(rows2, rows)),
|
||||
Point2f(rng.uniform(cols2, cols), rng.uniform(rows2, rows)) };
|
||||
Mat M = getPerspectiveTransform(sp, dp);
|
||||
|
||||
OCL_OFF(cv::warpPerspective(src_roi, dst_roi, M, dsize, interpolation));
|
||||
OCL_ON(cv::warpPerspective(usrc_roi, udst_roi, M, dsize, interpolation));
|
||||
|
||||
Near(eps);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//// resize
|
||||
|
||||
PARAM_TEST_CASE(Resize, MatType, double, double, Interpolation, bool, int)
|
||||
{
|
||||
int type, interpolation;
|
||||
int widthMultiple;
|
||||
double fx, fy;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
fx = GET_PARAM(1);
|
||||
fy = GET_PARAM(2);
|
||||
interpolation = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
widthMultiple = GET_PARAM(5);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
CV_Assert(fx > 0 && fy > 0);
|
||||
|
||||
Size srcRoiSize = randomSize(10, MAX_VALUE), dstRoiSize;
|
||||
// Make sure the width is a multiple of the requested value, and no more
|
||||
srcRoiSize.width += widthMultiple - 1 - (srcRoiSize.width - 1) % widthMultiple;
|
||||
dstRoiSize.width = cvRound(srcRoiSize.width * fx);
|
||||
dstRoiSize.height = cvRound(srcRoiSize.height * fy);
|
||||
|
||||
if (dstRoiSize.empty())
|
||||
{
|
||||
random_roi();
|
||||
return;
|
||||
}
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, srcRoiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dstRoiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__aarch64__) || defined(__arm__)
|
||||
const int integerEps = 3;
|
||||
#else
|
||||
const int integerEps = 1;
|
||||
#endif
|
||||
OCL_TEST_P(Resize, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
double eps = depth <= CV_32S ? integerEps : 5e-2;
|
||||
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::resize(src_roi, dst_roi, Size(), fx, fy, interpolation));
|
||||
OCL_ON(cv::resize(usrc_roi, udst_roi, Size(), fx, fy, interpolation));
|
||||
|
||||
OCL_EXPECT_MAT_N_DIFF(dst, eps);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST(Resize, overflow_21198)
|
||||
{
|
||||
Mat src(Size(600, 600), CV_16UC3, Scalar::all(32768));
|
||||
UMat src_u;
|
||||
src.copyTo(src_u);
|
||||
|
||||
Mat dst;
|
||||
cv::resize(src, dst, Size(1024, 1024), 0, 0, INTER_LINEAR);
|
||||
UMat dst_u;
|
||||
cv::resize(src_u, dst_u, Size(1024, 1024), 0, 0, INTER_LINEAR);
|
||||
EXPECT_LE(cv::norm(dst_u, dst, NORM_INF), 1.0f);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// remap
|
||||
|
||||
PARAM_TEST_CASE(Remap, MatDepth, Channels, std::pair<MatType, MatType>, BorderType, bool)
|
||||
{
|
||||
int srcType, map1Type, map2Type;
|
||||
int borderType;
|
||||
bool useRoi;
|
||||
|
||||
Scalar val;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
TEST_DECLARE_INPUT_PARAMETER(map1);
|
||||
TEST_DECLARE_INPUT_PARAMETER(map2);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
srcType = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
map1Type = GET_PARAM(2).first;
|
||||
map2Type = GET_PARAM(2).second;
|
||||
borderType = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
val = randomScalar(-MAX_VALUE, MAX_VALUE);
|
||||
Size srcROISize = randomSize(1, MAX_VALUE);
|
||||
Size dstROISize = randomSize(1, MAX_VALUE);
|
||||
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, srcROISize, srcBorder, srcType, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dstROISize, dstBorder, srcType, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
int mapMaxValue = MAX_VALUE << 2;
|
||||
Border map1Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(map1, map1_roi, dstROISize, map1Border, map1Type, -mapMaxValue, mapMaxValue);
|
||||
|
||||
Border map2Border = randomBorder(0, useRoi ? MAX_VALUE + 1 : 0);
|
||||
if (map2Type != noType)
|
||||
{
|
||||
int mapMinValue = -mapMaxValue;
|
||||
if (map2Type == CV_16UC1 || map2Type == CV_16SC1)
|
||||
mapMinValue = 0, mapMaxValue = INTER_TAB_SIZE2;
|
||||
randomSubMat(map2, map2_roi, dstROISize, map2Border, map2Type, mapMinValue, mapMaxValue);
|
||||
}
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src);
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(map1);
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst);
|
||||
if (noType != map2Type)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(map2);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Remap Remap_INTER_NEAREST;
|
||||
|
||||
OCL_TEST_P(Remap_INTER_NEAREST, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::remap(src_roi, dst_roi, map1_roi, map2_roi, INTER_NEAREST, borderType, val));
|
||||
OCL_ON(cv::remap(usrc_roi, udst_roi, umap1_roi, umap2_roi, INTER_NEAREST, borderType, val));
|
||||
|
||||
OCL_EXPECT_MAT_N_DIFF(dst, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
typedef Remap Remap_INTER_LINEAR;
|
||||
|
||||
OCL_TEST_P(Remap_INTER_LINEAR, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double eps = 2.0;
|
||||
#ifdef __ANDROID__
|
||||
// TODO investigate accuracy
|
||||
if (cv::ocl::Device::getDefault().isNVidia())
|
||||
eps = 8.0;
|
||||
#elif defined(__arm__)
|
||||
eps = 8.0;
|
||||
#endif
|
||||
|
||||
OCL_OFF(cv::remap(src_roi, dst_roi, map1_roi, map2_roi, INTER_LINEAR, borderType, val));
|
||||
OCL_ON(cv::remap(usrc_roi, udst_roi, umap1_roi, umap2_roi, INTER_LINEAR, borderType, val));
|
||||
|
||||
OCL_EXPECT_MAT_N_DIFF(dst, eps);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// remap relative
|
||||
|
||||
PARAM_TEST_CASE(RemapRelative, MatDepth, Channels, Interpolation, BorderType, bool)
|
||||
{
|
||||
int srcType;
|
||||
int interpolation;
|
||||
int borderType;
|
||||
bool useFixedPoint;
|
||||
|
||||
Scalar val;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(map1);
|
||||
TEST_DECLARE_INPUT_PARAMETER(map2);
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst);
|
||||
|
||||
UMat uSrc;
|
||||
UMat uMapRelativeX32F;
|
||||
UMat uMapRelativeY32F;
|
||||
UMat uMapAbsoluteX32F;
|
||||
UMat uMapAbsoluteY32F;
|
||||
UMat uMapRelativeX16S;
|
||||
UMat uMapRelativeY16S;
|
||||
UMat uMapAbsoluteX16S;
|
||||
UMat uMapAbsoluteY16S;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
srcType = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
interpolation = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
useFixedPoint = GET_PARAM(4);
|
||||
|
||||
const int nChannels = CV_MAT_CN(srcType);
|
||||
const cv::Size size(127, 61);
|
||||
cv::Mat data64FC1(1, size.area()*nChannels, CV_64FC1);
|
||||
data64FC1.forEach<double>([&](double& pixel, const int* position) {pixel = static_cast<double>(position[1]);});
|
||||
|
||||
cv::Mat src;
|
||||
data64FC1.reshape(nChannels, size.height).convertTo(src, srcType);
|
||||
|
||||
cv::Mat mapRelativeX32F(size, CV_32FC1);
|
||||
mapRelativeX32F.setTo(cv::Scalar::all(-0.25));
|
||||
|
||||
cv::Mat mapRelativeY32F(size, CV_32FC1);
|
||||
mapRelativeY32F.setTo(cv::Scalar::all(-0.25));
|
||||
|
||||
cv::Mat mapAbsoluteX32F = mapRelativeX32F.clone();
|
||||
mapAbsoluteX32F.forEach<float>([&](float& pixel, const int* position) {
|
||||
pixel += static_cast<float>(position[1]);
|
||||
});
|
||||
|
||||
cv::Mat mapAbsoluteY32F = mapRelativeY32F.clone();
|
||||
mapAbsoluteY32F.forEach<float>([&](float& pixel, const int* position) {
|
||||
pixel += static_cast<float>(position[0]);
|
||||
});
|
||||
|
||||
OCL_ON(src.copyTo(uSrc));
|
||||
OCL_ON(mapRelativeX32F.copyTo(uMapRelativeX32F));
|
||||
OCL_ON(mapRelativeY32F.copyTo(uMapRelativeY32F));
|
||||
OCL_ON(mapAbsoluteX32F.copyTo(uMapAbsoluteX32F));
|
||||
OCL_ON(mapAbsoluteY32F.copyTo(uMapAbsoluteY32F));
|
||||
|
||||
if (useFixedPoint)
|
||||
{
|
||||
const bool nninterpolation = (interpolation == cv::INTER_NEAREST) || (interpolation == cv::INTER_NEAREST_EXACT);
|
||||
OCL_ON(cv::convertMaps(uMapAbsoluteX32F, uMapAbsoluteY32F, uMapAbsoluteX16S, uMapAbsoluteY16S, CV_16SC2, nninterpolation));
|
||||
OCL_ON(cv::convertMaps(uMapRelativeX32F, uMapRelativeY32F, uMapRelativeX16S, uMapRelativeY16S, CV_16SC2, nninterpolation));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(RemapRelative, Mat)
|
||||
{
|
||||
cv::UMat uDstAbsolute;
|
||||
cv::UMat uDstRelative;
|
||||
if (useFixedPoint)
|
||||
{
|
||||
OCL_ON(cv::remap(uSrc, uDstAbsolute, uMapAbsoluteX16S, uMapAbsoluteY16S, interpolation, borderType));
|
||||
OCL_ON(cv::remap(uSrc, uDstRelative, uMapRelativeX16S, uMapRelativeY16S, interpolation | WARP_RELATIVE_MAP, borderType));
|
||||
}
|
||||
else
|
||||
{
|
||||
OCL_ON(cv::remap(uSrc, uDstAbsolute, uMapAbsoluteX32F, uMapAbsoluteY32F, interpolation, borderType));
|
||||
OCL_ON(cv::remap(uSrc, uDstRelative, uMapRelativeX32F, uMapRelativeY32F, interpolation | WARP_RELATIVE_MAP, borderType));
|
||||
}
|
||||
|
||||
cv::Mat dstAbsolute;
|
||||
OCL_ON(uDstAbsolute.copyTo(dstAbsolute));
|
||||
cv::Mat dstRelative;
|
||||
OCL_ON(uDstRelative.copyTo(dstRelative));
|
||||
|
||||
EXPECT_MAT_NEAR(dstAbsolute, dstRelative, dstAbsolute.depth() == CV_32F ? 1e-3 : 1.0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpAffine, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4),
|
||||
Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR, (Interpolation)INTER_CUBIC),
|
||||
Bool(),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpAffine_cols4, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR, (Interpolation)INTER_CUBIC),
|
||||
Bool(),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpPerspective, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4),
|
||||
Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR, (Interpolation)INTER_CUBIC),
|
||||
Bool(),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpPerspective_cols4, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR, (Interpolation)INTER_CUBIC),
|
||||
Bool(),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, Resize, Combine(
|
||||
Values(CV_8UC1, CV_8UC4, CV_16UC2, CV_32FC1, CV_32FC4),
|
||||
Values(0.5, 1.5, 2.0, 0.2),
|
||||
Values(0.5, 1.5, 2.0, 0.2),
|
||||
Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR),
|
||||
Bool(),
|
||||
Values(1, 16)));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarpLinearExact, Resize, Combine(
|
||||
Values(CV_8UC1, CV_8UC4, CV_16UC2),
|
||||
Values(0.5, 1.5, 2.0, 0.2),
|
||||
Values(0.5, 1.5, 2.0, 0.2),
|
||||
Values((Interpolation)INTER_LINEAR_EXACT),
|
||||
Bool(),
|
||||
Values(1, 16)));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarpResizeArea, Resize, Combine(
|
||||
Values((MatType)CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4),
|
||||
Values(0.7, 0.4, 0.5),
|
||||
Values(0.3, 0.6, 0.5),
|
||||
Values((Interpolation)INTER_AREA),
|
||||
Bool(),
|
||||
Values(1, 16)));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, Remap_INTER_LINEAR, Combine(
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
Values(std::pair<MatType, MatType>((MatType)CV_32FC1, (MatType)CV_32FC1),
|
||||
std::pair<MatType, MatType>((MatType)CV_16SC2, (MatType)CV_16UC1),
|
||||
std::pair<MatType, MatType>((MatType)CV_32FC2, noType)),
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_WRAP,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, Remap_INTER_NEAREST, Combine(
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
Values(std::pair<MatType, MatType>((MatType)CV_32FC1, (MatType)CV_32FC1),
|
||||
std::pair<MatType, MatType>((MatType)CV_32FC2, noType),
|
||||
std::pair<MatType, MatType>((MatType)CV_16SC2, (MatType)CV_16UC1),
|
||||
std::pair<MatType, MatType>((MatType)CV_16SC2, noType)),
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_WRAP,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, RemapRelative, Combine(
|
||||
Values(CV_8U, CV_16U, CV_32F, CV_64F),
|
||||
Values(1, 3, 4),
|
||||
Values((Interpolation)INTER_NEAREST,
|
||||
(Interpolation)INTER_LINEAR,
|
||||
(Interpolation)INTER_CUBIC,
|
||||
(Interpolation)INTER_LANCZOS4),
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_WRAP,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
@@ -0,0 +1,323 @@
|
||||
/*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_BilateralFilterTest :
|
||||
public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_WIDTH = 1920, MIN_WIDTH = 1,
|
||||
MAX_HEIGHT = 1080, MIN_HEIGHT = 1
|
||||
};
|
||||
|
||||
CV_BilateralFilterTest();
|
||||
~CV_BilateralFilterTest();
|
||||
|
||||
protected:
|
||||
virtual void run_func();
|
||||
virtual int prepare_test_case(int test_case_index);
|
||||
virtual int validate_test_results(int test_case_index);
|
||||
|
||||
private:
|
||||
void reference_bilateral_filter(const Mat& src, Mat& dst, int d, double sigma_color,
|
||||
double sigma_space, int borderType = BORDER_DEFAULT);
|
||||
|
||||
int getRandInt(RNG& rng, int min_value, int max_value) const;
|
||||
|
||||
double _sigma_color;
|
||||
double _sigma_space;
|
||||
|
||||
Mat _src;
|
||||
Mat _parallel_dst;
|
||||
int _d;
|
||||
};
|
||||
|
||||
CV_BilateralFilterTest::CV_BilateralFilterTest() :
|
||||
cvtest::BaseTest(), _src(), _parallel_dst(), _d()
|
||||
{
|
||||
test_case_count = 1000;
|
||||
}
|
||||
|
||||
CV_BilateralFilterTest::~CV_BilateralFilterTest()
|
||||
{
|
||||
}
|
||||
|
||||
int CV_BilateralFilterTest::getRandInt(RNG& rng, int min_value, int max_value) const
|
||||
{
|
||||
double rand_value = rng.uniform(log((double)min_value), log((double)max_value + 1));
|
||||
return cvRound(exp((double)rand_value));
|
||||
}
|
||||
|
||||
void CV_BilateralFilterTest::reference_bilateral_filter(const Mat &src, Mat &dst, int d,
|
||||
double sigma_color, double sigma_space, int borderType)
|
||||
{
|
||||
int cn = src.channels();
|
||||
int i, j, k, maxk, radius;
|
||||
double minValSrc = -1, maxValSrc = 1;
|
||||
const int kExpNumBinsPerChannel = 1 << 12;
|
||||
int kExpNumBins = 0;
|
||||
float lastExpVal = 1.f;
|
||||
float len, scale_index;
|
||||
Size size = src.size();
|
||||
|
||||
dst.create(size, src.type());
|
||||
|
||||
CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) &&
|
||||
src.type() == dst.type() && src.size() == dst.size() &&
|
||||
src.data != dst.data );
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigma_color <= eps || sigma_space <= eps )
|
||||
{
|
||||
src.copyTo(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
|
||||
double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
|
||||
|
||||
if( d <= 0 )
|
||||
radius = cvRound(sigma_space*1.5);
|
||||
else
|
||||
radius = d/2;
|
||||
radius = MAX(radius, 1);
|
||||
d = radius*2 + 1;
|
||||
// compute the min/max range for the input image (even if multichannel)
|
||||
|
||||
// TODO cvtest
|
||||
cv::minMaxLoc( src.reshape(1), &minValSrc, &maxValSrc );
|
||||
if(std::abs(minValSrc - maxValSrc) < FLT_EPSILON)
|
||||
{
|
||||
src.copyTo(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
// temporary copy of the image with borders for easy processing
|
||||
Mat temp;
|
||||
cv::copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
|
||||
cv::patchNaNs(temp);
|
||||
|
||||
// allocate lookup tables
|
||||
vector<float> _space_weight(d*d);
|
||||
vector<int> _space_ofs(d*d);
|
||||
float* space_weight = &_space_weight[0];
|
||||
int* space_ofs = &_space_ofs[0];
|
||||
|
||||
// assign a length which is slightly more than needed
|
||||
len = (float)(maxValSrc - minValSrc) * cn;
|
||||
kExpNumBins = kExpNumBinsPerChannel * cn;
|
||||
vector<float> _expLUT(kExpNumBins+2);
|
||||
float* expLUT = &_expLUT[0];
|
||||
|
||||
scale_index = kExpNumBins/len;
|
||||
|
||||
// initialize the exp LUT
|
||||
for( i = 0; i < kExpNumBins+2; i++ )
|
||||
{
|
||||
if( lastExpVal > 0.f )
|
||||
{
|
||||
double val = i / scale_index;
|
||||
expLUT[i] = (float)std::exp(val * val * gauss_color_coeff);
|
||||
lastExpVal = expLUT[i];
|
||||
}
|
||||
else
|
||||
expLUT[i] = 0.f;
|
||||
}
|
||||
|
||||
// initialize space-related bilateral filter coefficients
|
||||
for( i = -radius, maxk = 0; i <= radius; i++ )
|
||||
for( j = -radius; j <= radius; j++ )
|
||||
{
|
||||
double r = std::sqrt((double)i*i + (double)j*j);
|
||||
if( r > radius )
|
||||
continue;
|
||||
space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
|
||||
space_ofs[maxk++] = (int)(i*(temp.step/sizeof(float)) + j*cn);
|
||||
}
|
||||
|
||||
for( i = 0; i < size.height; i++ )
|
||||
{
|
||||
const float* sptr = temp.ptr<float>(i+radius) + radius*cn;
|
||||
float* dptr = dst.ptr<float>(i);
|
||||
|
||||
if( cn == 1 )
|
||||
{
|
||||
for( j = 0; j < size.width; j++ )
|
||||
{
|
||||
float sum = 0, wsum = 0;
|
||||
float val0 = sptr[j];
|
||||
for( k = 0; k < maxk; k++ )
|
||||
{
|
||||
float val = sptr[j + space_ofs[k]];
|
||||
float alpha = (float)(std::abs(val - val0)*scale_index);
|
||||
int idx = cvFloor(alpha);
|
||||
alpha -= idx;
|
||||
float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
|
||||
sum += val*w;
|
||||
wsum += w;
|
||||
}
|
||||
dptr[j] = (float)(sum/wsum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( cn == 3 );
|
||||
for( j = 0; j < size.width*3; j += 3 )
|
||||
{
|
||||
float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
|
||||
float b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
|
||||
for( k = 0; k < maxk; k++ )
|
||||
{
|
||||
const float* sptr_k = sptr + j + space_ofs[k];
|
||||
float b = sptr_k[0], g = sptr_k[1], r = sptr_k[2];
|
||||
float alpha = (float)((std::abs(b - b0) +
|
||||
std::abs(g - g0) + std::abs(r - r0))*scale_index);
|
||||
int idx = cvFloor(alpha);
|
||||
alpha -= idx;
|
||||
float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
|
||||
sum_b += b*w; sum_g += g*w; sum_r += r*w;
|
||||
wsum += w;
|
||||
}
|
||||
wsum = 1.f/wsum;
|
||||
b0 = sum_b*wsum;
|
||||
g0 = sum_g*wsum;
|
||||
r0 = sum_r*wsum;
|
||||
dptr[j] = b0; dptr[j+1] = g0; dptr[j+2] = r0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CV_BilateralFilterTest::prepare_test_case(int /* test_case_index */)
|
||||
{
|
||||
const static int types[] = { CV_32FC1, CV_32FC3, CV_8UC1, CV_8UC3 };
|
||||
RNG& rng = ts->get_rng();
|
||||
Size size(getRandInt(rng, MIN_WIDTH, MAX_WIDTH), getRandInt(rng, MIN_HEIGHT, MAX_HEIGHT));
|
||||
int type = types[rng(sizeof(types) / sizeof(types[0]))];
|
||||
|
||||
_d = rng.uniform(0., 1.) > 0.5 ? 5 : 3;
|
||||
|
||||
_src.create(size, type);
|
||||
|
||||
rng.fill(_src, RNG::UNIFORM, 0, 256);
|
||||
|
||||
_sigma_color = _sigma_space = rng.uniform(0., 10.);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CV_BilateralFilterTest::validate_test_results(int test_case_index)
|
||||
{
|
||||
double eps = (_src.depth() < CV_32F)?1:5e-3;
|
||||
double e;
|
||||
Mat reference_dst, reference_src;
|
||||
if (_src.depth() == CV_32F)
|
||||
{
|
||||
reference_bilateral_filter(_src, reference_dst, _d, _sigma_color, _sigma_space);
|
||||
e = cvtest::norm(reference_dst, _parallel_dst, NORM_INF|NORM_RELATIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
int type = _src.type();
|
||||
_src.convertTo(reference_src, CV_32F);
|
||||
reference_bilateral_filter(reference_src, reference_dst, _d, _sigma_color, _sigma_space);
|
||||
reference_dst.convertTo(reference_dst, type);
|
||||
e = cvtest::norm(reference_dst, _parallel_dst, NORM_INF);
|
||||
}
|
||||
|
||||
if (e > eps)
|
||||
{
|
||||
ts->printf(cvtest::TS::CONSOLE, "actual error: %g, expected: %g", e, eps);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
else
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
|
||||
return BaseTest::validate_test_results(test_case_index);
|
||||
}
|
||||
|
||||
void CV_BilateralFilterTest::run_func()
|
||||
{
|
||||
bilateralFilter(_src, _parallel_dst, _d, _sigma_color, _sigma_space);
|
||||
}
|
||||
|
||||
TEST(Imgproc_BilateralFilter, accuracy)
|
||||
{
|
||||
CV_BilateralFilterTest test;
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
// Regression test for issue #28254
|
||||
// Out-of-bounds read in AVX2 bilateralFilter 32f path with BORDER_CONSTANT
|
||||
TEST(Imgproc_BilateralFilter, regression_28254_oob_read)
|
||||
{
|
||||
// Create a 64x64 CV_32FC1 image with values in range [100, 200]
|
||||
// Image must be large enough (width >= 32) to trigger SIMD/AVX2 code path.
|
||||
// Values are set so BORDER_CONSTANT padding (default 0) is outside the range,
|
||||
// which triggers the out-of-bounds condition in the LUT access.
|
||||
cv::Mat src(64, 64, CV_32FC1);
|
||||
cv::randu(src, 100.0f, 200.0f);
|
||||
cv::Mat dst;
|
||||
|
||||
// Parameters that trigger the bug
|
||||
int d = -1;
|
||||
double sigmaColor = 2.7;
|
||||
double sigmaSpace = 44.5;
|
||||
int borderType = cv::BORDER_CONSTANT;
|
||||
|
||||
// This should not crash or trigger AddressSanitizer
|
||||
EXPECT_NO_THROW(
|
||||
cv::bilateralFilter(src, dst, d, sigmaColor, sigmaSpace, borderType)
|
||||
);
|
||||
|
||||
// Verify output is valid
|
||||
EXPECT_FALSE(dst.empty());
|
||||
EXPECT_EQ(dst.size(), src.size());
|
||||
EXPECT_EQ(dst.type(), src.type());
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,228 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static void Canny_reference_follow( int x, int y, float lowThreshold, const Mat& mag, Mat& dst )
|
||||
{
|
||||
static const int ofs[][2] = {{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};
|
||||
int i;
|
||||
|
||||
dst.at<uchar>(y, x) = (uchar)255;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
int x1 = x + ofs[i][0];
|
||||
int y1 = y + ofs[i][1];
|
||||
if( (unsigned)x1 < (unsigned)mag.cols &&
|
||||
(unsigned)y1 < (unsigned)mag.rows &&
|
||||
mag.at<float>(y1, x1) > lowThreshold &&
|
||||
!dst.at<uchar>(y1, x1) )
|
||||
Canny_reference_follow( x1, y1, lowThreshold, mag, dst );
|
||||
}
|
||||
}
|
||||
|
||||
static void Canny_reference( const Mat& src, Mat& dst,
|
||||
double threshold1, double threshold2,
|
||||
int aperture_size, bool use_true_gradient )
|
||||
{
|
||||
dst.create(src.size(), src.type());
|
||||
int m = aperture_size;
|
||||
Point anchor(m/2, m/2);
|
||||
const double tan_pi_8 = tan(CV_PI/8.);
|
||||
const double tan_3pi_8 = tan(CV_PI*3/8);
|
||||
float lowThreshold = (float)MIN(threshold1, threshold2);
|
||||
float highThreshold = (float)MAX(threshold1, threshold2);
|
||||
|
||||
int x, y, width = src.cols, height = src.rows;
|
||||
|
||||
Mat dxkernel = cvtest::calcSobelKernel2D( 1, 0, m, 0 );
|
||||
Mat dykernel = cvtest::calcSobelKernel2D( 0, 1, m, 0 );
|
||||
Mat dx, dy, mag(height, width, CV_32F);
|
||||
cvtest::filter2D(src, dx, CV_32S, dxkernel, anchor, 0, BORDER_REPLICATE);
|
||||
cvtest::filter2D(src, dy, CV_32S, dykernel, anchor, 0, BORDER_REPLICATE);
|
||||
|
||||
// calc gradient magnitude
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < width; x++ )
|
||||
{
|
||||
int dxval = dx.at<int>(y, x), dyval = dy.at<int>(y, x);
|
||||
mag.at<float>(y, x) = use_true_gradient ?
|
||||
(float)sqrt((double)(dxval*dxval + dyval*dyval)) :
|
||||
(float)(fabs((double)dxval) + fabs((double)dyval));
|
||||
}
|
||||
}
|
||||
|
||||
// calc gradient direction, do nonmaxima suppression
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < width; x++ )
|
||||
{
|
||||
|
||||
float a = mag.at<float>(y, x), b = 0, c = 0;
|
||||
int y1 = 0, y2 = 0, x1 = 0, x2 = 0;
|
||||
|
||||
if( a <= lowThreshold )
|
||||
continue;
|
||||
|
||||
int dxval = dx.at<int>(y, x);
|
||||
int dyval = dy.at<int>(y, x);
|
||||
|
||||
double tg = dxval ? (double)dyval/dxval : DBL_MAX*CV_SIGN(dyval);
|
||||
|
||||
if( fabs(tg) < tan_pi_8 )
|
||||
{
|
||||
y1 = y2 = y; x1 = x + 1; x2 = x - 1;
|
||||
}
|
||||
else if( tan_pi_8 <= tg && tg <= tan_3pi_8 )
|
||||
{
|
||||
y1 = y + 1; y2 = y - 1; x1 = x + 1; x2 = x - 1;
|
||||
}
|
||||
else if( -tan_3pi_8 <= tg && tg <= -tan_pi_8 )
|
||||
{
|
||||
y1 = y - 1; y2 = y + 1; x1 = x + 1; x2 = x - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( fabs(tg) > tan_3pi_8 );
|
||||
x1 = x2 = x; y1 = y + 1; y2 = y - 1;
|
||||
}
|
||||
|
||||
if( (unsigned)y1 < (unsigned)height && (unsigned)x1 < (unsigned)width )
|
||||
b = (float)fabs(mag.at<float>(y1, x1));
|
||||
|
||||
if( (unsigned)y2 < (unsigned)height && (unsigned)x2 < (unsigned)width )
|
||||
c = (float)fabs(mag.at<float>(y2, x2));
|
||||
|
||||
if( (a > b || (a == b && ((x1 == x+1 && y1 == y) || (x1 == x && y1 == y+1)))) && a > c )
|
||||
;
|
||||
else
|
||||
mag.at<float>(y, x) = -a;
|
||||
}
|
||||
}
|
||||
|
||||
dst = Scalar::all(0);
|
||||
|
||||
// hysteresis threshold
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < width; x++ )
|
||||
if( mag.at<float>(y, x) > highThreshold && !dst.at<uchar>(y, x) )
|
||||
Canny_reference_follow( x, y, lowThreshold, mag, dst );
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
// aperture, true gradient
|
||||
typedef testing::TestWithParam<testing::tuple<int, bool>> Canny_Modes;
|
||||
|
||||
TEST_P(Canny_Modes, accuracy)
|
||||
{
|
||||
const int aperture = get<0>(GetParam());
|
||||
const bool trueGradient = get<1>(GetParam());
|
||||
const double range = aperture == 3 ? 300. : 1000.;
|
||||
RNG & rng = TS::ptr()->get_rng();
|
||||
|
||||
for (int ITER = 0; ITER < 20; ++ITER)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("iteration %d", ITER));
|
||||
|
||||
const std::string fname = cvtest::findDataFile("shared/fruits.png");
|
||||
const Mat original = cv::imread(fname, IMREAD_GRAYSCALE);
|
||||
|
||||
const double thresh1 = rng.uniform(0., range);
|
||||
const double thresh2 = rng.uniform(0., range * 0.3);
|
||||
const Size sz(rng.uniform(127, 800), rng.uniform(127, 600));
|
||||
const Size osz = original.size();
|
||||
|
||||
// preparation
|
||||
Mat img;
|
||||
if (sz.width >= osz.width || sz.height >= osz.height)
|
||||
{
|
||||
// larger image -> scale
|
||||
resize(original, img, sz, 0, 0, INTER_LINEAR_EXACT);
|
||||
}
|
||||
else
|
||||
{
|
||||
// smaller image -> crop
|
||||
Point origin(rng.uniform(0, osz.width - sz.width), rng.uniform(0, osz.height - sz.height));
|
||||
Rect roi(origin, sz);
|
||||
original(roi).copyTo(img);
|
||||
}
|
||||
GaussianBlur(img, img, Size(5, 5), 0);
|
||||
|
||||
// regular function
|
||||
Mat result;
|
||||
{
|
||||
cv::Canny(img, result, thresh1, thresh2, aperture, trueGradient);
|
||||
}
|
||||
|
||||
// custom derivatives
|
||||
Mat customResult;
|
||||
{
|
||||
Mat dxkernel = cvtest::calcSobelKernel2D(1, 0, aperture, 0);
|
||||
Mat dykernel = cvtest::calcSobelKernel2D(0, 1, aperture, 0);
|
||||
Point anchor(aperture / 2, aperture / 2);
|
||||
cv::Mat dx, dy;
|
||||
cvtest::filter2D(img, dx, CV_16S, dxkernel, anchor, 0, BORDER_REPLICATE);
|
||||
cvtest::filter2D(img, dy, CV_16S, dykernel, anchor, 0, BORDER_REPLICATE);
|
||||
cv::Canny(dx, dy, customResult, thresh1, thresh2, trueGradient);
|
||||
}
|
||||
|
||||
Mat reference;
|
||||
Canny_reference(img, reference, thresh1, thresh2, aperture, trueGradient);
|
||||
|
||||
EXPECT_MAT_NEAR(result, reference, 0);
|
||||
EXPECT_MAT_NEAR(customResult, reference, 0);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Canny_Modes,
|
||||
testing::Combine(
|
||||
testing::Values(3, 5),
|
||||
testing::Values(true, false)));
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,799 @@
|
||||
/*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_ConnectedComponentsTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ConnectedComponentsTest();
|
||||
~CV_ConnectedComponentsTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_ConnectedComponentsTest::CV_ConnectedComponentsTest() {}
|
||||
CV_ConnectedComponentsTest::~CV_ConnectedComponentsTest() {}
|
||||
|
||||
// This function force a row major order for the labels
|
||||
void normalizeLabels(Mat1i& imgLabels, int iNumLabels) {
|
||||
vector<int> vecNewLabels(iNumLabels + 1, 0);
|
||||
int iMaxNewLabel = 0;
|
||||
|
||||
for (int r = 0; r < imgLabels.rows; ++r) {
|
||||
for (int c = 0; c < imgLabels.cols; ++c) {
|
||||
int iCurLabel = imgLabels(r, c);
|
||||
if (iCurLabel > 0) {
|
||||
if (vecNewLabels[iCurLabel] == 0) {
|
||||
vecNewLabels[iCurLabel] = ++iMaxNewLabel;
|
||||
}
|
||||
imgLabels(r, c) = vecNewLabels[iCurLabel];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CV_ConnectedComponentsTest::run(int /* start_from */)
|
||||
{
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
string exp_path = string(ts->get_data_path()) + "connectedcomponents/ccomp_exp.png";
|
||||
Mat exp = imread(exp_path, IMREAD_GRAYSCALE);
|
||||
Mat orig = imread(string(ts->get_data_path()) + "connectedcomponents/concentric_circles.png", 0);
|
||||
|
||||
if (orig.empty())
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
Mat bw = orig > 128;
|
||||
|
||||
for (uint cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt)
|
||||
{
|
||||
|
||||
Mat1i labelImage;
|
||||
int nLabels = connectedComponents(bw, labelImage, 8, CV_32S, ccltype[cclt]);
|
||||
|
||||
normalizeLabels(labelImage, nLabels);
|
||||
|
||||
// Validate test results
|
||||
for (int r = 0; r < labelImage.rows; ++r) {
|
||||
for (int c = 0; c < labelImage.cols; ++c) {
|
||||
int l = labelImage.at<int>(r, c);
|
||||
bool pass = l >= 0 && l <= nLabels;
|
||||
if (!pass) {
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exp.empty() || orig.size() != exp.size())
|
||||
{
|
||||
imwrite(exp_path, labelImage);
|
||||
exp = labelImage;
|
||||
}
|
||||
|
||||
if (0 != cvtest::norm(labelImage > 0, exp > 0, NORM_INF))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
if (nLabels != cvtest::norm(labelImage, NORM_INF) + 1)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, regression) { CV_ConnectedComponentsTest test; test.safe_run(); }
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, grana_buffer_overflow)
|
||||
{
|
||||
cv::Mat darkMask;
|
||||
darkMask.create(31, 87, CV_8U);
|
||||
darkMask = 0;
|
||||
|
||||
cv::Mat labels;
|
||||
cv::Mat stats;
|
||||
cv::Mat centroids;
|
||||
|
||||
int nbComponents = cv::connectedComponentsWithStats(darkMask, labels, stats, centroids, 8, CV_32S, cv::CCL_GRANA);
|
||||
EXPECT_EQ(1, nbComponents);
|
||||
}
|
||||
|
||||
static cv::Mat createCrashMat(int numThreads) {
|
||||
const int h = numThreads * 4 * 2 + 8;
|
||||
const double nParallelStripes = std::max(1, std::min(h / 2, numThreads * 4));
|
||||
const int w = 4;
|
||||
|
||||
const int nstripes = cvRound(nParallelStripes <= 0 ? h : MIN(MAX(nParallelStripes, 1.), h));
|
||||
const cv::Range stripeRange(0, nstripes);
|
||||
const cv::Range wholeRange(0, h);
|
||||
|
||||
cv::Mat m(h, w, CV_8U);
|
||||
m = 0;
|
||||
|
||||
// Look for a range that starts with odd value and ends with even value
|
||||
cv::Range bugRange;
|
||||
for (int s = stripeRange.start; s < stripeRange.end; s++) {
|
||||
cv::Range sr(s, s + 1);
|
||||
cv::Range r;
|
||||
r.start = (int)(wholeRange.start +
|
||||
((uint64)sr.start * (wholeRange.end - wholeRange.start) + nstripes / 2) / nstripes);
|
||||
r.end = sr.end >= nstripes ?
|
||||
wholeRange.end :
|
||||
(int)(wholeRange.start +
|
||||
((uint64)sr.end * (wholeRange.end - wholeRange.start) + nstripes / 2) / nstripes);
|
||||
|
||||
if (r.start > 0 && r.start % 2 == 1 && r.end % 2 == 0 && r.end >= r.start + 2) {
|
||||
bugRange = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bugRange.empty()) { // Could not create a buggy range
|
||||
return m;
|
||||
}
|
||||
|
||||
// Fill in bug Range
|
||||
for (int x = 1; x < w; x++) {
|
||||
m.at<char>(bugRange.start - 1, x) = 1;
|
||||
}
|
||||
|
||||
m.at<char>(bugRange.start + 0, 0) = 1;
|
||||
m.at<char>(bugRange.start + 0, 1) = 1;
|
||||
m.at<char>(bugRange.start + 0, 3) = 1;
|
||||
m.at<char>(bugRange.start + 1, 1) = 1;
|
||||
m.at<char>(bugRange.start + 2, 1) = 1;
|
||||
m.at<char>(bugRange.start + 2, 3) = 1;
|
||||
m.at<char>(bugRange.start + 3, 0) = 1;
|
||||
m.at<char>(bugRange.start + 3, 1) = 1;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, parallel_wu_labels)
|
||||
{
|
||||
cv::Mat mat = createCrashMat(cv::getNumThreads());
|
||||
if (mat.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int nbPixels = cv::countNonZero(mat);
|
||||
|
||||
cv::Mat labels;
|
||||
cv::Mat stats;
|
||||
cv::Mat centroids;
|
||||
int nb = 0;
|
||||
EXPECT_NO_THROW(nb = cv::connectedComponentsWithStats(mat, labels, stats, centroids, 8, CV_32S, cv::CCL_WU));
|
||||
|
||||
int area = 0;
|
||||
for (int i = 1; i < nb; ++i) {
|
||||
area += stats.at<int32_t>(i, cv::CC_STAT_AREA);
|
||||
}
|
||||
|
||||
EXPECT_EQ(nbPixels, area);
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, missing_background_pixels)
|
||||
{
|
||||
cv::Mat m = Mat::ones(10, 10, CV_8U);
|
||||
cv::Mat labels;
|
||||
cv::Mat stats;
|
||||
cv::Mat centroids;
|
||||
EXPECT_NO_THROW(cv::connectedComponentsWithStats(m, labels, stats, centroids, 8, CV_32S, cv::CCL_WU));
|
||||
EXPECT_EQ(stats.at<int32_t>(0, cv::CC_STAT_WIDTH), 0);
|
||||
EXPECT_EQ(stats.at<int32_t>(0, cv::CC_STAT_HEIGHT), 0);
|
||||
EXPECT_EQ(stats.at<int32_t>(0, cv::CC_STAT_LEFT), -1);
|
||||
EXPECT_TRUE(std::isnan(centroids.at<double>(0, 0)));
|
||||
EXPECT_TRUE(std::isnan(centroids.at<double>(0, 1)));
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, spaghetti_bbdt_sauf_stats)
|
||||
{
|
||||
cv::Mat1b img({16, 16}, { (unsigned char)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1,
|
||||
0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1,
|
||||
0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||
});
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat1i stats;
|
||||
cv::Mat1d centroids;
|
||||
|
||||
int ccltype[] = { cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
for (uint cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(cv::connectedComponentsWithStats(img, labels, stats, centroids, 8, CV_32S, ccltype[cclt]));
|
||||
EXPECT_EQ(stats(0, cv::CC_STAT_LEFT), 0);
|
||||
EXPECT_EQ(stats(0, cv::CC_STAT_TOP), 0);
|
||||
EXPECT_EQ(stats(0, cv::CC_STAT_WIDTH), 16);
|
||||
EXPECT_EQ(stats(0, cv::CC_STAT_HEIGHT), 15);
|
||||
EXPECT_EQ(stats(0, cv::CC_STAT_AREA), 144);
|
||||
|
||||
EXPECT_EQ(stats(1, cv::CC_STAT_LEFT), 1);
|
||||
EXPECT_EQ(stats(1, cv::CC_STAT_TOP), 1);
|
||||
EXPECT_EQ(stats(1, cv::CC_STAT_WIDTH), 3);
|
||||
EXPECT_EQ(stats(1, cv::CC_STAT_HEIGHT), 3);
|
||||
EXPECT_EQ(stats(1, cv::CC_STAT_AREA), 9);
|
||||
|
||||
EXPECT_EQ(stats(2, cv::CC_STAT_LEFT), 1);
|
||||
EXPECT_EQ(stats(2, cv::CC_STAT_TOP), 1);
|
||||
EXPECT_EQ(stats(2, cv::CC_STAT_WIDTH), 8);
|
||||
EXPECT_EQ(stats(2, cv::CC_STAT_HEIGHT), 7);
|
||||
EXPECT_EQ(stats(2, cv::CC_STAT_AREA), 40);
|
||||
|
||||
EXPECT_EQ(stats(3, cv::CC_STAT_LEFT), 10);
|
||||
EXPECT_EQ(stats(3, cv::CC_STAT_TOP), 2);
|
||||
EXPECT_EQ(stats(3, cv::CC_STAT_WIDTH), 5);
|
||||
EXPECT_EQ(stats(3, cv::CC_STAT_HEIGHT), 2);
|
||||
EXPECT_EQ(stats(3, cv::CC_STAT_AREA), 8);
|
||||
|
||||
EXPECT_EQ(stats(4, cv::CC_STAT_LEFT), 11);
|
||||
EXPECT_EQ(stats(4, cv::CC_STAT_TOP), 5);
|
||||
EXPECT_EQ(stats(4, cv::CC_STAT_WIDTH), 3);
|
||||
EXPECT_EQ(stats(4, cv::CC_STAT_HEIGHT), 3);
|
||||
EXPECT_EQ(stats(4, cv::CC_STAT_AREA), 9);
|
||||
|
||||
EXPECT_EQ(stats(5, cv::CC_STAT_LEFT), 2);
|
||||
EXPECT_EQ(stats(5, cv::CC_STAT_TOP), 9);
|
||||
EXPECT_EQ(stats(5, cv::CC_STAT_WIDTH), 1);
|
||||
EXPECT_EQ(stats(5, cv::CC_STAT_HEIGHT), 1);
|
||||
EXPECT_EQ(stats(5, cv::CC_STAT_AREA), 1);
|
||||
|
||||
EXPECT_EQ(stats(6, cv::CC_STAT_LEFT), 12);
|
||||
EXPECT_EQ(stats(6, cv::CC_STAT_TOP), 9);
|
||||
EXPECT_EQ(stats(6, cv::CC_STAT_WIDTH), 1);
|
||||
EXPECT_EQ(stats(6, cv::CC_STAT_HEIGHT), 1);
|
||||
EXPECT_EQ(stats(6, cv::CC_STAT_AREA), 1);
|
||||
|
||||
// Labels' order could be different!
|
||||
if (cclt == cv::CCL_WU || cclt == cv::CCL_SAUF) {
|
||||
// CCL_SAUF, CCL_WU
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_LEFT), 1);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_TOP), 11);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_WIDTH), 4);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_HEIGHT), 2);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_AREA), 8);
|
||||
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_LEFT), 6);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_TOP), 10);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_WIDTH), 4);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_HEIGHT), 2);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_AREA), 8);
|
||||
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_LEFT), 0);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_TOP), 10);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_WIDTH), 16);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_HEIGHT), 6);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_AREA), 21);
|
||||
}
|
||||
else {
|
||||
// CCL_BBDT, CCL_GRANA, CCL_SPAGHETTI, CCL_BOLELLI
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_LEFT), 1);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_TOP), 11);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_WIDTH), 4);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_HEIGHT), 2);
|
||||
EXPECT_EQ(stats(7, cv::CC_STAT_AREA), 8);
|
||||
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_LEFT), 6);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_TOP), 10);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_WIDTH), 4);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_HEIGHT), 2);
|
||||
EXPECT_EQ(stats(8, cv::CC_STAT_AREA), 8);
|
||||
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_LEFT), 0);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_TOP), 10);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_WIDTH), 16);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_HEIGHT), 6);
|
||||
EXPECT_EQ(stats(9, cv::CC_STAT_AREA), 21);
|
||||
}
|
||||
EXPECT_EQ(stats(10, cv::CC_STAT_LEFT), 9);
|
||||
EXPECT_EQ(stats(10, cv::CC_STAT_TOP), 12);
|
||||
EXPECT_EQ(stats(10, cv::CC_STAT_WIDTH), 5);
|
||||
EXPECT_EQ(stats(10, cv::CC_STAT_HEIGHT), 2);
|
||||
EXPECT_EQ(stats(10, cv::CC_STAT_AREA), 7);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, chessboard_even)
|
||||
{
|
||||
auto size = {16, 16};
|
||||
cv::Mat1b input(size, { (unsigned char)
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
|
||||
});
|
||||
cv::Mat1i output_8c(size, {
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
|
||||
});
|
||||
cv::Mat1i output_4c(size, {
|
||||
1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0,
|
||||
0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16,
|
||||
17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0,
|
||||
0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32,
|
||||
33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0,
|
||||
0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48,
|
||||
49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0,
|
||||
0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64,
|
||||
65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, 72, 0,
|
||||
0, 73, 0, 74, 0, 75, 0, 76, 0, 77, 0, 78, 0, 79, 0, 80,
|
||||
81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0,
|
||||
0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96,
|
||||
97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0,
|
||||
0, 105, 0, 106, 0, 107, 0, 108, 0, 109, 0, 110, 0, 111, 0, 112,
|
||||
113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0, 119, 0, 120, 0,
|
||||
0, 121, 0, 122, 0, 123, 0, 124, 0, 125, 0, 126, 0, 127, 0, 128
|
||||
});
|
||||
|
||||
// Chessboard image with even number of rows and cols
|
||||
// Note that this is the maximum number of labels for 4-way connectivity
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat diff;
|
||||
int nLabels = 0;
|
||||
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 8, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_8c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 4, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_4c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, chessboard_odd)
|
||||
{
|
||||
auto size = {15, 15};
|
||||
cv::Mat1b input(size, { (unsigned char)
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
|
||||
});
|
||||
cv::Mat1i output_8c(size, {
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
|
||||
});
|
||||
cv::Mat1i output_4c(size, {
|
||||
1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
|
||||
0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0,
|
||||
16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23,
|
||||
0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0,
|
||||
31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38,
|
||||
0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0,
|
||||
46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53,
|
||||
0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0,
|
||||
61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68,
|
||||
0, 69, 0, 70, 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0,
|
||||
76, 0, 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83,
|
||||
0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0,
|
||||
91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98,
|
||||
0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 105, 0,
|
||||
106, 0, 107, 0, 108, 0, 109, 0, 110, 0, 111, 0, 112, 0, 113
|
||||
});
|
||||
|
||||
// Chessboard image with odd number of rows and cols
|
||||
// Note that this is the maximum number of labels for 4-way connectivity
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat diff;
|
||||
int nLabels = 0;
|
||||
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 8, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_8c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 4, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_4c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, maxlabels_8conn_even)
|
||||
{
|
||||
auto size = {16, 16};
|
||||
cv::Mat1b input(size, { (unsigned char)
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
});
|
||||
cv::Mat1i output_8c(size, {
|
||||
1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
});
|
||||
cv::Mat1i output_4c(size, {
|
||||
1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
});
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat diff;
|
||||
int nLabels = 0;
|
||||
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 8, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_8c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 4, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_4c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, maxlabels_8conn_odd)
|
||||
{
|
||||
auto size = {15, 15};
|
||||
cv::Mat1b input(size, { (unsigned char)
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
|
||||
});
|
||||
cv::Mat1i output_8c(size, {
|
||||
1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64
|
||||
});
|
||||
cv::Mat1i output_4c(size, {
|
||||
1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64
|
||||
});
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat diff;
|
||||
int nLabels = 0;
|
||||
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 8, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_8c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 4, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_4c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, single_row)
|
||||
{
|
||||
auto size = {1, 15};
|
||||
cv::Mat1b input(size, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
|
||||
cv::Mat1i output_8c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8});
|
||||
cv::Mat1i output_4c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8});
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat diff;
|
||||
int nLabels = 0;
|
||||
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 8, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_8c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 4, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_4c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, single_column)
|
||||
{
|
||||
auto size = {15, 1};
|
||||
cv::Mat1b input(size, {(unsigned char)1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
|
||||
cv::Mat1i output_8c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8});
|
||||
cv::Mat1i output_4c(size, {1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8});
|
||||
|
||||
int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI, cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
|
||||
|
||||
cv::Mat1i labels;
|
||||
cv::Mat diff;
|
||||
int nLabels = 0;
|
||||
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(int); ++cclt) {
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 8, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_8c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
|
||||
|
||||
EXPECT_NO_THROW(nLabels = cv::connectedComponents(input, labels, 4, CV_32S, ccltype[cclt]));
|
||||
normalizeLabels(labels, nLabels);
|
||||
|
||||
diff = labels != output_4c;
|
||||
EXPECT_EQ(cv::countNonZero(diff), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, 4conn_regression_21366)
|
||||
{
|
||||
Mat src = Mat::zeros(Size(10, 10), CV_8UC1);
|
||||
{
|
||||
Mat labels, stats, centroids;
|
||||
EXPECT_NO_THROW(cv::connectedComponentsWithStats(src, labels, stats, centroids, 4));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, regression_27568)
|
||||
{
|
||||
Mat image = Mat::zeros(Size(512, 512), CV_8UC1);
|
||||
for (int row = 0; row < image.rows; row += 2)
|
||||
{
|
||||
for (int col = 0; col < image.cols; col += 2)
|
||||
{
|
||||
image.at<uint8_t>(row, col) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (const int connectivity : {4, 8})
|
||||
{
|
||||
for (const int ccltype : {CCL_DEFAULT, CCL_WU, CCL_GRANA, CCL_BOLELLI, CCL_SAUF, CCL_BBDT, CCL_SPAGHETTI})
|
||||
{
|
||||
{
|
||||
Mat labels, stats, centroids;
|
||||
try
|
||||
{
|
||||
connectedComponentsWithStats(
|
||||
image, labels, stats, centroids, connectivity, CV_16U, ccltype);
|
||||
ADD_FAILURE();
|
||||
}
|
||||
catch (const Exception& exception)
|
||||
{
|
||||
EXPECT_TRUE(
|
||||
strstr(
|
||||
exception.what(),
|
||||
"Total number of labels overflowed label type. Try using CV_32S instead of CV_16U as ltype"));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Mat labels, stats, centroids;
|
||||
EXPECT_NO_THROW(
|
||||
connectedComponentsWithStats(
|
||||
image, labels, stats, centroids, connectivity, CV_32S, ccltype));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
@@ -0,0 +1,223 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//rotate/flip a quadrant appropriately
|
||||
static void rot(int n, int *x, int *y, int rx, int ry)
|
||||
{
|
||||
if (ry == 0) {
|
||||
if (rx == 1) {
|
||||
*x = n-1 - *x;
|
||||
*y = n-1 - *y;
|
||||
}
|
||||
|
||||
//Swap x and y
|
||||
int t = *x;
|
||||
*x = *y;
|
||||
*y = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void d2xy(int n, int d, int *x, int *y)
|
||||
{
|
||||
int rx, ry, s, t=d;
|
||||
*x = *y = 0;
|
||||
for (s=1; s<n; s*=2)
|
||||
{
|
||||
rx = 1 & (t/2);
|
||||
ry = 1 & (t ^ rx);
|
||||
rot(s, x, y, rx, ry);
|
||||
*x += s * rx;
|
||||
*y += s * ry;
|
||||
t /= 4;
|
||||
}
|
||||
}
|
||||
|
||||
static Mat draw_hilbert(int n = 64, int scale = 10)
|
||||
{
|
||||
int n2 = n*n, w = (n + 2)*scale;
|
||||
Point ofs(scale, scale);
|
||||
Mat img(w, w, CV_8U);
|
||||
img.setTo(Scalar::all(0));
|
||||
|
||||
Point p(0,0);
|
||||
for( int i = 0; i < n2; i++ )
|
||||
{
|
||||
Point q(0,0);
|
||||
d2xy(n2, i, &q.x, &q.y);
|
||||
line(img, p*scale + ofs, q*scale + ofs, Scalar::all(255));
|
||||
p = q;
|
||||
}
|
||||
dilate(img, img, Mat());
|
||||
return img;
|
||||
}
|
||||
|
||||
TEST(Imgproc_FindContours, hilbert)
|
||||
{
|
||||
Mat img = draw_hilbert();
|
||||
vector<vector<Point> > contours;
|
||||
|
||||
findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_NONE);
|
||||
ASSERT_EQ(1, (int)contours.size());
|
||||
ASSERT_EQ(78632, (int)contours[0].size());
|
||||
|
||||
findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE);
|
||||
ASSERT_EQ(1, (int)contours.size());
|
||||
ASSERT_EQ(9832, (int)contours[0].size());
|
||||
}
|
||||
|
||||
TEST(Imgproc_FindContours, border)
|
||||
{
|
||||
Mat img;
|
||||
cv::copyMakeBorder(Mat::zeros(8, 10, CV_8U), img, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(1));
|
||||
|
||||
std::vector<std::vector<cv::Point> > contours;
|
||||
findContours(img, contours, RETR_LIST, CHAIN_APPROX_NONE);
|
||||
|
||||
Mat img_draw_contours = Mat::zeros(img.size(), CV_8U);
|
||||
for (size_t cpt = 0; cpt < contours.size(); cpt++)
|
||||
{
|
||||
drawContours(img_draw_contours, contours, static_cast<int>(cpt), cv::Scalar(1));
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, cvtest::norm(img, img_draw_contours, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_FindContours, regression_4363_shared_nbd)
|
||||
{
|
||||
// Create specific test image
|
||||
Mat1b img(12, 69, (const uchar&)0);
|
||||
|
||||
img(1, 1) = 1;
|
||||
|
||||
// Vertical rectangle with hole sharing the same NBD
|
||||
for (int r = 1; r <= 10; ++r) {
|
||||
for (int c = 3; c <= 5; ++c) {
|
||||
img(r, c) = 1;
|
||||
}
|
||||
}
|
||||
img(9, 4) = 0;
|
||||
|
||||
// 124 small CCs
|
||||
for (int r = 1; r <= 7; r += 2) {
|
||||
for (int c = 7; c <= 67; c += 2) {
|
||||
img(r, c) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Last CC
|
||||
img(9, 7) = 1;
|
||||
|
||||
vector< vector<Point> > contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
|
||||
|
||||
bool found = false;
|
||||
size_t index = 0;
|
||||
for (vector< vector<Point> >::const_iterator i = contours.begin(); i != contours.end(); ++i)
|
||||
{
|
||||
const vector<Point>& c = *i;
|
||||
if (!c.empty() && c[0] == Point(7, 9))
|
||||
{
|
||||
found = true;
|
||||
index = (size_t)(i - contours.begin());
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(found) << "Desired result: point (7,9) is a contour - Actual result: point (7,9) is not a contour";
|
||||
|
||||
if (found)
|
||||
{
|
||||
ASSERT_EQ(contours.size(), hierarchy.size());
|
||||
EXPECT_LT(hierarchy[index][3], 0) << "Desired result: (7,9) has no parent - Actual result: parent of (7,9) is another contour. index = " << index;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_DrawContours, regression_26264)
|
||||
{
|
||||
Mat img = draw_hilbert(32);
|
||||
img.push_back(~img);
|
||||
|
||||
for (int i = 50; i < 200; i += 17)
|
||||
{
|
||||
rectangle(img, Rect(i, i, img.cols - (i*2), img.rows - (i*2)), Scalar(0), 7);
|
||||
rectangle(img, Rect(i, i, img.cols - (i*2), img.rows - (i*2)), Scalar(255), 1);
|
||||
}
|
||||
|
||||
vector<vector<Point> > contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
|
||||
img.setTo(Scalar::all(0));
|
||||
Mat img1 = img.clone();
|
||||
Mat img2 = img.clone();
|
||||
Mat img3 = img.clone();
|
||||
|
||||
int idx = 0;
|
||||
while (idx >= 0)
|
||||
{
|
||||
drawContours(img, contours, idx, Scalar::all(255), FILLED, LINE_8, hierarchy);
|
||||
drawContours(img2, contours, idx, Scalar::all(255), 1, LINE_8, hierarchy);
|
||||
idx = hierarchy[idx][0];
|
||||
}
|
||||
|
||||
drawContours(img1, contours, -1, Scalar::all(255), FILLED, LINE_8, hierarchy);
|
||||
drawContours(img3, contours, -1, Scalar::all(255), 1, LINE_8, hierarchy);
|
||||
ASSERT_EQ(0, cvtest::norm(img, img1, NORM_INF));
|
||||
ASSERT_EQ(0, cvtest::norm(img2, img3, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_DrawContours, MatListOfMatIntScalarInt)
|
||||
{
|
||||
Mat gray0 = Mat::zeros(10, 10, CV_8U);
|
||||
rectangle(gray0, Point(1, 2), Point(7, 8), Scalar(100));
|
||||
vector<Mat> contours;
|
||||
findContours(gray0, contours, noArray(), RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
|
||||
drawContours(gray0, contours, -1, Scalar(0), FILLED);
|
||||
int nz = countNonZero(gray0);
|
||||
EXPECT_EQ(nz, 0);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,485 @@
|
||||
// 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"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
// debug function
|
||||
template <typename T>
|
||||
inline static void print_pts(const T& c)
|
||||
{
|
||||
for (const auto& one_pt : c)
|
||||
{
|
||||
cout << one_pt << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// debug function
|
||||
template <typename T>
|
||||
inline static void print_pts_2(vector<T>& cs)
|
||||
{
|
||||
int cnt = 0;
|
||||
cout << "Contours:" << endl;
|
||||
for (const auto& one_c : cs)
|
||||
{
|
||||
cout << cnt++ << " : ";
|
||||
print_pts(one_c);
|
||||
}
|
||||
};
|
||||
|
||||
// draw 1-2 px blob with orientation defined by 'kind'
|
||||
template <typename T>
|
||||
inline static void drawSmallContour(Mat& img, Point pt, int kind, int color_)
|
||||
{
|
||||
const T color = static_cast<T>(color_);
|
||||
img.at<T>(pt) = color;
|
||||
switch (kind)
|
||||
{
|
||||
case 1: img.at<T>(pt + Point(1, 0)) = color; break;
|
||||
case 2: img.at<T>(pt + Point(1, -1)) = color; break;
|
||||
case 3: img.at<T>(pt + Point(0, -1)) = color; break;
|
||||
case 4: img.at<T>(pt + Point(-1, -1)) = color; break;
|
||||
case 5: img.at<T>(pt + Point(-1, 0)) = color; break;
|
||||
case 6: img.at<T>(pt + Point(-1, 1)) = color; break;
|
||||
case 7: img.at<T>(pt + Point(0, 1)) = color; break;
|
||||
case 8: img.at<T>(pt + Point(1, 1)) = color; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void drawContours(Mat& img,
|
||||
const vector<vector<Point>>& contours,
|
||||
const Scalar& color = Scalar::all(255))
|
||||
{
|
||||
for (const auto& contour : contours)
|
||||
{
|
||||
for (size_t n = 0, end = contour.size(); n < end; ++n)
|
||||
{
|
||||
size_t m = n + 1;
|
||||
if (n == end - 1)
|
||||
m = 0;
|
||||
line(img, contour[m], contour[n], color, 1, LINE_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
// Test parameters - mode + method
|
||||
typedef testing::TestWithParam<tuple<int, int>> Imgproc_FindContours_Modes1;
|
||||
|
||||
|
||||
// Draw random rectangle and find contours
|
||||
//
|
||||
TEST_P(Imgproc_FindContours_Modes1, rectangle)
|
||||
{
|
||||
const int mode = get<0>(GetParam());
|
||||
const int method = get<1>(GetParam());
|
||||
|
||||
const size_t ITER = 100;
|
||||
RNG rng = TS::ptr()->get_rng();
|
||||
|
||||
for (size_t i = 0; i < ITER; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%zu", i));
|
||||
const Size sz(rng.uniform(640, 1920), rng.uniform(480, 1080));
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
Mat img32s(sz, CV_32SC1, Scalar::all(0));
|
||||
const Rect r(Point(rng.uniform(1, sz.width / 2 - 1), rng.uniform(1, sz.height / 2)),
|
||||
Point(rng.uniform(sz.width / 2 - 1, sz.width - 1),
|
||||
rng.uniform(sz.height / 2 - 1, sz.height - 1)));
|
||||
rectangle(img, r, Scalar::all(255));
|
||||
rectangle(img32s, r, Scalar::all(255), FILLED);
|
||||
|
||||
const vector<Point> ext_ref {r.tl(),
|
||||
r.tl() + Point(0, r.height - 1),
|
||||
r.br() + Point(-1, -1),
|
||||
r.tl() + Point(r.width - 1, 0)};
|
||||
const vector<Point> int_ref {ext_ref[0] + Point(0, 1),
|
||||
ext_ref[0] + Point(1, 0),
|
||||
ext_ref[3] + Point(-1, 0),
|
||||
ext_ref[3] + Point(0, 1),
|
||||
ext_ref[2] + Point(0, -1),
|
||||
ext_ref[2] + Point(-1, 0),
|
||||
ext_ref[1] + Point(1, 0),
|
||||
ext_ref[1] + Point(0, -1)};
|
||||
const size_t ext_perimeter = r.width * 2 + r.height * 2;
|
||||
const size_t int_perimeter = ext_perimeter - 4;
|
||||
|
||||
vector<vector<Point>> contours;
|
||||
vector<vector<schar>> chains;
|
||||
vector<Vec4i> hierarchy;
|
||||
|
||||
// run functionn
|
||||
if (mode == RETR_FLOODFILL)
|
||||
if (method == 0)
|
||||
findContours(img32s, chains, hierarchy, mode, method);
|
||||
else
|
||||
findContours(img32s, contours, hierarchy, mode, method);
|
||||
else if (method == 0)
|
||||
findContours(img, chains, hierarchy, mode, method);
|
||||
else
|
||||
findContours(img, contours, hierarchy, mode, method);
|
||||
|
||||
// verify results
|
||||
if (mode == RETR_EXTERNAL)
|
||||
{
|
||||
if (method == 0)
|
||||
{
|
||||
ASSERT_EQ(1U, chains.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQ(1U, contours.size());
|
||||
if (method == CHAIN_APPROX_NONE)
|
||||
{
|
||||
EXPECT_EQ(int_perimeter, contours[0].size());
|
||||
}
|
||||
else if (method == CHAIN_APPROX_SIMPLE)
|
||||
{
|
||||
EXPECT_MAT_NEAR(Mat(ext_ref), Mat(contours[0]), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (method == 0)
|
||||
{
|
||||
ASSERT_EQ(2U, chains.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQ(2U, contours.size());
|
||||
if (mode == RETR_LIST)
|
||||
{
|
||||
if (method == CHAIN_APPROX_NONE)
|
||||
{
|
||||
EXPECT_EQ(int_perimeter - 4, contours[0].size());
|
||||
EXPECT_EQ(int_perimeter, contours[1].size());
|
||||
}
|
||||
else if (method == CHAIN_APPROX_SIMPLE)
|
||||
{
|
||||
EXPECT_MAT_NEAR(Mat(int_ref), Mat(contours[0]), 0);
|
||||
EXPECT_MAT_NEAR(Mat(ext_ref), Mat(contours[1]), 0);
|
||||
}
|
||||
}
|
||||
else if (mode == RETR_CCOMP || mode == RETR_TREE)
|
||||
{
|
||||
if (method == CHAIN_APPROX_NONE)
|
||||
{
|
||||
EXPECT_EQ(int_perimeter, contours[0].size());
|
||||
EXPECT_EQ(int_perimeter - 4, contours[1].size());
|
||||
}
|
||||
else if (method == CHAIN_APPROX_SIMPLE)
|
||||
{
|
||||
EXPECT_MAT_NEAR(Mat(ext_ref), Mat(contours[0]), 0);
|
||||
EXPECT_MAT_NEAR(Mat(int_ref), Mat(contours[1]), 0);
|
||||
}
|
||||
}
|
||||
else if (mode == RETR_FLOODFILL)
|
||||
{
|
||||
if (method == CHAIN_APPROX_NONE)
|
||||
{
|
||||
EXPECT_EQ(int_perimeter + 4, contours[0].size());
|
||||
}
|
||||
else if (method == CHAIN_APPROX_SIMPLE)
|
||||
{
|
||||
EXPECT_EQ(int_ref.size(), contours[0].size());
|
||||
EXPECT_MAT_NEAR(Mat(ext_ref), Mat(contours[1]), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Draw many small 1-2px blobs and find contours
|
||||
//
|
||||
TEST_P(Imgproc_FindContours_Modes1, small)
|
||||
{
|
||||
const int mode = get<0>(GetParam());
|
||||
const int method = get<1>(GetParam());
|
||||
|
||||
const size_t DIM = 1000;
|
||||
const Size sz(DIM, DIM);
|
||||
const int num = (DIM / 10) * (DIM / 10); // number of 10x10 squares
|
||||
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
Mat img32s(sz, CV_32SC1, Scalar::all(0));
|
||||
vector<Point> pts;
|
||||
int extra_contours_32s = 0;
|
||||
for (int j = 0; j < num; ++j)
|
||||
{
|
||||
const int kind = j % 9;
|
||||
Point pt {(j % 100) * 10 + 4, (j / 100) * 10 + 4};
|
||||
drawSmallContour<uchar>(img, pt, kind, 255);
|
||||
drawSmallContour<int>(img32s, pt, kind, j + 1);
|
||||
pts.push_back(pt);
|
||||
// NOTE: for some reason these small diagonal contours (NW, SE)
|
||||
// result in 2 external contours for FLOODFILL mode
|
||||
if (kind == 8 || kind == 4)
|
||||
++extra_contours_32s;
|
||||
}
|
||||
{
|
||||
vector<vector<Point>> contours;
|
||||
vector<vector<schar>> chains;
|
||||
vector<Vec4i> hierarchy;
|
||||
|
||||
if (mode == RETR_FLOODFILL)
|
||||
{
|
||||
if (method == 0)
|
||||
{
|
||||
findContours(img32s, chains, hierarchy, mode, method);
|
||||
ASSERT_EQ(pts.size() * 2 + extra_contours_32s, chains.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
findContours(img32s, contours, hierarchy, mode, method);
|
||||
ASSERT_EQ(pts.size() * 2 + extra_contours_32s, contours.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (method == 0)
|
||||
{
|
||||
findContours(img, chains, hierarchy, mode, method);
|
||||
ASSERT_EQ(pts.size(), chains.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
findContours(img, contours, hierarchy, mode, method);
|
||||
ASSERT_EQ(pts.size(), contours.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Draw many nested rectangles and find contours
|
||||
//
|
||||
TEST_P(Imgproc_FindContours_Modes1, deep)
|
||||
{
|
||||
const int mode = get<0>(GetParam());
|
||||
const int method = get<1>(GetParam());
|
||||
|
||||
const size_t DIM = 1000;
|
||||
const Size sz(DIM, DIM);
|
||||
const size_t NUM = 249U;
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
Mat img32s(sz, CV_32SC1, Scalar::all(0));
|
||||
Rect rect(1, 1, 998, 998);
|
||||
for (size_t i = 0; i < NUM; ++i)
|
||||
{
|
||||
rectangle(img, rect, Scalar::all(255));
|
||||
rectangle(img32s, rect, Scalar::all((double)i + 1), FILLED);
|
||||
rect.x += 2;
|
||||
rect.y += 2;
|
||||
rect.width -= 4;
|
||||
rect.height -= 4;
|
||||
}
|
||||
{
|
||||
vector<vector<Point>> contours {{{0, 0}, {1, 1}}};
|
||||
vector<vector<schar>> chains {{1, 2, 3}};
|
||||
vector<Vec4i> hierarchy;
|
||||
|
||||
if (mode == RETR_FLOODFILL)
|
||||
{
|
||||
if (method == 0)
|
||||
{
|
||||
findContours(img32s, chains, hierarchy, mode, method);
|
||||
ASSERT_EQ(2 * NUM, chains.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
findContours(img32s, contours, hierarchy, mode, method);
|
||||
ASSERT_EQ(2 * NUM, contours.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t expected_count = (mode == RETR_EXTERNAL) ? 1U : 2 * NUM;
|
||||
if (method == 0)
|
||||
{
|
||||
findContours(img, chains, hierarchy, mode, method);
|
||||
ASSERT_EQ(expected_count, chains.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
findContours(img, contours, hierarchy, mode, method);
|
||||
ASSERT_EQ(expected_count, contours.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
,
|
||||
Imgproc_FindContours_Modes1,
|
||||
testing::Combine(
|
||||
testing::Values(RETR_EXTERNAL, RETR_LIST, RETR_CCOMP, RETR_TREE, RETR_FLOODFILL),
|
||||
testing::Values(0,
|
||||
CHAIN_APPROX_NONE,
|
||||
CHAIN_APPROX_SIMPLE,
|
||||
CHAIN_APPROX_TC89_L1,
|
||||
CHAIN_APPROX_TC89_KCOS)));
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
typedef testing::TestWithParam<tuple<int, int>> Imgproc_FindContours_Modes2;
|
||||
|
||||
// Very approximate backport of an old accuracy test
|
||||
//
|
||||
TEST_P(Imgproc_FindContours_Modes2, new_accuracy)
|
||||
{
|
||||
const int mode = get<0>(GetParam());
|
||||
const int method = get<1>(GetParam());
|
||||
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
const int blob_count = rng.uniform(1, 10);
|
||||
const Size sz(rng.uniform(640, 1920), rng.uniform(480, 1080));
|
||||
const int blob_sz = 50;
|
||||
|
||||
// prepare image
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
vector<RotatedRect> rects;
|
||||
for (int i = 0; i < blob_count; ++i)
|
||||
{
|
||||
const Point2f center((float)rng.uniform(blob_sz, sz.width - blob_sz),
|
||||
(float)rng.uniform(blob_sz, sz.height - blob_sz));
|
||||
const Size2f rsize((float)rng.uniform(1, blob_sz), (float)rng.uniform(1, blob_sz));
|
||||
RotatedRect rect(center, rsize, rng.uniform(0.f, 180.f));
|
||||
rects.push_back(rect);
|
||||
ellipse(img, rect, Scalar::all(100), FILLED);
|
||||
}
|
||||
|
||||
// draw contours manually
|
||||
Mat cont_img(sz, CV_8UC1, Scalar::all(0));
|
||||
for (int y = 1; y < sz.height - 1; ++y)
|
||||
{
|
||||
for (int x = 1; x < sz.width - 1; ++x)
|
||||
{
|
||||
if (img.at<uchar>(y, x) != 0 &&
|
||||
((img.at<uchar>(y - 1, x) == 0) || (img.at<uchar>(y + 1, x) == 0) ||
|
||||
(img.at<uchar>(y, x + 1) == 0) || (img.at<uchar>(y, x - 1) == 0)))
|
||||
{
|
||||
cont_img.at<uchar>(y, x) = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find contours
|
||||
vector<vector<Point>> contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(img, contours, hierarchy, mode, method);
|
||||
|
||||
// 0 < contours <= rects
|
||||
EXPECT_GT(contours.size(), 0U);
|
||||
EXPECT_GE(rects.size(), contours.size());
|
||||
|
||||
// draw contours
|
||||
Mat res_img(sz, CV_8UC1, Scalar::all(0));
|
||||
drawContours(res_img, contours);
|
||||
|
||||
// compare resulting drawn contours with manually drawn contours
|
||||
const double diff1 = cvtest::norm(cont_img, res_img, NORM_L1) / 255;
|
||||
|
||||
if (method == CHAIN_APPROX_NONE || method == CHAIN_APPROX_SIMPLE)
|
||||
{
|
||||
EXPECT_EQ(0., diff1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_FindContours_Modes2, approx)
|
||||
{
|
||||
const int mode = get<0>(GetParam());
|
||||
const int method = get<1>(GetParam());
|
||||
|
||||
const Size sz {500, 500};
|
||||
Mat img = Mat::zeros(sz, CV_8UC1);
|
||||
|
||||
for (int c = 0; c < 4; ++c)
|
||||
{
|
||||
if (c != 0)
|
||||
{
|
||||
// noise + filter + threshold
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
cvtest::randUni(rng, img, 0, 255);
|
||||
|
||||
Mat fimg;
|
||||
boxFilter(img, fimg, CV_8U, Size(5, 5));
|
||||
|
||||
Mat timg;
|
||||
const int level = 44 + c * 42;
|
||||
// 'level' goes through:
|
||||
// 86 - some black speckles on white
|
||||
// 128 - 50/50 black/white
|
||||
// 170 - some white speckles on black
|
||||
cv::threshold(fimg, timg, level, 255, THRESH_BINARY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// circle with cut
|
||||
const Point center {250, 250};
|
||||
const int r {20};
|
||||
const Point cut {r, r};
|
||||
circle(img, center, r, Scalar(255), FILLED);
|
||||
rectangle(img, center, center + cut, Scalar(0), FILLED);
|
||||
}
|
||||
|
||||
vector<vector<Point>> contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(img, contours, hierarchy, mode, method);
|
||||
|
||||
// TODO: check something
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: offset test
|
||||
|
||||
// no RETR_FLOODFILL - no CV_32S input images
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
,
|
||||
Imgproc_FindContours_Modes2,
|
||||
testing::Combine(testing::Values(RETR_EXTERNAL, RETR_LIST, RETR_CCOMP, RETR_TREE),
|
||||
testing::Values(CHAIN_APPROX_NONE,
|
||||
CHAIN_APPROX_SIMPLE,
|
||||
CHAIN_APPROX_TC89_L1,
|
||||
CHAIN_APPROX_TC89_KCOS)));
|
||||
|
||||
TEST(Imgproc_FindContours, link_runs)
|
||||
{
|
||||
const Size sz {500, 500};
|
||||
Mat img = Mat::zeros(sz, CV_8UC1);
|
||||
|
||||
// noise + filter + threshold
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
cvtest::randUni(rng, img, 0, 255);
|
||||
|
||||
Mat fimg;
|
||||
boxFilter(img, fimg, CV_8U, Size(5, 5));
|
||||
|
||||
const int level = 135;
|
||||
cv::threshold(fimg, img, level, 255, THRESH_BINARY);
|
||||
|
||||
vector<vector<Point>> contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContoursLinkRuns(img, contours, hierarchy);
|
||||
|
||||
if (cvtest::debugLevel >= 10)
|
||||
{
|
||||
print_pts_2(contours);
|
||||
|
||||
Mat res = Mat::zeros(sz, CV_8UC1);
|
||||
drawContours(res, contours);
|
||||
imshow("res", res);
|
||||
imshow("img", img);
|
||||
waitKey(0);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace opencv_test
|
||||
@@ -0,0 +1,254 @@
|
||||
// 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"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//helps to temporarily change the number of threads and restore it back after the scope
|
||||
struct CvNThreadScope{
|
||||
int nprev;
|
||||
CvNThreadScope(int n){
|
||||
nprev=cv::getNumThreads();
|
||||
cv::setNumThreads(n);
|
||||
}
|
||||
~CvNThreadScope(){
|
||||
cv::setNumThreads(nprev);
|
||||
}
|
||||
};
|
||||
|
||||
// Order-independent contour-set comparison
|
||||
static bool trucoContoursMatch(const vector<vector<Point>>& cont1, const vector<vector<Point>>& cont2)
|
||||
{
|
||||
//order senstive hash
|
||||
auto Hash=[](const std::vector<cv::Point>& contour) {
|
||||
// FNV-1a 64-bit hash constants
|
||||
constexpr uint64_t FNV_OFFSET = 1469598103934665603ULL;
|
||||
constexpr uint64_t FNV_PRIME = 1099511628211ULL;
|
||||
|
||||
uint64_t hash = FNV_OFFSET;
|
||||
|
||||
// Mix in the size so that contours with different lengths
|
||||
// but same prefix produce different hashes
|
||||
uint64_t size = static_cast<uint64_t>(contour.size());
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
hash ^= (size >> (i * 8)) & 0xFF;
|
||||
hash *= FNV_PRIME;
|
||||
}
|
||||
|
||||
// Mix in each point's x and y coordinates byte by byte
|
||||
for (const cv::Point& p : contour) {
|
||||
uint32_t x = static_cast<uint32_t>(p.x);
|
||||
uint32_t y = static_cast<uint32_t>(p.y);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
hash ^= (x >> (i * 8)) & 0xFF;
|
||||
hash *= FNV_PRIME;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
hash ^= (y >> (i * 8)) & 0xFF;
|
||||
hash *= FNV_PRIME;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
std::set<uint64> hashes1,hashes2;
|
||||
for(auto &contour:cont1){
|
||||
hashes1.insert( Hash(contour));
|
||||
}
|
||||
for(auto &contour:cont2){
|
||||
hashes2.insert( Hash(contour));
|
||||
}
|
||||
|
||||
for(auto &h1:hashes1){//element in cont and not in cont2
|
||||
if( hashes2.find(h1) ==hashes2.end()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<ContourApproximationModes> Imgproc_FindTRUContours;
|
||||
|
||||
TEST_P(Imgproc_FindTRUContours, nthreads_consistency)
|
||||
{
|
||||
ContourApproximationModes method = GetParam();
|
||||
const Size sz(1000, 1000);
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
Mat noise(sz, CV_8UC1);
|
||||
cvtest::randUni(rng, noise, 0, 255);
|
||||
Mat blurred;
|
||||
boxFilter(noise, blurred, CV_8U, Size(5, 5));
|
||||
Mat img;
|
||||
cv::threshold(blurred, img, 128, 255, THRESH_BINARY);
|
||||
|
||||
vector<vector<Point>> ref_contours;
|
||||
vector<vector<Point>> ref_contours_m0;
|
||||
{
|
||||
CvNThreadScope nt(1);
|
||||
findContours(img, ref_contours, RETR_LIST, method);
|
||||
}
|
||||
|
||||
std::vector<int> thread_counts;
|
||||
for(int i=2;i<40;i++) thread_counts.push_back(i);
|
||||
for (int t : thread_counts)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("nthreads=%d method=%d", t, (int)method));
|
||||
CvNThreadScope nt(t);
|
||||
vector<vector<Point>> contours;
|
||||
findContours(img, contours, RETR_LIST, method); //will use TRUCO because NOT using hierarchy AND RETR_LIST
|
||||
auto match=trucoContoursMatch(ref_contours, contours);
|
||||
EXPECT_TRUE(match);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_FindTRUContours, circles_vs_standard)
|
||||
{
|
||||
ContourApproximationModes method = GetParam();
|
||||
const Size sz(4000, 4000);
|
||||
const int ITER = cvtest::debugLevel >= 10?100:10;
|
||||
const int NUM_CIRCLES = 250;
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
|
||||
for (int iter = 0; iter < ITER; ++iter)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("iter=%d method=%d", iter, (int)method));
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
for (int i = 0; i < NUM_CIRCLES; ++i)
|
||||
{
|
||||
Point center(rng.uniform(50, sz.width - 50),
|
||||
rng.uniform(50, sz.height - 50));
|
||||
int radius = rng.uniform(10, 150);
|
||||
circle(img, center, radius, Scalar::all(255), FILLED);
|
||||
}
|
||||
Mat binary;
|
||||
adaptiveThreshold(img, binary, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 11, 0);
|
||||
|
||||
vector<vector<Point>> ref_contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(binary, ref_contours, hierarchy, RETR_LIST, method); //will call suzuki abe because using hierarchy
|
||||
EXPECT_TRUE(!hierarchy.empty());
|
||||
vector<vector<Point>> truco_contours;
|
||||
findContours(binary, truco_contours, RETR_LIST, method);
|
||||
EXPECT_TRUE(trucoContoursMatch(ref_contours, truco_contours)); //will use TRUCO because NOT using hierarchy AND RETR_LIST
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_FindTRUContours, noise_threshold)
|
||||
{
|
||||
ContourApproximationModes method = GetParam();
|
||||
const Size sz(1500, 1500);
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
const int levels[] = {86, 128, 170};
|
||||
const int ITER = 2;
|
||||
|
||||
std::vector<int> thread_counts;
|
||||
for(int i=2; i<40; i+=3) thread_counts.push_back(i);
|
||||
for(int i=0; i<ITER; i++)
|
||||
{
|
||||
for (int level : levels)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("level=%d method=%d", level, (int)method));
|
||||
Mat noise(sz, CV_8UC1);
|
||||
cvtest::randUni(rng, noise, 0, 255);
|
||||
Mat blurred;
|
||||
boxFilter(noise, blurred, CV_8U, Size(5, 5));
|
||||
Mat binary;
|
||||
cv::threshold(blurred, binary, level, 255, THRESH_BINARY);
|
||||
|
||||
vector<vector<Point>> ref_contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(binary, ref_contours, hierarchy, RETR_LIST, method);//will call suzuki&abe because using hierarchy
|
||||
EXPECT_TRUE(!hierarchy.empty());
|
||||
for(auto nt: thread_counts){
|
||||
CvNThreadScope ts(nt);
|
||||
vector<vector<Point>> truco_contours;
|
||||
findContours(binary, truco_contours, RETR_LIST, method);//will call TRUCO abe because NOT using hierarchy
|
||||
EXPECT_TRUE(trucoContoursMatch(ref_contours, truco_contours));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_FindTRUContours, nested_rectangles)
|
||||
{
|
||||
ContourApproximationModes method = GetParam();
|
||||
const int DIM = 1500;
|
||||
const Size sz(DIM, DIM);
|
||||
const int NUM = 25;
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
Rect rect(1, 1, DIM - 2, DIM - 2);
|
||||
for (int i = 0; i < NUM; ++i)
|
||||
{
|
||||
rectangle(img, rect, Scalar::all(255));
|
||||
rect.x += 10;
|
||||
rect.y += 10;
|
||||
rect.width -= 20;
|
||||
rect.height -= 20;
|
||||
if (rect.width <= 0 || rect.height <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
vector<vector<Point>> ref_contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(img, ref_contours, hierarchy, RETR_LIST, method);//will call suzuki abe because using hierarchy
|
||||
EXPECT_TRUE(!hierarchy.empty());
|
||||
|
||||
vector<vector<Point>> truco_contours;
|
||||
findContours(img, truco_contours, RETR_LIST, method);//will use TRUCO because NOT using hierarchy AND RETR_LIST
|
||||
|
||||
EXPECT_TRUE(trucoContoursMatch(ref_contours, truco_contours));
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_FindTRUContours, mixed_figures)
|
||||
{
|
||||
ContourApproximationModes method = GetParam();
|
||||
const Size sz(1800, 1600);
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
const int ITER = cvtest::debugLevel >= 10?100:10;
|
||||
|
||||
|
||||
for (int iter = 0; iter < ITER; ++iter)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("iter=%d method=%d", iter, (int)method));
|
||||
Mat img(sz, CV_8UC1, Scalar::all(0));
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
Rect r(rng.uniform(10, sz.width / 2),
|
||||
rng.uniform(10, sz.height / 2),
|
||||
rng.uniform(20, 100),
|
||||
rng.uniform(20, 100));
|
||||
r &= Rect(0, 0, sz.width - 1, sz.height - 1);
|
||||
rectangle(img, r, Scalar::all(255), FILLED);
|
||||
}
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
Point center(rng.uniform(50, sz.width - 50),
|
||||
rng.uniform(50, sz.height - 50));
|
||||
int radius = rng.uniform(10, 50);
|
||||
circle(img, center, radius, Scalar::all(255), FILLED);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Point pts[3];
|
||||
for (auto& p : pts)
|
||||
p = Point(rng.uniform(10, sz.width - 10),
|
||||
rng.uniform(10, sz.height - 10));
|
||||
const Point* ppts = pts;
|
||||
int npts = 3;
|
||||
fillPoly(img, &ppts, &npts, 1, Scalar::all(255));
|
||||
}
|
||||
vector<vector<Point>> ref_contours;
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(img, ref_contours, hierarchy, RETR_LIST, method);//will call suzuki abe because using hierarchy
|
||||
EXPECT_TRUE(!hierarchy.empty());
|
||||
vector<vector<Point>> truco_contours;
|
||||
findContours(img, truco_contours, RETR_LIST, method);//will use TRUCO because NOT using hierarchy AND RETR_LIST
|
||||
|
||||
EXPECT_TRUE(trucoContoursMatch(ref_contours, truco_contours));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Imgproc, Imgproc_FindTRUContours,
|
||||
testing::Values(CHAIN_APPROX_NONE,CHAIN_APPROX_SIMPLE, CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS));
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,97 @@
|
||||
/*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-2023, 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(Imgproc_CornerSubPix, out_of_image_corners)
|
||||
{
|
||||
const uint8_t image_pixels[] = {
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 2,
|
||||
0, 0, 0, 0, 0, 0, 3};
|
||||
|
||||
cv::Mat image(cv::Size(7, 7), CV_8UC1, (void*)image_pixels, cv::Mat::AUTO_STEP);
|
||||
std::vector<cv::Point2f> corners = {cv::Point2f(5.25, 6.5)};
|
||||
cv::Size win(1, 1);
|
||||
cv::Size zeroZone(-1, -1);
|
||||
cv::TermCriteria criteria;
|
||||
cv::cornerSubPix(image, corners, win, zeroZone, criteria);
|
||||
|
||||
ASSERT_EQ(corners.size(), 1u);
|
||||
ASSERT_TRUE(Rect(0, 0, image.cols, image.rows).contains(corners.front()));
|
||||
}
|
||||
|
||||
// See https://github.com/opencv/opencv/issues/26016
|
||||
TEST(Imgproc_CornerSubPix, corners_on_the_edge)
|
||||
{
|
||||
cv::Mat image(500, 500, CV_8UC1);
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
cvtest::randUni(rng, image, 0, 255);
|
||||
cv::Size win(1, 1);
|
||||
cv::Size zeroZone(-1, -1);
|
||||
cv::TermCriteria criteria;
|
||||
|
||||
std::vector<cv::Point2f> cornersOK1 = { cv::Point2f(250, std::nextafter(499.5f, 499.5f - 1.0f)) };
|
||||
EXPECT_NO_THROW( cv::cornerSubPix(image, cornersOK1, win, zeroZone, criteria) ) << cornersOK1;
|
||||
|
||||
std::vector<cv::Point2f> cornersOK2 = { cv::Point2f(250, 499.5f) };
|
||||
EXPECT_NO_THROW( cv::cornerSubPix(image, cornersOK2, win, zeroZone, criteria) ) << cornersOK2;
|
||||
|
||||
std::vector<cv::Point2f> cornersOK3 = { cv::Point2f(250, std::nextafter(499.5f, 499.5f + 1.0f)) };
|
||||
EXPECT_NO_THROW( cv::cornerSubPix(image, cornersOK3, win, zeroZone, criteria) ) << cornersOK3;
|
||||
|
||||
std::vector<cv::Point2f> cornersOK4 = { cv::Point2f(250, std::nextafter(500.0f, 500.0f - 1.0f)) };
|
||||
EXPECT_NO_THROW( cv::cornerSubPix(image, cornersOK4, win, zeroZone, criteria) ) << cornersOK4;
|
||||
|
||||
std::vector<cv::Point2f> cornersNG1 = { cv::Point2f(250, 500.0f) };
|
||||
EXPECT_ANY_THROW( cv::cornerSubPix(image, cornersNG1, win, zeroZone, criteria) ) << cornersNG1;
|
||||
|
||||
std::vector<cv::Point2f> cornersNG2 = { cv::Point2f(250, std::nextafter(500.0f, 500.0f + 1.0f)) };
|
||||
EXPECT_ANY_THROW( cv::cornerSubPix(image, cornersNG2, win, zeroZone, criteria) ) << cornersNG2;
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,887 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#undef RGB
|
||||
#undef YUV
|
||||
|
||||
typedef Vec3b YUV;
|
||||
typedef Vec3b RGB;
|
||||
|
||||
int countOfDifferencies(const Mat& gold, const Mat& result, int maxAllowedDifference = 1)
|
||||
{
|
||||
Mat diff;
|
||||
absdiff(gold, result, diff);
|
||||
return countNonZero(diff.reshape(1) > maxAllowedDifference);
|
||||
}
|
||||
|
||||
class YUVreader
|
||||
{
|
||||
public:
|
||||
virtual ~YUVreader() {}
|
||||
virtual YUV read(const Mat& yuv, int row, int col) = 0;
|
||||
virtual int channels() = 0;
|
||||
virtual Size size(Size imgSize) = 0;
|
||||
|
||||
virtual bool requiresEvenHeight() { return true; }
|
||||
virtual bool requiresEvenWidth() { return true; }
|
||||
|
||||
static YUVreader* getReader(int code);
|
||||
};
|
||||
|
||||
class RGBreader
|
||||
{
|
||||
public:
|
||||
virtual ~RGBreader() {}
|
||||
virtual RGB read(const Mat& rgb, int row, int col) = 0;
|
||||
virtual int channels() = 0;
|
||||
|
||||
static RGBreader* getReader(int code);
|
||||
};
|
||||
|
||||
class RGBwriter
|
||||
{
|
||||
public:
|
||||
virtual ~RGBwriter() {}
|
||||
|
||||
virtual void write(Mat& rgb, int row, int col, const RGB& val) = 0;
|
||||
virtual int channels() = 0;
|
||||
|
||||
static RGBwriter* getWriter(int code);
|
||||
};
|
||||
|
||||
class GRAYwriter
|
||||
{
|
||||
public:
|
||||
virtual ~GRAYwriter() {}
|
||||
|
||||
virtual void write(Mat& gray, int row, int col, const uchar& val)
|
||||
{
|
||||
gray.at<uchar>(row, col) = val;
|
||||
}
|
||||
|
||||
virtual int channels() { return 1; }
|
||||
|
||||
static GRAYwriter* getWriter(int code);
|
||||
};
|
||||
|
||||
class YUVwriter
|
||||
{
|
||||
public:
|
||||
virtual ~YUVwriter() {}
|
||||
|
||||
virtual void write(Mat& yuv, int row, int col, const YUV& val) = 0;
|
||||
virtual int channels() = 0;
|
||||
virtual Size size(Size imgSize) = 0;
|
||||
|
||||
virtual bool requiresEvenHeight() { return true; }
|
||||
virtual bool requiresEvenWidth() { return true; }
|
||||
|
||||
static YUVwriter* getWriter(int code);
|
||||
};
|
||||
|
||||
class RGB888Writer : public RGBwriter
|
||||
{
|
||||
void write(Mat& rgb, int row, int col, const RGB& val)
|
||||
{
|
||||
rgb.at<Vec3b>(row, col) = val;
|
||||
}
|
||||
|
||||
int channels() { return 3; }
|
||||
};
|
||||
|
||||
class BGR888Writer : public RGBwriter
|
||||
{
|
||||
void write(Mat& rgb, int row, int col, const RGB& val)
|
||||
{
|
||||
Vec3b tmp(val[2], val[1], val[0]);
|
||||
rgb.at<Vec3b>(row, col) = tmp;
|
||||
}
|
||||
|
||||
int channels() { return 3; }
|
||||
};
|
||||
|
||||
class RGBA8888Writer : public RGBwriter
|
||||
{
|
||||
void write(Mat& rgb, int row, int col, const RGB& val)
|
||||
{
|
||||
Vec4b tmp(val[0], val[1], val[2], 255);
|
||||
rgb.at<Vec4b>(row, col) = tmp;
|
||||
}
|
||||
|
||||
int channels() { return 4; }
|
||||
};
|
||||
|
||||
class BGRA8888Writer : public RGBwriter
|
||||
{
|
||||
void write(Mat& rgb, int row, int col, const RGB& val)
|
||||
{
|
||||
Vec4b tmp(val[2], val[1], val[0], 255);
|
||||
rgb.at<Vec4b>(row, col) = tmp;
|
||||
}
|
||||
|
||||
int channels() { return 4; }
|
||||
};
|
||||
|
||||
class YUV420pWriter: public YUVwriter
|
||||
{
|
||||
int channels() { return 1; }
|
||||
Size size(Size imgSize) { return Size(imgSize.width, imgSize.height + imgSize.height/2); }
|
||||
};
|
||||
|
||||
class YV12Writer: public YUV420pWriter
|
||||
{
|
||||
void write(Mat& yuv, int row, int col, const YUV& val)
|
||||
{
|
||||
int h = yuv.rows * 2 / 3;
|
||||
|
||||
yuv.ptr<uchar>(row)[col] = val[0];
|
||||
if( row % 2 == 0 && col % 2 == 0 )
|
||||
{
|
||||
yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[2];
|
||||
yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class I420Writer: public YUV420pWriter
|
||||
{
|
||||
void write(Mat& yuv, int row, int col, const YUV& val)
|
||||
{
|
||||
int h = yuv.rows * 2 / 3;
|
||||
|
||||
yuv.ptr<uchar>(row)[col] = val[0];
|
||||
if( row % 2 == 0 && col % 2 == 0 )
|
||||
{
|
||||
yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[1];
|
||||
yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[2];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class YUV422Writer: public YUVwriter
|
||||
{
|
||||
int channels() { return 2; }
|
||||
Size size(Size imgSize) { return Size(imgSize.width, imgSize.height); }
|
||||
};
|
||||
|
||||
class UYVYWriter: public YUV422Writer
|
||||
{
|
||||
virtual void write(Mat& yuv, int row, int col, const YUV& val)
|
||||
{
|
||||
yuv.ptr<Vec2b>(row)[col][1] = val[0];
|
||||
yuv.ptr<Vec2b>(row)[(col/2)*2][0] = val[1];
|
||||
yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][0] = val[2];
|
||||
}
|
||||
};
|
||||
|
||||
class YUY2Writer: public YUV422Writer
|
||||
{
|
||||
virtual void write(Mat& yuv, int row, int col, const YUV& val)
|
||||
{
|
||||
yuv.ptr<Vec2b>(row)[col][0] = val[0];
|
||||
yuv.ptr<Vec2b>(row)[(col/2)*2][1] = val[1];
|
||||
yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1] = val[2];
|
||||
}
|
||||
};
|
||||
|
||||
class YVYUWriter: public YUV422Writer
|
||||
{
|
||||
virtual void write(Mat& yuv, int row, int col, const YUV& val)
|
||||
{
|
||||
yuv.ptr<Vec2b>(row)[col][0] = val[0];
|
||||
yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1] = val[1];
|
||||
yuv.ptr<Vec2b>(row)[(col/2)*2][1] = val[2];
|
||||
}
|
||||
};
|
||||
|
||||
class YUV420Reader: public YUVreader
|
||||
{
|
||||
int channels() { return 1; }
|
||||
Size size(Size imgSize) { return Size(imgSize.width, imgSize.height * 3 / 2); }
|
||||
};
|
||||
|
||||
class YUV422Reader: public YUVreader
|
||||
{
|
||||
int channels() { return 2; }
|
||||
Size size(Size imgSize) { return imgSize; }
|
||||
bool requiresEvenHeight() { return false; }
|
||||
};
|
||||
|
||||
class NV21Reader: public YUV420Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
uchar y = yuv.ptr<uchar>(row)[col];
|
||||
uchar u = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2 + 1];
|
||||
uchar v = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct NV12Reader: public YUV420Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
uchar y = yuv.ptr<uchar>(row)[col];
|
||||
uchar u = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2];
|
||||
uchar v = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2 + 1];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class YV12Reader: public YUV420Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
int h = yuv.rows * 2 / 3;
|
||||
uchar y = yuv.ptr<uchar>(row)[col];
|
||||
uchar u = yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)];
|
||||
uchar v = yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class IYUVReader: public YUV420Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
int h = yuv.rows * 2 / 3;
|
||||
uchar y = yuv.ptr<uchar>(row)[col];
|
||||
uchar u = yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)];
|
||||
uchar v = yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class UYVYReader: public YUV422Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
uchar y = yuv.ptr<Vec2b>(row)[col][1];
|
||||
uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2][0];
|
||||
uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][0];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class YUY2Reader: public YUV422Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
uchar y = yuv.ptr<Vec2b>(row)[col][0];
|
||||
uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2][1];
|
||||
uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class YVYUReader: public YUV422Reader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
uchar y = yuv.ptr<Vec2b>(row)[col][0];
|
||||
uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1];
|
||||
uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2][1];
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class YUV888Reader : public YUVreader
|
||||
{
|
||||
YUV read(const Mat& yuv, int row, int col)
|
||||
{
|
||||
return yuv.at<YUV>(row, col);
|
||||
}
|
||||
|
||||
int channels() { return 3; }
|
||||
Size size(Size imgSize) { return imgSize; }
|
||||
bool requiresEvenHeight() { return false; }
|
||||
bool requiresEvenWidth() { return false; }
|
||||
};
|
||||
|
||||
class RGB888Reader : public RGBreader
|
||||
{
|
||||
RGB read(const Mat& rgb, int row, int col)
|
||||
{
|
||||
return rgb.at<RGB>(row, col);
|
||||
}
|
||||
|
||||
int channels() { return 3; }
|
||||
};
|
||||
|
||||
class BGR888Reader : public RGBreader
|
||||
{
|
||||
RGB read(const Mat& rgb, int row, int col)
|
||||
{
|
||||
RGB tmp = rgb.at<RGB>(row, col);
|
||||
return RGB(tmp[2], tmp[1], tmp[0]);
|
||||
}
|
||||
|
||||
int channels() { return 3; }
|
||||
};
|
||||
|
||||
class RGBA8888Reader : public RGBreader
|
||||
{
|
||||
RGB read(const Mat& rgb, int row, int col)
|
||||
{
|
||||
Vec4b rgba = rgb.at<Vec4b>(row, col);
|
||||
return RGB(rgba[0], rgba[1], rgba[2]);
|
||||
}
|
||||
|
||||
int channels() { return 4; }
|
||||
};
|
||||
|
||||
class BGRA8888Reader : public RGBreader
|
||||
{
|
||||
RGB read(const Mat& rgb, int row, int col)
|
||||
{
|
||||
Vec4b rgba = rgb.at<Vec4b>(row, col);
|
||||
return RGB(rgba[2], rgba[1], rgba[0]);
|
||||
}
|
||||
|
||||
int channels() { return 4; }
|
||||
};
|
||||
|
||||
class YUV2RGB_Converter
|
||||
{
|
||||
public:
|
||||
RGB convert(YUV yuv)
|
||||
{
|
||||
int y = std::max(0, yuv[0] - 16);
|
||||
int u = yuv[1] - 128;
|
||||
int v = yuv[2] - 128;
|
||||
uchar r = saturate_cast<uchar>(1.164f * y + 1.596f * v);
|
||||
uchar g = saturate_cast<uchar>(1.164f * y - 0.813f * v - 0.391f * u);
|
||||
uchar b = saturate_cast<uchar>(1.164f * y + 2.018f * u);
|
||||
|
||||
return RGB(r, g, b);
|
||||
}
|
||||
};
|
||||
|
||||
class YUV2GRAY_Converter
|
||||
{
|
||||
public:
|
||||
uchar convert(YUV yuv)
|
||||
{
|
||||
return yuv[0];
|
||||
}
|
||||
};
|
||||
|
||||
class RGB2YUV_Converter
|
||||
{
|
||||
public:
|
||||
YUV convert(RGB rgb)
|
||||
{
|
||||
int r = rgb[0];
|
||||
int g = rgb[1];
|
||||
int b = rgb[2];
|
||||
|
||||
uchar y = saturate_cast<uchar>((int)( 0.257f*r + 0.504f*g + 0.098f*b + 0.5f) + 16);
|
||||
uchar u = saturate_cast<uchar>((int)(-0.148f*r - 0.291f*g + 0.439f*b + 0.5f) + 128);
|
||||
uchar v = saturate_cast<uchar>((int)( 0.439f*r - 0.368f*g - 0.071f*b + 0.5f) + 128);
|
||||
|
||||
return YUV(y, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
class RGB2YUV422_Converter
|
||||
{
|
||||
public:
|
||||
YUV convert(RGB rgb1, RGB rgb2, int idx)
|
||||
{
|
||||
int r1 = rgb1[0];
|
||||
int g1 = rgb1[1];
|
||||
int b1 = rgb1[2];
|
||||
|
||||
int r2 = rgb2[0];
|
||||
int g2 = rgb2[1];
|
||||
int b2 = rgb2[2];
|
||||
|
||||
// Coefficients below based on ITU.BT-601, ISBN 1-878707-09-4 (https://fourcc.org/fccyvrgb.php)
|
||||
// The conversion coefficients for RGB to YUV422 are based on the ones for RGB to YUV.
|
||||
// For both Y components, the coefficients are applied as given in the link to each input RGB pixel
|
||||
// separately. For U and V, they are reduced by half to account for two RGB pixels contributing
|
||||
// to the same U and V values. In other words, the U and V contributions from the two RGB pixels
|
||||
// are averaged. The integer versions are obtained by multiplying the float versions by 16384
|
||||
// and rounding to the nearest integer.
|
||||
|
||||
uchar y1 = saturate_cast<uchar>((int)( 0.257f*r1 + 0.504f*g1 + 0.098f*b1 + 16));
|
||||
uchar y2 = saturate_cast<uchar>((int)( 0.257f*r2 + 0.504f*g2 + 0.098f*b2 + 16));
|
||||
uchar u = saturate_cast<uchar>((int)(-0.074f*(r1+r2) - 0.1455f*(g1+g2) + 0.2195f*(b1+b2) + 128));
|
||||
uchar v = saturate_cast<uchar>((int)( 0.2195f*(r1+r2) - 0.184f*(g1+g2) - 0.0355f*(b1+b2) + 128));
|
||||
|
||||
return YUV((idx==0)?y1:y2, u, v);
|
||||
}
|
||||
};
|
||||
|
||||
YUVreader* YUVreader::getReader(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case COLOR_YUV2RGB_NV12:
|
||||
case COLOR_YUV2BGR_NV12:
|
||||
case COLOR_YUV2RGBA_NV12:
|
||||
case COLOR_YUV2BGRA_NV12:
|
||||
return new NV12Reader();
|
||||
case COLOR_YUV2RGB_NV21:
|
||||
case COLOR_YUV2BGR_NV21:
|
||||
case COLOR_YUV2RGBA_NV21:
|
||||
case COLOR_YUV2BGRA_NV21:
|
||||
return new NV21Reader();
|
||||
case COLOR_YUV2RGB_YV12:
|
||||
case COLOR_YUV2BGR_YV12:
|
||||
case COLOR_YUV2RGBA_YV12:
|
||||
case COLOR_YUV2BGRA_YV12:
|
||||
return new YV12Reader();
|
||||
case COLOR_YUV2RGB_IYUV:
|
||||
case COLOR_YUV2BGR_IYUV:
|
||||
case COLOR_YUV2RGBA_IYUV:
|
||||
case COLOR_YUV2BGRA_IYUV:
|
||||
return new IYUVReader();
|
||||
case COLOR_YUV2RGB_UYVY:
|
||||
case COLOR_YUV2BGR_UYVY:
|
||||
case COLOR_YUV2RGBA_UYVY:
|
||||
case COLOR_YUV2BGRA_UYVY:
|
||||
return new UYVYReader();
|
||||
//case COLOR_YUV2RGB_VYUY = 109,
|
||||
//case COLOR_YUV2BGR_VYUY = 110,
|
||||
//case COLOR_YUV2RGBA_VYUY = 113,
|
||||
//case COLOR_YUV2BGRA_VYUY = 114,
|
||||
// return ??
|
||||
case COLOR_YUV2RGB_YUY2:
|
||||
case COLOR_YUV2BGR_YUY2:
|
||||
case COLOR_YUV2RGBA_YUY2:
|
||||
case COLOR_YUV2BGRA_YUY2:
|
||||
return new YUY2Reader();
|
||||
case COLOR_YUV2RGB_YVYU:
|
||||
case COLOR_YUV2BGR_YVYU:
|
||||
case COLOR_YUV2RGBA_YVYU:
|
||||
case COLOR_YUV2BGRA_YVYU:
|
||||
return new YVYUReader();
|
||||
case COLOR_YUV2GRAY_420:
|
||||
return new NV21Reader();
|
||||
case COLOR_YUV2GRAY_UYVY:
|
||||
return new UYVYReader();
|
||||
case COLOR_YUV2GRAY_YUY2:
|
||||
return new YUY2Reader();
|
||||
case COLOR_YUV2BGR:
|
||||
case COLOR_YUV2RGB:
|
||||
return new YUV888Reader();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RGBreader* RGBreader::getReader(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case COLOR_RGB2YUV_YV12:
|
||||
case COLOR_RGB2YUV_I420:
|
||||
case COLOR_RGB2YUV_UYVY:
|
||||
case COLOR_RGB2YUV_YUY2:
|
||||
case COLOR_RGB2YUV_YVYU:
|
||||
return new RGB888Reader();
|
||||
case COLOR_BGR2YUV_YV12:
|
||||
case COLOR_BGR2YUV_I420:
|
||||
case COLOR_BGR2YUV_UYVY:
|
||||
case COLOR_BGR2YUV_YUY2:
|
||||
case COLOR_BGR2YUV_YVYU:
|
||||
return new BGR888Reader();
|
||||
case COLOR_RGBA2YUV_I420:
|
||||
case COLOR_RGBA2YUV_YV12:
|
||||
case COLOR_RGBA2YUV_UYVY:
|
||||
case COLOR_RGBA2YUV_YUY2:
|
||||
case COLOR_RGBA2YUV_YVYU:
|
||||
return new RGBA8888Reader();
|
||||
case COLOR_BGRA2YUV_YV12:
|
||||
case COLOR_BGRA2YUV_I420:
|
||||
case COLOR_BGRA2YUV_UYVY:
|
||||
case COLOR_BGRA2YUV_YUY2:
|
||||
case COLOR_BGRA2YUV_YVYU:
|
||||
return new BGRA8888Reader();
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
RGBwriter* RGBwriter::getWriter(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case COLOR_YUV2RGB_NV12:
|
||||
case COLOR_YUV2RGB_NV21:
|
||||
case COLOR_YUV2RGB_YV12:
|
||||
case COLOR_YUV2RGB_IYUV:
|
||||
case COLOR_YUV2RGB_UYVY:
|
||||
//case COLOR_YUV2RGB_VYUY:
|
||||
case COLOR_YUV2RGB_YUY2:
|
||||
case COLOR_YUV2RGB_YVYU:
|
||||
case COLOR_YUV2RGB:
|
||||
return new RGB888Writer();
|
||||
case COLOR_YUV2BGR_NV12:
|
||||
case COLOR_YUV2BGR_NV21:
|
||||
case COLOR_YUV2BGR_YV12:
|
||||
case COLOR_YUV2BGR_IYUV:
|
||||
case COLOR_YUV2BGR_UYVY:
|
||||
//case COLOR_YUV2BGR_VYUY:
|
||||
case COLOR_YUV2BGR_YUY2:
|
||||
case COLOR_YUV2BGR_YVYU:
|
||||
case COLOR_YUV2BGR:
|
||||
return new BGR888Writer();
|
||||
case COLOR_YUV2RGBA_NV12:
|
||||
case COLOR_YUV2RGBA_NV21:
|
||||
case COLOR_YUV2RGBA_YV12:
|
||||
case COLOR_YUV2RGBA_IYUV:
|
||||
case COLOR_YUV2RGBA_UYVY:
|
||||
//case COLOR_YUV2RGBA_VYUY:
|
||||
case COLOR_YUV2RGBA_YUY2:
|
||||
case COLOR_YUV2RGBA_YVYU:
|
||||
return new RGBA8888Writer();
|
||||
case COLOR_YUV2BGRA_NV12:
|
||||
case COLOR_YUV2BGRA_NV21:
|
||||
case COLOR_YUV2BGRA_YV12:
|
||||
case COLOR_YUV2BGRA_IYUV:
|
||||
case COLOR_YUV2BGRA_UYVY:
|
||||
//case COLOR_YUV2BGRA_VYUY:
|
||||
case COLOR_YUV2BGRA_YUY2:
|
||||
case COLOR_YUV2BGRA_YVYU:
|
||||
return new BGRA8888Writer();
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
GRAYwriter* GRAYwriter::getWriter(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case COLOR_YUV2GRAY_420:
|
||||
case COLOR_YUV2GRAY_UYVY:
|
||||
case COLOR_YUV2GRAY_YUY2:
|
||||
return new GRAYwriter();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
YUVwriter* YUVwriter::getWriter(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case COLOR_RGB2YUV_YV12:
|
||||
case COLOR_BGR2YUV_YV12:
|
||||
case COLOR_RGBA2YUV_YV12:
|
||||
case COLOR_BGRA2YUV_YV12:
|
||||
return new YV12Writer();
|
||||
case COLOR_RGB2YUV_UYVY:
|
||||
case COLOR_BGR2YUV_UYVY:
|
||||
case COLOR_RGBA2YUV_UYVY:
|
||||
case COLOR_BGRA2YUV_UYVY:
|
||||
return new UYVYWriter();
|
||||
case COLOR_RGB2YUV_YUY2:
|
||||
case COLOR_BGR2YUV_YUY2:
|
||||
case COLOR_RGBA2YUV_YUY2:
|
||||
case COLOR_BGRA2YUV_YUY2:
|
||||
return new YUY2Writer();
|
||||
case COLOR_RGB2YUV_YVYU:
|
||||
case COLOR_BGR2YUV_YVYU:
|
||||
case COLOR_RGBA2YUV_YVYU:
|
||||
case COLOR_BGRA2YUV_YVYU:
|
||||
return new YVYUWriter();
|
||||
case COLOR_RGB2YUV_I420:
|
||||
case COLOR_BGR2YUV_I420:
|
||||
case COLOR_RGBA2YUV_I420:
|
||||
case COLOR_BGRA2YUV_I420:
|
||||
return new I420Writer();
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
template<class convertor>
|
||||
void referenceYUV2RGB(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, RGBwriter* rgbWriter)
|
||||
{
|
||||
convertor cvt;
|
||||
|
||||
for(int row = 0; row < rgb.rows; ++row)
|
||||
for(int col = 0; col < rgb.cols; ++col)
|
||||
rgbWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col)));
|
||||
}
|
||||
|
||||
template<class convertor>
|
||||
void referenceYUV2GRAY(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, GRAYwriter* grayWriter)
|
||||
{
|
||||
convertor cvt;
|
||||
|
||||
for(int row = 0; row < rgb.rows; ++row)
|
||||
for(int col = 0; col < rgb.cols; ++col)
|
||||
grayWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col)));
|
||||
}
|
||||
|
||||
template<class convertor>
|
||||
void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* yuvWriter)
|
||||
{
|
||||
convertor cvt;
|
||||
|
||||
for(int row = 0; row < rgb.rows; ++row)
|
||||
for(int col = 0; col < rgb.cols; ++col)
|
||||
yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col)));
|
||||
}
|
||||
|
||||
template<class convertor>
|
||||
void referenceRGB2YUV422(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* yuvWriter)
|
||||
{
|
||||
convertor cvt;
|
||||
|
||||
for(int row = 0; row < rgb.rows; ++row)
|
||||
{
|
||||
for(int col = 0; col < rgb.cols; col+=2)
|
||||
{
|
||||
yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col), rgbReader->read(rgb, row, col+1), 0));
|
||||
yuvWriter->write(yuv, row, col+1, cvt.convert(rgbReader->read(rgb, row, col), rgbReader->read(rgb, row, col+1), 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConversionYUV
|
||||
{
|
||||
explicit ConversionYUV( const int code )
|
||||
{
|
||||
yuvReader_ = YUVreader :: getReader(code);
|
||||
yuvWriter_ = YUVwriter :: getWriter(code);
|
||||
rgbReader_ = RGBreader :: getReader(code);
|
||||
rgbWriter_ = RGBwriter :: getWriter(code);
|
||||
grayWriter_ = GRAYwriter:: getWriter(code);
|
||||
}
|
||||
|
||||
~ConversionYUV()
|
||||
{
|
||||
if (yuvReader_)
|
||||
delete yuvReader_;
|
||||
|
||||
if (yuvWriter_)
|
||||
delete yuvWriter_;
|
||||
|
||||
if (rgbReader_)
|
||||
delete rgbReader_;
|
||||
|
||||
if (rgbWriter_)
|
||||
delete rgbWriter_;
|
||||
|
||||
if (grayWriter_)
|
||||
delete grayWriter_;
|
||||
}
|
||||
|
||||
int getDcn()
|
||||
{
|
||||
return (rgbWriter_ != 0) ? rgbWriter_->channels() : ((grayWriter_ != 0) ? grayWriter_->channels() : yuvWriter_->channels());
|
||||
}
|
||||
|
||||
int getScn()
|
||||
{
|
||||
return (yuvReader_ != 0) ? yuvReader_->channels() : rgbReader_->channels();
|
||||
}
|
||||
|
||||
Size getSrcSize( const Size& imgSize )
|
||||
{
|
||||
return (yuvReader_ != 0) ? yuvReader_->size(imgSize) : imgSize;
|
||||
}
|
||||
|
||||
Size getDstSize( const Size& imgSize )
|
||||
{
|
||||
return (yuvWriter_ != 0) ? yuvWriter_->size(imgSize) : imgSize;
|
||||
}
|
||||
|
||||
bool requiresEvenHeight()
|
||||
{
|
||||
return (yuvReader_ != 0) ? yuvReader_->requiresEvenHeight() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenHeight() : false);
|
||||
}
|
||||
|
||||
bool requiresEvenWidth()
|
||||
{
|
||||
return (yuvReader_ != 0) ? yuvReader_->requiresEvenWidth() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenWidth() : false);
|
||||
}
|
||||
|
||||
YUVreader* yuvReader_;
|
||||
YUVwriter* yuvWriter_;
|
||||
RGBreader* rgbReader_;
|
||||
RGBwriter* rgbWriter_;
|
||||
GRAYwriter* grayWriter_;
|
||||
};
|
||||
|
||||
bool is_rgb2yuv422(int code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case COLOR_RGB2YUV_UYVY:
|
||||
case COLOR_BGR2YUV_UYVY:
|
||||
case COLOR_RGBA2YUV_UYVY:
|
||||
case COLOR_BGRA2YUV_UYVY:
|
||||
case COLOR_RGB2YUV_YUY2:
|
||||
case COLOR_BGR2YUV_YUY2:
|
||||
case COLOR_RGBA2YUV_YUY2:
|
||||
case COLOR_BGRA2YUV_YUY2:
|
||||
case COLOR_RGB2YUV_YVYU:
|
||||
case COLOR_BGR2YUV_YVYU:
|
||||
case COLOR_RGBA2YUV_YVYU:
|
||||
case COLOR_BGRA2YUV_YVYU:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CV_ENUM(YUVCVTS, COLOR_YUV2RGB_NV12, COLOR_YUV2BGR_NV12, COLOR_YUV2RGB_NV21, COLOR_YUV2BGR_NV21,
|
||||
COLOR_YUV2RGBA_NV12, COLOR_YUV2BGRA_NV12, COLOR_YUV2RGBA_NV21, COLOR_YUV2BGRA_NV21,
|
||||
COLOR_YUV2RGB_YV12, COLOR_YUV2BGR_YV12, COLOR_YUV2RGB_IYUV, COLOR_YUV2BGR_IYUV,
|
||||
COLOR_YUV2RGBA_YV12, COLOR_YUV2BGRA_YV12, COLOR_YUV2RGBA_IYUV, COLOR_YUV2BGRA_IYUV,
|
||||
COLOR_YUV2RGB_UYVY, COLOR_YUV2BGR_UYVY, COLOR_YUV2RGBA_UYVY, COLOR_YUV2BGRA_UYVY,
|
||||
COLOR_YUV2RGB_YUY2, COLOR_YUV2BGR_YUY2, COLOR_YUV2RGB_YVYU, COLOR_YUV2BGR_YVYU,
|
||||
COLOR_YUV2RGBA_YUY2, COLOR_YUV2BGRA_YUY2, COLOR_YUV2RGBA_YVYU, COLOR_YUV2BGRA_YVYU,
|
||||
COLOR_YUV2GRAY_420, COLOR_YUV2GRAY_UYVY, COLOR_YUV2GRAY_YUY2,
|
||||
COLOR_YUV2BGR, COLOR_YUV2RGB, COLOR_RGB2YUV_YV12, COLOR_BGR2YUV_YV12, COLOR_RGBA2YUV_YV12,
|
||||
COLOR_BGRA2YUV_YV12, COLOR_RGB2YUV_I420, COLOR_BGR2YUV_I420, COLOR_RGBA2YUV_I420, COLOR_BGRA2YUV_I420,
|
||||
COLOR_RGB2YUV_UYVY, COLOR_BGR2YUV_UYVY, COLOR_RGBA2YUV_UYVY, COLOR_BGRA2YUV_UYVY,
|
||||
COLOR_RGB2YUV_YUY2, COLOR_BGR2YUV_YUY2, COLOR_RGB2YUV_YVYU, COLOR_BGR2YUV_YVYU,
|
||||
COLOR_RGBA2YUV_YUY2, COLOR_BGRA2YUV_YUY2, COLOR_RGBA2YUV_YVYU, COLOR_BGRA2YUV_YVYU)
|
||||
|
||||
typedef ::testing::TestWithParam<YUVCVTS> Imgproc_ColorYUV;
|
||||
|
||||
TEST_P(Imgproc_ColorYUV, accuracy)
|
||||
{
|
||||
int code = GetParam();
|
||||
bool yuv422 = is_rgb2yuv422(code);
|
||||
|
||||
RNG& random = theRNG();
|
||||
|
||||
ConversionYUV cvt(code);
|
||||
|
||||
const int scn = cvt.getScn();
|
||||
const int dcn = cvt.getDcn();
|
||||
for(int iter = 0; iter < 30; ++iter)
|
||||
{
|
||||
Size sz(random.uniform(1, 641), random.uniform(1, 481));
|
||||
|
||||
if(cvt.requiresEvenWidth()) sz.width += sz.width % 2;
|
||||
if(cvt.requiresEvenHeight()) sz.height += sz.height % 2;
|
||||
|
||||
Size srcSize = cvt.getSrcSize(sz);
|
||||
Mat src = Mat(srcSize.height, srcSize.width * scn, CV_8UC1).reshape(scn);
|
||||
|
||||
Size dstSize = cvt.getDstSize(sz);
|
||||
Mat dst = Mat(dstSize.height, dstSize.width * dcn, CV_8UC1).reshape(dcn);
|
||||
Mat gold(dstSize, CV_8UC(dcn));
|
||||
|
||||
random.fill(src, RNG::UNIFORM, 0, 256);
|
||||
|
||||
if(cvt.rgbWriter_)
|
||||
referenceYUV2RGB<YUV2RGB_Converter> (src, gold, cvt.yuvReader_, cvt.rgbWriter_);
|
||||
else if(cvt.grayWriter_)
|
||||
referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, cvt.yuvReader_, cvt.grayWriter_);
|
||||
else if(cvt.yuvWriter_)
|
||||
{
|
||||
if(!yuv422)
|
||||
referenceRGB2YUV<RGB2YUV_Converter> (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
|
||||
else
|
||||
referenceRGB2YUV422<RGB2YUV422_Converter> (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
|
||||
}
|
||||
|
||||
cv::cvtColor(src, dst, code, -1);
|
||||
|
||||
EXPECT_EQ(0, countOfDifferencies(gold, dst));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_ColorYUV, roi_accuracy)
|
||||
{
|
||||
int code = GetParam();
|
||||
bool yuv422 = is_rgb2yuv422(code);
|
||||
|
||||
RNG& random = theRNG();
|
||||
|
||||
ConversionYUV cvt(code);
|
||||
|
||||
const int scn = cvt.getScn();
|
||||
const int dcn = cvt.getDcn();
|
||||
for(int iter = 0; iter < 30; ++iter)
|
||||
{
|
||||
Size sz(random.uniform(1, 641), random.uniform(1, 481));
|
||||
|
||||
if(cvt.requiresEvenWidth()) sz.width += sz.width % 2;
|
||||
if(cvt.requiresEvenHeight()) sz.height += sz.height % 2;
|
||||
|
||||
int roi_offset_top = random.uniform(0, 6);
|
||||
int roi_offset_bottom = random.uniform(0, 6);
|
||||
int roi_offset_left = random.uniform(0, 6);
|
||||
int roi_offset_right = random.uniform(0, 6);
|
||||
|
||||
Size srcSize = cvt.getSrcSize(sz);
|
||||
Mat src_full(srcSize.height + roi_offset_top + roi_offset_bottom, srcSize.width + roi_offset_left + roi_offset_right, CV_8UC(scn));
|
||||
|
||||
Size dstSize = cvt.getDstSize(sz);
|
||||
Mat dst_full(dstSize.height + roi_offset_left + roi_offset_right, dstSize.width + roi_offset_top + roi_offset_bottom, CV_8UC(dcn), Scalar::all(0));
|
||||
Mat gold_full(dst_full.size(), CV_8UC(dcn), Scalar::all(0));
|
||||
|
||||
random.fill(src_full, RNG::UNIFORM, 0, 256);
|
||||
|
||||
Mat src = src_full(Range(roi_offset_top, roi_offset_top + srcSize.height), Range(roi_offset_left, roi_offset_left + srcSize.width));
|
||||
Mat dst = dst_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width));
|
||||
Mat gold = gold_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width));
|
||||
|
||||
if(cvt.rgbWriter_)
|
||||
referenceYUV2RGB<YUV2RGB_Converter> (src, gold, cvt.yuvReader_, cvt.rgbWriter_);
|
||||
else if(cvt.grayWriter_)
|
||||
referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, cvt.yuvReader_, cvt.grayWriter_);
|
||||
else if(cvt.yuvWriter_)
|
||||
{
|
||||
if(!yuv422)
|
||||
referenceRGB2YUV<RGB2YUV_Converter> (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
|
||||
else
|
||||
referenceRGB2YUV422<RGB2YUV422_Converter> (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
|
||||
}
|
||||
|
||||
cv::cvtColor(src, dst, code, -1);
|
||||
|
||||
EXPECT_EQ(0, countOfDifferencies(gold_full, dst_full));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(cvt420, Imgproc_ColorYUV,
|
||||
::testing::Values((int)COLOR_YUV2RGB_NV12, (int)COLOR_YUV2BGR_NV12, (int)COLOR_YUV2RGB_NV21, (int)COLOR_YUV2BGR_NV21,
|
||||
(int)COLOR_YUV2RGBA_NV12, (int)COLOR_YUV2BGRA_NV12, (int)COLOR_YUV2RGBA_NV21, (int)COLOR_YUV2BGRA_NV21,
|
||||
(int)COLOR_YUV2RGB_YV12, (int)COLOR_YUV2BGR_YV12, (int)COLOR_YUV2RGB_IYUV, (int)COLOR_YUV2BGR_IYUV,
|
||||
(int)COLOR_YUV2RGBA_YV12, (int)COLOR_YUV2BGRA_YV12, (int)COLOR_YUV2RGBA_IYUV, (int)COLOR_YUV2BGRA_IYUV,
|
||||
(int)COLOR_YUV2GRAY_420, (int)COLOR_RGB2YUV_YV12, (int)COLOR_BGR2YUV_YV12, (int)COLOR_RGBA2YUV_YV12,
|
||||
(int)COLOR_BGRA2YUV_YV12, (int)COLOR_RGB2YUV_I420, (int)COLOR_BGR2YUV_I420, (int)COLOR_RGBA2YUV_I420,
|
||||
(int)COLOR_BGRA2YUV_I420));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(cvt422, Imgproc_ColorYUV,
|
||||
::testing::Values((int)COLOR_YUV2RGB_UYVY, (int)COLOR_YUV2BGR_UYVY, (int)COLOR_YUV2RGBA_UYVY, (int)COLOR_YUV2BGRA_UYVY,
|
||||
(int)COLOR_YUV2RGB_YUY2, (int)COLOR_YUV2BGR_YUY2, (int)COLOR_YUV2RGB_YVYU, (int)COLOR_YUV2BGR_YVYU,
|
||||
(int)COLOR_YUV2RGBA_YUY2, (int)COLOR_YUV2BGRA_YUY2, (int)COLOR_YUV2RGBA_YVYU, (int)COLOR_YUV2BGRA_YVYU,
|
||||
(int)COLOR_YUV2GRAY_UYVY, (int)COLOR_YUV2GRAY_YUY2,
|
||||
(int)COLOR_RGB2YUV_UYVY, (int)COLOR_BGR2YUV_UYVY, (int)COLOR_RGBA2YUV_UYVY, (int)COLOR_BGRA2YUV_UYVY,
|
||||
(int)COLOR_RGB2YUV_YUY2, (int)COLOR_BGR2YUV_YUY2, (int)COLOR_RGB2YUV_YVYU, (int)COLOR_BGR2YUV_YVYU,
|
||||
(int)COLOR_RGBA2YUV_YUY2, (int)COLOR_BGRA2YUV_YUY2, (int)COLOR_RGBA2YUV_YVYU, (int)COLOR_BGRA2YUV_YVYU,
|
||||
(int)COLOR_RGB2YUV_YUY2));
|
||||
|
||||
}
|
||||
|
||||
TEST(cvtColorUYVY, size_issue_21035)
|
||||
{
|
||||
Mat input = Mat::zeros(1, 1, CV_8UC2);
|
||||
Mat output;
|
||||
EXPECT_THROW(cv::cvtColor(input, output, cv::COLOR_YUV2BGR_UYVY), cv::Exception);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,212 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
#include <numeric>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
BIGDATA_TEST(Imgproc_DistanceTransform, large_image_12218)
|
||||
{
|
||||
const int lls_maxcnt = 79992000; // labels's maximum count
|
||||
const int lls_mincnt = 1; // labels's minimum count
|
||||
int i, j, nz;
|
||||
Mat src(8000, 20000, CV_8UC1), dst, labels;
|
||||
for( i = 0; i < src.rows; i++ )
|
||||
for( j = 0; j < src.cols; j++ )
|
||||
src.at<uchar>(i, j) = (j > (src.cols / 2)) ? 0 : 255;
|
||||
|
||||
distanceTransform(src, dst, labels, cv::DIST_L2, cv::DIST_MASK_3, DIST_LABEL_PIXEL);
|
||||
|
||||
double scale = (double)lls_mincnt / (double)lls_maxcnt;
|
||||
labels.convertTo(labels, CV_32SC1, scale);
|
||||
Size size = labels.size();
|
||||
nz = cv::countNonZero(labels);
|
||||
EXPECT_EQ(nz, (size.height*size.width / 2));
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, wide_image_22732)
|
||||
{
|
||||
Mat src = Mat::zeros(1, 4099, CV_8U); // 4099 or larger used to be bad
|
||||
Mat dist(src.rows, src.cols, CV_32F);
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
|
||||
int nz = countNonZero(dist);
|
||||
EXPECT_EQ(nz, 0);
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, large_square_22732)
|
||||
{
|
||||
Mat src = Mat::zeros(8000, 8005, CV_8U), dist;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
|
||||
int nz = countNonZero(dist);
|
||||
EXPECT_EQ(dist.size(), src.size());
|
||||
EXPECT_EQ(dist.type(), CV_32F);
|
||||
EXPECT_EQ(nz, 0);
|
||||
|
||||
Point p0(src.cols-1, src.rows-1);
|
||||
src.setTo(1);
|
||||
src.at<uchar>(p0) = 0;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
|
||||
EXPECT_EQ(dist.size(), src.size());
|
||||
EXPECT_EQ(dist.type(), CV_32F);
|
||||
bool first = true;
|
||||
int nerrs = 0;
|
||||
for (int y = 0; y < dist.rows; y++)
|
||||
for (int x = 0; x < dist.cols; x++) {
|
||||
float d = dist.at<float>(y, x);
|
||||
double dx = (double)(x - p0.x), dy = (double)(y - p0.y);
|
||||
float d0 = (float)sqrt(dx*dx + dy*dy);
|
||||
if (std::abs(d0 - d) > 1) {
|
||||
if (first) {
|
||||
printf("y=%d, x=%d. dist_ref=%.2f, dist=%.2f\n", y, x, d0, d);
|
||||
first = false;
|
||||
}
|
||||
nerrs++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(0, nerrs) << "reference distance map is different from computed one at " << nerrs << " pixels\n";
|
||||
}
|
||||
|
||||
BIGDATA_TEST(Imgproc_DistanceTransform, issue_23895_3x3)
|
||||
{
|
||||
Mat src = Mat::zeros(50000, 50000, CV_8U), dist;
|
||||
distanceTransform(src.col(0), dist, DIST_L2, DIST_MASK_3);
|
||||
int nz = countNonZero(dist);
|
||||
EXPECT_EQ(nz, 0);
|
||||
}
|
||||
|
||||
BIGDATA_TEST(Imgproc_DistanceTransform, issue_23895_5x5)
|
||||
{
|
||||
Mat src = Mat::zeros(50000, 50000, CV_8U), dist;
|
||||
distanceTransform(src.col(0), dist, DIST_L2, DIST_MASK_5);
|
||||
int nz = countNonZero(dist);
|
||||
EXPECT_EQ(nz, 0);
|
||||
}
|
||||
|
||||
BIGDATA_TEST(Imgproc_DistanceTransform, issue_23895_5x5_labels)
|
||||
{
|
||||
Mat src = Mat::zeros(50000, 50000, CV_8U), dist, labels;
|
||||
distanceTransform(src.col(0), dist, labels, DIST_L2, DIST_MASK_5);
|
||||
int nz = countNonZero(dist);
|
||||
EXPECT_EQ(nz, 0);
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, max_distance_3x3)
|
||||
{
|
||||
Mat src = Mat::ones(1, 70000, CV_8U), dist;
|
||||
src.at<uint8_t>(0, 0) = 0;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_3);
|
||||
|
||||
double minVal, maxVal;
|
||||
minMaxLoc(dist, &minVal, &maxVal);
|
||||
EXPECT_GE(maxVal, 65533);
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, max_distance_5x5)
|
||||
{
|
||||
Mat src = Mat::ones(1, 70000, CV_8U), dist;
|
||||
src.at<uint8_t>(0, 0) = 0;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_5);
|
||||
|
||||
double minVal, maxVal;
|
||||
minMaxLoc(dist, &minVal, &maxVal);
|
||||
EXPECT_GE(maxVal, 65533);
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, max_distance_5x5_labels)
|
||||
{
|
||||
Mat src = Mat::ones(1, 70000, CV_8U), dist, labels;
|
||||
src.at<uint8_t>(0, 0) = 0;
|
||||
distanceTransform(src, dist, labels, DIST_L2, DIST_MASK_5);
|
||||
|
||||
double minVal, maxVal;
|
||||
minMaxLoc(dist, &minVal, &maxVal);
|
||||
EXPECT_GE(maxVal, 65533);
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, precise_long_dist)
|
||||
{
|
||||
static const int maxDist = 1 << 16;
|
||||
Mat src = Mat::ones(1, 70000, CV_8U), dist;
|
||||
src.at<uint8_t>(0, 0) = 0;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
|
||||
|
||||
Mat expected(src.size(), CV_32F);
|
||||
std::iota(expected.begin<float>(), expected.end<float>(), 0.f);
|
||||
expected.colRange(maxDist, expected.cols).setTo(maxDist);
|
||||
|
||||
EXPECT_EQ(cv::norm(expected, dist, NORM_INF), 0);
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, ipp_deterministic_corner)
|
||||
{
|
||||
setNumThreads(1);
|
||||
|
||||
Mat src(1, 4096, CV_8U, Scalar(255)), dist;
|
||||
src.at<uint8_t>(0, 0) = 0;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE);
|
||||
for (int i = 0; i < src.cols; ++i)
|
||||
{
|
||||
float expected = static_cast<float>(i);
|
||||
ASSERT_EQ(expected, dist.at<float>(0, i)) << cv::format("diff: %e", expected - dist.at<float>(0, i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_DistanceTransform, ipp_deterministic)
|
||||
{
|
||||
setNumThreads(1);
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
Mat src(1, 800, CV_8U, Scalar(255)), dist;
|
||||
int p1 = cvtest::randInt(rng) % src.cols;
|
||||
int p2 = cvtest::randInt(rng) % src.cols;
|
||||
int p3 = cvtest::randInt(rng) % src.cols;
|
||||
src.at<uint8_t>(0, p1) = 0;
|
||||
src.at<uint8_t>(0, p2) = 0;
|
||||
src.at<uint8_t>(0, p3) = 0;
|
||||
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE);
|
||||
for (int i = 0; i < src.cols; ++i)
|
||||
{
|
||||
float expected = static_cast<float>(min(min(abs(i - p1), abs(i - p2)), abs(i - p3)));
|
||||
ASSERT_EQ(expected, dist.at<float>(0, i)) << cv::format("diff: %e", expected - dist.at<float>(0, i));
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,250 @@
|
||||
// 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 "opencv2/imgproc.hpp"
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//==============================================================================
|
||||
// Utility
|
||||
|
||||
template <typename T>
|
||||
inline T sqr(T val)
|
||||
{
|
||||
return val * val;
|
||||
}
|
||||
|
||||
inline static float calcEMD(Mat w1, Mat w2, Mat& flow, int dist, int dims)
|
||||
{
|
||||
float mass1 = 0.f, mass2 = 0.f, work = 0.f;
|
||||
for (int i = 0; i < flow.rows; ++i)
|
||||
{
|
||||
mass1 += w1.at<float>(i, 0);
|
||||
for (int j = 0; j < flow.cols; ++j)
|
||||
{
|
||||
if (i == 0)
|
||||
mass2 += w2.at<float>(j, 0);
|
||||
float dist_ = 0.f;
|
||||
switch (dist)
|
||||
{
|
||||
case DIST_L1:
|
||||
{
|
||||
for (int k = 1; k <= dims; ++k)
|
||||
{
|
||||
dist_ += abs(w1.at<float>(i, k) - w2.at<float>(j, k));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIST_L2:
|
||||
{
|
||||
for (int k = 1; k <= dims; ++k)
|
||||
{
|
||||
dist_ += sqr(w1.at<float>(i, k) - w2.at<float>(j, k));
|
||||
}
|
||||
dist_ = sqrt(dist_);
|
||||
break;
|
||||
}
|
||||
case DIST_C:
|
||||
{
|
||||
for (int k = 1; k <= dims; ++k)
|
||||
{
|
||||
const float val = abs(w1.at<float>(i, k) - w2.at<float>(j, k));
|
||||
if (val > dist_)
|
||||
dist_ = val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
const float weight = flow.at<float>(i, j);
|
||||
work += dist_ * weight;
|
||||
}
|
||||
}
|
||||
return work / max(mass1, mass2);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
TEST(Imgproc_EMD, regression)
|
||||
{
|
||||
// input data
|
||||
const float M = 10000;
|
||||
Matx<float, 4, 1> w1 {50, 60, 50, 50};
|
||||
Matx<float, 5, 1> w2 {30, 20, 70, 30, 60};
|
||||
Matx<float, 4, 5> cost {16, 16, 13, 22, 17, 14, 14, 13, 19, 15,
|
||||
19, 19, 20, 23, M, M, 0, M, 0, 0};
|
||||
|
||||
// expected results
|
||||
const double emd0 = 2460. / 210;
|
||||
Matx<float, 4, 5> flow0 {0, 0, 50, 0, 0, 0, 0, 20, 0, 40, 30, 20, 0, 0, 0, 0, 0, 0, 30, 20};
|
||||
|
||||
// basic call with cost
|
||||
{
|
||||
float emd = 0.f;
|
||||
ASSERT_NO_THROW(emd = EMD(w1, w2, DIST_USER, cost));
|
||||
EXPECT_NEAR(emd, emd0, 1e-6 * emd0);
|
||||
}
|
||||
|
||||
// basic call with cost and flow output
|
||||
{
|
||||
Mat flow;
|
||||
float emd = 0.f;
|
||||
ASSERT_NO_THROW(emd = EMD(w1, w2, DIST_USER, cost, nullptr, flow));
|
||||
EXPECT_NEAR(emd, emd0, 1e-6 * emd0);
|
||||
EXPECT_MAT_NEAR(Mat(flow0), flow, 1e-6);
|
||||
}
|
||||
// no cost and DIST_USER - error
|
||||
{
|
||||
Mat flow;
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER, noArray(), nullptr, flow), cv::Exception);
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER), cv::Exception);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_EMD, distance_types)
|
||||
{
|
||||
// 1D (sum = 210)
|
||||
Matx<float, 4, 2> w1 {50, 1, 60, 2, 50, 3, 50, 4};
|
||||
Matx<float, 5, 2> w2 {30, 1, 20, 2, 70, 3, 30, 4, 60, 5};
|
||||
|
||||
// 2D (sum = 210)
|
||||
Matx<float, 4, 3> w3 {50, 0, 0, 60, 0, 1, 50, 1, 0, 50, 1, 1};
|
||||
Matx<float, 5, 3> w4 {20, 0, 1, 70, 1, 0, 30, 1, 1, 60, 2, 2, 30, 3, 3};
|
||||
|
||||
// basic call with all distance types
|
||||
{
|
||||
const vector<DistanceTypes> good_types {DIST_L1, DIST_L2, DIST_C};
|
||||
for (const auto& dt : good_types)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("dt=%d", dt));
|
||||
float emd = 0.f;
|
||||
Mat flow;
|
||||
// 1D
|
||||
{
|
||||
ASSERT_NO_THROW(emd = EMD(w1, w2, dt, noArray(), nullptr, flow));
|
||||
const float emd0 = calcEMD(Mat(w1), Mat(w2), flow, dt, 1);
|
||||
EXPECT_NEAR(emd0, emd, 1e-6);
|
||||
}
|
||||
// 2D
|
||||
{
|
||||
ASSERT_NO_THROW(emd = EMD(w3, w4, dt, noArray(), nullptr, flow));
|
||||
const float emd0 = calcEMD(Mat(w3), Mat(w4), flow, dt, 2);
|
||||
EXPECT_NEAR(emd0, emd, 1e-6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<int> Imgproc_EMD_dist;
|
||||
|
||||
TEST_P(Imgproc_EMD_dist, random_flow_verify)
|
||||
{
|
||||
const int dist = GetParam();
|
||||
for (size_t iter = 0; iter < 100; ++iter)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("iter=%zu", iter));
|
||||
RNG& rng = TS::ptr()->get_rng();
|
||||
const int dims = rng.uniform(1, 10);
|
||||
Mat w1(rng.uniform(1, 10), dims + 1, CV_32FC1);
|
||||
Mat w2(rng.uniform(1, 10), dims + 1, CV_32FC1);
|
||||
|
||||
// weights > 0
|
||||
{
|
||||
Mat w1_weights = w1.col(0);
|
||||
Mat w2_weights = w2.col(0);
|
||||
cvtest::randUni(rng, w1_weights, 0, 100);
|
||||
cvtest::randUni(rng, w2_weights, 0, 100);
|
||||
}
|
||||
|
||||
// coord
|
||||
{
|
||||
Mat w1_coord = w1.colRange(1, dims + 1);
|
||||
Mat w2_coord = w2.colRange(1, dims + 1);
|
||||
cvtest::randUni(rng, w1_coord, -10, +10);
|
||||
cvtest::randUni(rng, w2_coord, -10, +10);
|
||||
}
|
||||
|
||||
float emd1 = 0.f, emd2 = 0.f;
|
||||
const float eps = 1e-5f;
|
||||
Mat flow;
|
||||
{
|
||||
ASSERT_NO_THROW(emd1 = EMD(w1, w2, dist, noArray(), nullptr, flow));
|
||||
const float emd0 = calcEMD(w1, w2, flow, dist, dims);
|
||||
EXPECT_NEAR(emd0, emd1, eps);
|
||||
}
|
||||
{
|
||||
ASSERT_NO_THROW(emd2 = EMD(w2, w1, dist, noArray(), nullptr, flow));
|
||||
const float emd0 = calcEMD(w2, w1, flow, dist, dims);
|
||||
EXPECT_NEAR(emd0, emd2, eps);
|
||||
}
|
||||
EXPECT_NEAR(emd1, emd2, eps);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, Imgproc_EMD_dist, testing::Values(DIST_L1, DIST_L2, DIST_C));
|
||||
|
||||
|
||||
TEST(Imgproc_EMD, invalid)
|
||||
{
|
||||
Matx<float, 4, 2> w1 {50, 1, 60, 2, 50, 3, 50, 4};
|
||||
Matx<float, 5, 2> w2 {30, 1, 20, 2, 70, 3, 30, 4, 60, 5};
|
||||
|
||||
// empty signature
|
||||
{
|
||||
Mat empty;
|
||||
EXPECT_THROW(EMD(empty, w2, DIST_USER), cv::Exception);
|
||||
EXPECT_THROW(EMD(w1, empty, DIST_USER), cv::Exception);
|
||||
}
|
||||
|
||||
// zero total weight, negative weight
|
||||
{
|
||||
Matx<float, 3, 1> wz {0, 0, 0};
|
||||
Matx<float, 3, 2> wz1 {0, 1, 0, 2, 0, 3};
|
||||
Matx<float, 3, 1> wn {0, 3, -2};
|
||||
Matx<float, 3, 2> wn1 {0, 1, 3, 2, -2, 3};
|
||||
EXPECT_THROW(EMD(wz, w2, DIST_USER), cv::Exception);
|
||||
EXPECT_THROW(EMD(wz1, w2, DIST_USER), cv::Exception);
|
||||
EXPECT_THROW(EMD(wn, w2, DIST_USER), cv::Exception);
|
||||
EXPECT_THROW(EMD(wn1, w2, DIST_USER), cv::Exception);
|
||||
}
|
||||
|
||||
// user distance type, but no cost matrix provided or is wrong
|
||||
{
|
||||
Mat cost(3, 3, CV_32FC1, Scalar::all(0)), cost8u(4, 5, CV_8UC1, Scalar::all(0)), empty;
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER, noArray()), cv::Exception);
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER, empty), cv::Exception);
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER, cost8u), cv::Exception);
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER, cost), cv::Exception);
|
||||
}
|
||||
|
||||
// lower_bound is set together with cost
|
||||
{
|
||||
Mat cost(4, 5, CV_32FC1, Scalar::all(0));
|
||||
float bound = 0.f;
|
||||
EXPECT_THROW(EMD(w1, w2, DIST_USER, cost, &bound), cv::Exception);
|
||||
}
|
||||
|
||||
// zero dimensions with non-user distance type
|
||||
const vector<DistanceTypes> good_types {DIST_L1, DIST_L2, DIST_C};
|
||||
for (const auto& dt : good_types)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("dt=%d", dt));
|
||||
Matx<float, 4, 1> w01 {20, 30, 40, 50};
|
||||
Matx<float, 5, 1> w02 {20, 30, 40, 50, 10};
|
||||
EXPECT_THROW(EMD(w01, w02, dt), cv::Exception);
|
||||
}
|
||||
|
||||
// wrong distance type
|
||||
const vector<DistanceTypes> bad_types {DIST_L12, DIST_FAIR, DIST_WELSCH, DIST_HUBER};
|
||||
for (const auto& dt : bad_types)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("dt=%d", dt));
|
||||
EXPECT_THROW(EMD(w1, w2, dt), cv::Exception);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace opencv_test
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Imgproc_FloodFill, maskValue)
|
||||
{
|
||||
const int n = 50;
|
||||
Mat img = Mat::zeros(n, n, CV_8U);
|
||||
Mat mask;
|
||||
|
||||
circle(img, Point(n/2, n/2), 20, Scalar(100), 4);
|
||||
|
||||
int flags = 4 + FLOODFILL_MASK_ONLY;
|
||||
floodFill(img, mask, Point(n/2 + 13, n/2), Scalar(100), NULL, Scalar(), Scalar(), flags);
|
||||
|
||||
ASSERT_EQ(1, cvtest::norm(mask.rowRange(1, n-1).colRange(1, n-1), NORM_INF));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,178 @@
|
||||
/*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_GrabcutTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_GrabcutTest();
|
||||
~CV_GrabcutTest();
|
||||
protected:
|
||||
bool verify(const Mat& mask, const Mat& exp);
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_GrabcutTest::CV_GrabcutTest() {}
|
||||
CV_GrabcutTest::~CV_GrabcutTest() {}
|
||||
|
||||
bool CV_GrabcutTest::verify(const Mat& mask, const Mat& exp)
|
||||
{
|
||||
const float maxDiffRatio = 0.005f;
|
||||
int expArea = countNonZero( exp );
|
||||
int nonIntersectArea = countNonZero( mask != exp );
|
||||
|
||||
float curRatio = (float)nonIntersectArea / (float)expArea;
|
||||
ts->printf( cvtest::TS::LOG, "nonIntersectArea/expArea = %f\n", curRatio );
|
||||
return curRatio < maxDiffRatio;
|
||||
}
|
||||
|
||||
void CV_GrabcutTest::run( int /* start_from */)
|
||||
{
|
||||
cvtest::DefaultRngAuto defRng;
|
||||
|
||||
Mat img = imread(string(ts->get_data_path()) + "shared/airplane.png");
|
||||
Mat mask_prob = imread(string(ts->get_data_path()) + "grabcut/mask_prob.png", 0);
|
||||
Mat exp_mask1 = imread(string(ts->get_data_path()) + "grabcut/exp_mask1.png", 0);
|
||||
Mat exp_mask2 = imread(string(ts->get_data_path()) + "grabcut/exp_mask2.png", 0);
|
||||
|
||||
if (img.empty() || (!mask_prob.empty() && img.size() != mask_prob.size()) ||
|
||||
(!exp_mask1.empty() && img.size() != exp_mask1.size()) ||
|
||||
(!exp_mask2.empty() && img.size() != exp_mask2.size()) )
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
Rect rect(Point(24, 126), Point(483, 294));
|
||||
Mat exp_bgdModel, exp_fgdModel;
|
||||
|
||||
Mat mask;
|
||||
Mat bgdModel, fgdModel;
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_RECT );
|
||||
bgdModel.copyTo(exp_bgdModel);
|
||||
fgdModel.copyTo(exp_fgdModel);
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 2, GC_EVAL_FREEZE_MODEL );
|
||||
|
||||
// Multiply images by 255 for more visuality of test data.
|
||||
if( mask_prob.empty() )
|
||||
{
|
||||
mask.copyTo( mask_prob );
|
||||
imwrite(string(ts->get_data_path()) + "grabcut/mask_prob.png", mask_prob);
|
||||
}
|
||||
if( exp_mask1.empty() )
|
||||
{
|
||||
exp_mask1 = (mask & 1) * 255;
|
||||
imwrite(string(ts->get_data_path()) + "grabcut/exp_mask1.png", exp_mask1);
|
||||
}
|
||||
if (!verify((mask & 1) * 255, exp_mask1))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
// The model should not be changed after calling with GC_EVAL_FREEZE_MODEL
|
||||
double sumBgdModel = cv::sum(cv::abs(bgdModel) - cv::abs(exp_bgdModel))[0];
|
||||
double sumFgdModel = cv::sum(cv::abs(fgdModel) - cv::abs(exp_fgdModel))[0];
|
||||
if (sumBgdModel >= 0.1 || sumFgdModel >= 0.1)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "sumBgdModel = %f, sumFgdModel = %f\n", sumBgdModel, sumFgdModel);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = mask_prob;
|
||||
bgdModel.release();
|
||||
fgdModel.release();
|
||||
rect = Rect();
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_MASK );
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 1, GC_EVAL );
|
||||
|
||||
if( exp_mask2.empty() )
|
||||
{
|
||||
exp_mask2 = (mask & 1) * 255;
|
||||
imwrite(string(ts->get_data_path()) + "grabcut/exp_mask2.png", exp_mask2);
|
||||
}
|
||||
if (!verify((mask & 1) * 255, exp_mask2))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Imgproc_GrabCut, regression) { CV_GrabcutTest test; test.safe_run(); }
|
||||
|
||||
TEST(Imgproc_GrabCut, repeatability)
|
||||
{
|
||||
cvtest::TS& ts = *cvtest::TS::ptr();
|
||||
|
||||
Mat image_1 = imread(string(ts.get_data_path()) + "grabcut/image1652.ppm", IMREAD_COLOR);
|
||||
Mat mask_1 = imread(string(ts.get_data_path()) + "grabcut/mask1652.ppm", IMREAD_GRAYSCALE);
|
||||
Rect roi_1(0, 0, 150, 150);
|
||||
|
||||
Mat image_2 = image_1.clone();
|
||||
Mat mask_2 = mask_1.clone();
|
||||
Rect roi_2 = roi_1;
|
||||
|
||||
Mat image_3 = image_1.clone();
|
||||
Mat mask_3 = mask_1.clone();
|
||||
Rect roi_3 = roi_1;
|
||||
|
||||
Mat bgdModel_1, fgdModel_1;
|
||||
Mat bgdModel_2, fgdModel_2;
|
||||
Mat bgdModel_3, fgdModel_3;
|
||||
|
||||
theRNG().state = 12378213;
|
||||
grabCut(image_1, mask_1, roi_1, bgdModel_1, fgdModel_1, 1, GC_INIT_WITH_MASK);
|
||||
theRNG().state = 12378213;
|
||||
grabCut(image_2, mask_2, roi_2, bgdModel_2, fgdModel_2, 1, GC_INIT_WITH_MASK);
|
||||
theRNG().state = 12378213;
|
||||
grabCut(image_3, mask_3, roi_3, bgdModel_3, fgdModel_3, 1, GC_INIT_WITH_MASK);
|
||||
|
||||
EXPECT_EQ(0, countNonZero(mask_1 != mask_2));
|
||||
EXPECT_EQ(0, countNonZero(mask_1 != mask_3));
|
||||
EXPECT_EQ(0, countNonZero(mask_2 != mask_3));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,230 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Imgproc_Hist_Calc, calcHist_regression_11544)
|
||||
{
|
||||
cv::Mat1w m = cv::Mat1w::zeros(10, 10);
|
||||
int n_images = 1;
|
||||
int channels[] = { 0 };
|
||||
cv::Mat mask;
|
||||
cv::MatND hist1, hist2;
|
||||
cv::MatND hist1_opt, hist2_opt;
|
||||
int dims = 1;
|
||||
int hist_size[] = { 1000 };
|
||||
float range1[] = { 0, 900 };
|
||||
float range2[] = { 0, 1000 };
|
||||
const float* ranges1[] = { range1 };
|
||||
const float* ranges2[] = { range2 };
|
||||
|
||||
setUseOptimized(false);
|
||||
cv::calcHist(&m, n_images, channels, mask, hist1, dims, hist_size, ranges1);
|
||||
cv::calcHist(&m, n_images, channels, mask, hist2, dims, hist_size, ranges2);
|
||||
|
||||
setUseOptimized(true);
|
||||
cv::calcHist(&m, n_images, channels, mask, hist1_opt, dims, hist_size, ranges1);
|
||||
cv::calcHist(&m, n_images, channels, mask, hist2_opt, dims, hist_size, ranges2);
|
||||
|
||||
for(int i = 0; i < 1000; i++)
|
||||
{
|
||||
EXPECT_EQ(hist1.at<float>(i), hist1_opt.at<float>(i)) << i;
|
||||
EXPECT_EQ(hist2.at<float>(i), hist2_opt.at<float>(i)) << i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_Hist_Calc, badarg)
|
||||
{
|
||||
const int channels[] = {0};
|
||||
float range1[] = {0, 10};
|
||||
float range2[] = {10, 20};
|
||||
const float * ranges[] = {range1, range2};
|
||||
Mat img = cv::Mat::zeros(10, 10, CV_8UC1);
|
||||
Mat imgInt = cv::Mat::zeros(10, 10, CV_32SC1);
|
||||
Mat hist;
|
||||
const int hist_size[] = { 100, 100 };
|
||||
// base run
|
||||
EXPECT_NO_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, hist_size, ranges, true));
|
||||
// bad parameters
|
||||
EXPECT_THROW(cv::calcHist(NULL, 1, channels, noArray(), hist, 1, hist_size, ranges, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcHist(&img, 0, channels, noArray(), hist, 1, hist_size, ranges, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcHist(&img, 1, NULL, noArray(), hist, 2, hist_size, ranges, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), noArray(), 1, hist_size, ranges, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, -1, hist_size, ranges, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, NULL, ranges, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcHist(&imgInt, 1, channels, noArray(), hist, 1, hist_size, NULL, true), cv::Exception);
|
||||
// special case
|
||||
EXPECT_NO_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, hist_size, NULL, true));
|
||||
|
||||
Mat backProj;
|
||||
// base run
|
||||
EXPECT_NO_THROW(cv::calcBackProject(&img, 1, channels, hist, backProj, ranges, 1, true));
|
||||
// bad parameters
|
||||
EXPECT_THROW(cv::calcBackProject(NULL, 1, channels, hist, backProj, ranges, 1, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcBackProject(&img, 0, channels, hist, backProj, ranges, 1, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcBackProject(&img, 1, channels, noArray(), backProj, ranges, 1, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcBackProject(&img, 1, channels, hist, noArray(), ranges, 1, true), cv::Exception);
|
||||
EXPECT_THROW(cv::calcBackProject(&imgInt, 1, channels, hist, backProj, NULL, 1, true), cv::Exception);
|
||||
// special case
|
||||
EXPECT_NO_THROW(cv::calcBackProject(&img, 1, channels, hist, backProj, NULL, 1, true));
|
||||
}
|
||||
|
||||
TEST(Imgproc_Hist_Calc, IPP_ranges_with_equal_exponent_21595)
|
||||
{
|
||||
const int channels[] = { 0 };
|
||||
float range1[] = { -0.5f, 1.5f };
|
||||
const float* ranges[] = { range1 };
|
||||
const int hist_size[] = { 2 };
|
||||
|
||||
uint8_t m[1][6] = { { 0, 1, 0, 1 , 1, 1 } };
|
||||
cv::Mat images_u = Mat(1, 6, CV_8UC1, m);
|
||||
cv::Mat histogram_u;
|
||||
cv::calcHist(&images_u, 1, channels, noArray(), histogram_u, 1, hist_size, ranges);
|
||||
|
||||
ASSERT_EQ(histogram_u.at<float>(0), 2.f) << "0 not counts correctly, res: " << histogram_u.at<float>(0);
|
||||
ASSERT_EQ(histogram_u.at<float>(1), 4.f) << "1 not counts correctly, res: " << histogram_u.at<float>(0);
|
||||
}
|
||||
|
||||
TEST(Imgproc_Hist_Calc, IPP_ranges_with_nonequal_exponent_21595)
|
||||
{
|
||||
const int channels[] = { 0 };
|
||||
float range1[] = { -1.3f, 1.5f };
|
||||
const float* ranges[] = { range1 };
|
||||
const int hist_size[] = { 3 };
|
||||
|
||||
uint8_t m[1][6] = { { 0, 1, 0, 1 , 1, 1 } };
|
||||
cv::Mat images_u = Mat(1, 6, CV_8UC1, m);
|
||||
cv::Mat histogram_u;
|
||||
cv::calcHist(&images_u, 1, channels, noArray(), histogram_u, 1, hist_size, ranges);
|
||||
|
||||
ASSERT_EQ(histogram_u.at<float>(0), 0.f) << "not equal to zero, res: " << histogram_u.at<float>(0);
|
||||
ASSERT_EQ(histogram_u.at<float>(1), 2.f) << "0 not counts correctly, res: " << histogram_u.at<float>(1);
|
||||
ASSERT_EQ(histogram_u.at<float>(2), 4.f) << "1 not counts correctly, res: " << histogram_u.at<float>(2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////// equalizeHist() /////////////////////////////////////////
|
||||
|
||||
void equalizeHistReference(const Mat& src, Mat& dst)
|
||||
{
|
||||
std::vector<int> hist(256, 0);
|
||||
for (int y = 0; y < src.rows; y++)
|
||||
{
|
||||
const uchar* srow = src.ptr(y);
|
||||
for (int x = 0; x < src.cols; x++)
|
||||
{
|
||||
hist[srow[x]]++;
|
||||
}
|
||||
}
|
||||
|
||||
int first = 0;
|
||||
while (!hist[first]) ++first;
|
||||
|
||||
int total = (int)src.total();
|
||||
if (hist[first] == total)
|
||||
{
|
||||
dst.setTo(first);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uchar> lut(256);
|
||||
lut[first] = 0;
|
||||
float scale = (255.f)/(total - hist[first]);
|
||||
|
||||
int sum = 0;
|
||||
for (int i = first + 1; i < 256; ++i)
|
||||
{
|
||||
sum += hist[i];
|
||||
lut[i] = saturate_cast<uchar>(sum * scale);
|
||||
}
|
||||
|
||||
cv::LUT(src, lut, dst);
|
||||
}
|
||||
|
||||
typedef ::testing::TestWithParam<std::tuple<cv::Size, int>> Imgproc_Equalize_Hist;
|
||||
|
||||
TEST_P(Imgproc_Equalize_Hist, accuracy)
|
||||
{
|
||||
auto p = GetParam();
|
||||
cv::Size size = std::get<0>(p);
|
||||
int idx = std::get<1>(p);
|
||||
|
||||
RNG &rng = cvtest::TS::ptr()->get_rng();
|
||||
rng.state += idx;
|
||||
|
||||
cv::Mat src(size, CV_8U);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
cv::Mat dst, gold;
|
||||
|
||||
equalizeHistReference(src, gold);
|
||||
|
||||
cv::equalizeHist(src, dst);
|
||||
|
||||
ASSERT_EQ(CV_8UC1, dst.type());
|
||||
ASSERT_EQ(gold.size(), dst.size());
|
||||
|
||||
EXPECT_MAT_NEAR(dst, gold, 1);
|
||||
EXPECT_MAT_N_DIFF(dst, gold, 0.05 * size.area()); // The 5% range could be accomodated to HAL
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Imgproc_Hist, Imgproc_Equalize_Hist, ::testing::Combine(
|
||||
::testing::Values(cv::Size(123, 321), cv::Size(256, 256), cv::Size(1024, 768)),
|
||||
::testing::Range(0, 10)));
|
||||
|
||||
// See https://github.com/opencv/opencv/issues/24757
|
||||
TEST(Imgproc_Hist_Compare, intersect_regression_24757)
|
||||
{
|
||||
cv::Mat src1 = cv::Mat::zeros(128,1, CV_32FC1);
|
||||
cv::Mat src2 = cv::Mat(128,1, CV_32FC1, cv::Scalar(std::numeric_limits<double>::max()));
|
||||
|
||||
// Ideal result Wrong result
|
||||
src1.at<float>(32 * 0,0) = +1.0f; // work = +1.0 +1.0
|
||||
src1.at<float>(32 * 1,0) = +55555555.5f; // work = +55555556.5 +55555555.5
|
||||
src1.at<float>(32 * 2,0) = -55555555.5f; // work = +1.0 0.0
|
||||
src1.at<float>(32 * 3,0) = -1.0f; // work = 0.0 -1.0
|
||||
|
||||
EXPECT_DOUBLE_EQ(compareHist(src1, src2, cv::HISTCMP_INTERSECT), 0.0);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
/* End Of 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.
|
||||
//
|
||||
//
|
||||
// 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) 2014, Itseez, 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 {
|
||||
|
||||
#ifndef DEBUG_IMAGES
|
||||
#define DEBUG_IMAGES 0
|
||||
#endif
|
||||
|
||||
//#define GENERATE_DATA // generate data in debug mode via CPU code path (without IPP / OpenCL and other accelerators)
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
static string getTestCaseName(const string& picture_name, double minDist, double edgeThreshold, double accumThreshold, int minRadius, int maxRadius)
|
||||
{
|
||||
string results_name = cv::format("circles_%s_%.0f_%.0f_%.0f_%d_%d",
|
||||
picture_name.c_str(), minDist, edgeThreshold, accumThreshold, minRadius, maxRadius);
|
||||
string temp(results_name);
|
||||
size_t pos = temp.find_first_of("\\/.");
|
||||
while (pos != string::npos) {
|
||||
temp.replace(pos, 1, "_");
|
||||
pos = temp.find_first_of("\\/.");
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
#if DEBUG_IMAGES
|
||||
static void highlightCircles(const string& imagePath, const vector<Vec3f>& circles, const string& outputImagePath)
|
||||
{
|
||||
Mat imgDebug = imread(imagePath, IMREAD_COLOR);
|
||||
const Scalar yellow(0, 255, 255);
|
||||
|
||||
for (vector<Vec3f>::const_iterator iter = circles.begin(); iter != circles.end(); ++iter)
|
||||
{
|
||||
const Vec3f& circle = *iter;
|
||||
float x = circle[0];
|
||||
float y = circle[1];
|
||||
float r = max(circle[2], 2.0f);
|
||||
cv::circle(imgDebug, Point(int(x), int(y)), int(r), yellow);
|
||||
}
|
||||
imwrite(outputImagePath, imgDebug);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef tuple<string, double, double, double, int, int> Image_MinDist_EdgeThreshold_AccumThreshold_MinRadius_MaxRadius_t;
|
||||
class HoughCirclesTestFixture : public testing::TestWithParam<Image_MinDist_EdgeThreshold_AccumThreshold_MinRadius_MaxRadius_t>
|
||||
{
|
||||
string picture_name;
|
||||
double minDist;
|
||||
double edgeThreshold;
|
||||
double accumThreshold;
|
||||
int minRadius;
|
||||
int maxRadius;
|
||||
|
||||
public:
|
||||
HoughCirclesTestFixture()
|
||||
{
|
||||
picture_name = get<0>(GetParam());
|
||||
minDist = get<1>(GetParam());
|
||||
edgeThreshold = get<2>(GetParam());
|
||||
accumThreshold = get<3>(GetParam());
|
||||
minRadius = get<4>(GetParam());
|
||||
maxRadius = get<5>(GetParam());
|
||||
}
|
||||
|
||||
HoughCirclesTestFixture(const string& picture, double minD, double edge, double accum, int minR, int maxR) :
|
||||
picture_name(picture), minDist(minD), edgeThreshold(edge), accumThreshold(accum), minRadius(minR), maxRadius(maxR)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename CircleType>
|
||||
void run_test(const char* xml_name)
|
||||
{
|
||||
string test_case_name = getTestCaseName(picture_name, minDist, edgeThreshold, accumThreshold, minRadius, maxRadius);
|
||||
string filename = cvtest::TS::ptr()->get_data_path() + picture_name;
|
||||
Mat src = imread(filename, IMREAD_GRAYSCALE);
|
||||
EXPECT_FALSE(src.empty()) << "Invalid test image: " << filename;
|
||||
|
||||
GaussianBlur(src, src, Size(9, 9), 2, 2);
|
||||
|
||||
vector<CircleType> circles;
|
||||
const double dp = 1.0;
|
||||
HoughCircles(src, circles, cv::HOUGH_GRADIENT, dp, minDist, edgeThreshold, accumThreshold, minRadius, maxRadius);
|
||||
|
||||
string imgProc = string(cvtest::TS::ptr()->get_data_path()) + "imgproc/";
|
||||
#if DEBUG_IMAGES
|
||||
highlightCircles(filename, circles, imgProc + test_case_name + ".png");
|
||||
#endif
|
||||
|
||||
string xml = imgProc + xml_name;
|
||||
#ifdef GENERATE_DATA
|
||||
{
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
ASSERT_TRUE(!fs.isOpened() || fs[test_case_name].empty());
|
||||
}
|
||||
{
|
||||
FileStorage fs(xml, FileStorage::APPEND);
|
||||
EXPECT_TRUE(fs.isOpened()) << "Cannot open sanity data file: " << xml;
|
||||
fs << test_case_name << circles;
|
||||
}
|
||||
#else
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
FileNode node = fs[test_case_name];
|
||||
ASSERT_FALSE(node.empty()) << "Missing test data: " << test_case_name << std::endl << "XML: " << xml;
|
||||
vector<CircleType> exp_circles;
|
||||
read(fs[test_case_name], exp_circles, vector<CircleType>());
|
||||
fs.release();
|
||||
EXPECT_EQ(exp_circles.size(), circles.size());
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(HoughCirclesTestFixture, regression)
|
||||
{
|
||||
run_test<Vec3f>("HoughCircles.xml");
|
||||
}
|
||||
|
||||
TEST_P(HoughCirclesTestFixture, regression4f)
|
||||
{
|
||||
run_test<Vec4f>("HoughCircles4f.xml");
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ImgProc, HoughCirclesTestFixture, testing::Combine(
|
||||
// picture_name:
|
||||
testing::Values("imgproc/stuff.jpg"),
|
||||
// minDist:
|
||||
testing::Values(20),
|
||||
// edgeThreshold:
|
||||
testing::Values(20),
|
||||
// accumThreshold:
|
||||
testing::Values(30),
|
||||
// minRadius:
|
||||
testing::Values(20),
|
||||
// maxRadius:
|
||||
testing::Values(200)
|
||||
));
|
||||
|
||||
|
||||
class HoughCirclesTest : public testing::TestWithParam<HoughModes>
|
||||
{
|
||||
protected:
|
||||
HoughModes method;
|
||||
public:
|
||||
HoughCirclesTest() { method = GetParam(); }
|
||||
};
|
||||
|
||||
TEST_P(HoughCirclesTest, DefaultMaxRadius)
|
||||
{
|
||||
string picture_name = "imgproc/stuff.jpg";
|
||||
string filename = cvtest::TS::ptr()->get_data_path() + picture_name;
|
||||
Mat src = imread(filename, IMREAD_GRAYSCALE);
|
||||
EXPECT_FALSE(src.empty()) << "Invalid test image: " << filename;
|
||||
GaussianBlur(src, src, Size(9, 9), 2, 2);
|
||||
|
||||
double dp = 1.0;
|
||||
double minDist = 20.0;
|
||||
double edgeThreshold = 20.0;
|
||||
double param2 = method == HOUGH_GRADIENT_ALT ? 0.9 : 30.;
|
||||
int minRadius = method == HOUGH_GRADIENT_ALT ? 10 : 20;
|
||||
int maxRadius = 0;
|
||||
|
||||
vector<Vec3f> circles;
|
||||
vector<Vec4f> circles4f;
|
||||
HoughCircles(src, circles, method, dp, minDist, edgeThreshold, param2, minRadius, maxRadius);
|
||||
HoughCircles(src, circles4f, method, dp, minDist, edgeThreshold, param2, minRadius, maxRadius);
|
||||
|
||||
#if DEBUG_IMAGES
|
||||
string imgProc = string(cvtest::TS::ptr()->get_data_path()) + "imgproc/";
|
||||
highlightCircles(filename, circles, imgProc + "HoughCirclesTest_DefaultMaxRadius.png");
|
||||
#endif
|
||||
|
||||
int maxDimension = std::max(src.rows, src.cols);
|
||||
|
||||
if(method == HOUGH_GRADIENT_ALT)
|
||||
{
|
||||
EXPECT_EQ(circles.size(), size_t(3)) << "Should find 3 circles";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_GT(circles.size(), size_t(0)) << "Should find at least some circles";
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < circles.size(); ++i)
|
||||
{
|
||||
EXPECT_GE(circles[i][2], minRadius) << "Radius should be >= minRadius";
|
||||
EXPECT_LE(circles[i][2], maxDimension) << "Radius should be <= max image dimension";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(HoughCirclesTest, CentersOnly)
|
||||
{
|
||||
string picture_name = "imgproc/stuff.jpg";
|
||||
string filename = cvtest::TS::ptr()->get_data_path() + picture_name;
|
||||
Mat src = imread(filename, IMREAD_GRAYSCALE);
|
||||
EXPECT_FALSE(src.empty()) << "Invalid test image: " << filename;
|
||||
|
||||
GaussianBlur(src, src, Size(9, 9), 2, 2);
|
||||
double dp = 1.0;
|
||||
double minDist = 20.0;
|
||||
double edgeThreshold = 20.0;
|
||||
double param2 = method == HOUGH_GRADIENT_ALT ? 0.9 : 30.;
|
||||
int minRadius = method == HOUGH_GRADIENT_ALT ? 10 : 20;
|
||||
int maxRadius = -1;
|
||||
|
||||
vector<Vec3f> circles;
|
||||
vector<Vec4f> circles4f;
|
||||
|
||||
HoughCircles(src, circles, method, dp, minDist, edgeThreshold, param2, minRadius, maxRadius);
|
||||
HoughCircles(src, circles4f, method, dp, minDist, edgeThreshold, param2, minRadius, maxRadius);
|
||||
|
||||
#if DEBUG_IMAGES
|
||||
string imgProc = string(cvtest::TS::ptr()->get_data_path()) + "imgproc/";
|
||||
highlightCircles(filename, circles, imgProc + "HoughCirclesTest_DefaultMaxRadius.png");
|
||||
#endif
|
||||
|
||||
if(method == HOUGH_GRADIENT_ALT)
|
||||
{
|
||||
EXPECT_EQ(circles.size(), size_t(3)) << "Should find 3 circles";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_GT(circles.size(), size_t(0)) << "Should find at least some circles";
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < circles.size(); ++i)
|
||||
{
|
||||
if( method == HOUGH_GRADIENT )
|
||||
{
|
||||
EXPECT_EQ(circles[i][2], 0.0f) << "Did not ask for radius";
|
||||
}
|
||||
EXPECT_EQ(circles[i][0], circles4f[i][0]);
|
||||
EXPECT_EQ(circles[i][1], circles4f[i][1]);
|
||||
EXPECT_EQ(circles[i][2], circles4f[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(HoughCirclesTest, ManySmallCircles)
|
||||
{
|
||||
string picture_name = "imgproc/beads.jpg";
|
||||
|
||||
string filename = cvtest::TS::ptr()->get_data_path() + picture_name;
|
||||
Mat src = imread(filename, IMREAD_GRAYSCALE);
|
||||
EXPECT_FALSE(src.empty()) << "Invalid test image: " << filename;
|
||||
|
||||
const double dp = method == HOUGH_GRADIENT_ALT ? 1.5 : 1.0;
|
||||
double minDist = 10;
|
||||
double edgeThreshold = 90;
|
||||
double accumThreshold = 11;
|
||||
double minCos2 = 0.85;
|
||||
double param2 = method == HOUGH_GRADIENT_ALT ? minCos2 : accumThreshold;
|
||||
int minRadius = 7;
|
||||
int maxRadius = 18;
|
||||
int ncircles_min = method == HOUGH_GRADIENT_ALT ? 2000 : 3000;
|
||||
|
||||
Mat src_smooth;
|
||||
if( method == HOUGH_GRADIENT_ALT )
|
||||
GaussianBlur(src, src_smooth, Size(7, 7), 1.5, 1.5);
|
||||
else
|
||||
src.copyTo(src_smooth);
|
||||
vector<Vec3f> circles;
|
||||
vector<Vec4f> circles4f;
|
||||
HoughCircles(src_smooth, circles, method, dp, minDist, edgeThreshold, param2, minRadius, maxRadius);
|
||||
HoughCircles(src_smooth, circles4f, method, dp, minDist, edgeThreshold, param2, minRadius, maxRadius);
|
||||
|
||||
#if DEBUG_IMAGES
|
||||
string imgProc = string(cvtest::TS::ptr()->get_data_path()) + "imgproc/";
|
||||
string test_case_name = getTestCaseName(picture_name, minDist, edgeThreshold, accumThreshold, minRadius, maxRadius);
|
||||
highlightCircles(filename, circles, imgProc + test_case_name + ".png");
|
||||
#endif
|
||||
|
||||
EXPECT_GT(circles.size(), size_t(ncircles_min)) << "Should find a lot of circles";
|
||||
EXPECT_EQ(circles.size(), circles4f.size());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(HoughGradient, HoughCirclesTest, testing::Values(HOUGH_GRADIENT));
|
||||
INSTANTIATE_TEST_CASE_P(HoughGradientAlt, HoughCirclesTest, testing::Values(HOUGH_GRADIENT_ALT));
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,473 @@
|
||||
/*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) 2014, Itseez, 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"
|
||||
|
||||
//#define GENERATE_DATA // generate data in debug mode via CPU code path (without IPP / OpenCL and other accelerators)
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
template<typename T>
|
||||
struct SimilarWith
|
||||
{
|
||||
T value;
|
||||
float theta_eps;
|
||||
float rho_eps;
|
||||
SimilarWith(T val, float e, float r_e): value(val), theta_eps(e), rho_eps(r_e) { }
|
||||
bool operator()(const T& other);
|
||||
};
|
||||
|
||||
template<>
|
||||
bool SimilarWith<Vec2f>::operator()(const Vec2f& other)
|
||||
{
|
||||
return std::abs(other[0] - value[0]) < rho_eps && std::abs(other[1] - value[1]) < theta_eps;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool SimilarWith<Vec3f>::operator()(const Vec3f& other)
|
||||
{
|
||||
return std::abs(other[0] - value[0]) < rho_eps && std::abs(other[1] - value[1]) < theta_eps;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool SimilarWith<Vec4i>::operator()(const Vec4i& other)
|
||||
{
|
||||
return cv::norm(value, other) < theta_eps;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int countMatIntersection(const Mat& expect, const Mat& actual, float eps, float rho_eps)
|
||||
{
|
||||
int count = 0;
|
||||
if (!expect.empty() && !actual.empty())
|
||||
{
|
||||
for (MatConstIterator_<T> it=expect.begin<T>(); it!=expect.end<T>(); it++)
|
||||
{
|
||||
MatConstIterator_<T> f = std::find_if(actual.begin<T>(), actual.end<T>(), SimilarWith<T>(*it, eps, rho_eps));
|
||||
if (f != actual.end<T>())
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
String getTestCaseName(String filename)
|
||||
{
|
||||
string temp(filename);
|
||||
size_t pos = temp.find_first_of("\\/.");
|
||||
while ( pos != string::npos ) {
|
||||
temp.replace( pos, 1, "_" );
|
||||
pos = temp.find_first_of("\\/.");
|
||||
}
|
||||
return String(temp);
|
||||
}
|
||||
|
||||
class BaseHoughLineTest
|
||||
{
|
||||
public:
|
||||
enum {STANDART = 0, PROBABILISTIC};
|
||||
protected:
|
||||
template<typename LinesType, typename LineType>
|
||||
void run_test(int type, const char* xml_name);
|
||||
|
||||
string picture_name;
|
||||
double rhoStep;
|
||||
double thetaStep;
|
||||
int threshold;
|
||||
int minLineLength;
|
||||
int maxGap;
|
||||
};
|
||||
|
||||
typedef tuple<string, double, double, int> Image_RhoStep_ThetaStep_Threshold_t;
|
||||
class StandartHoughLinesTest : public BaseHoughLineTest, public testing::TestWithParam<Image_RhoStep_ThetaStep_Threshold_t>
|
||||
{
|
||||
public:
|
||||
StandartHoughLinesTest()
|
||||
{
|
||||
picture_name = get<0>(GetParam());
|
||||
rhoStep = get<1>(GetParam());
|
||||
thetaStep = get<2>(GetParam());
|
||||
threshold = get<3>(GetParam());
|
||||
minLineLength = 0;
|
||||
maxGap = 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef tuple<string, double, double, int, int, int> Image_RhoStep_ThetaStep_Threshold_MinLine_MaxGap_t;
|
||||
class ProbabilisticHoughLinesTest : public BaseHoughLineTest, public testing::TestWithParam<Image_RhoStep_ThetaStep_Threshold_MinLine_MaxGap_t>
|
||||
{
|
||||
public:
|
||||
ProbabilisticHoughLinesTest()
|
||||
{
|
||||
picture_name = get<0>(GetParam());
|
||||
rhoStep = get<1>(GetParam());
|
||||
thetaStep = get<2>(GetParam());
|
||||
threshold = get<3>(GetParam());
|
||||
minLineLength = get<4>(GetParam());
|
||||
maxGap = get<5>(GetParam());
|
||||
}
|
||||
};
|
||||
|
||||
typedef tuple<double, double, double, double> HoughLinesPointSetInput_t;
|
||||
class HoughLinesPointSetTest : public testing::TestWithParam<HoughLinesPointSetInput_t>
|
||||
{
|
||||
protected:
|
||||
void run_test();
|
||||
double Rho;
|
||||
double Theta;
|
||||
double rhoMin, rhoMax, rhoStep;
|
||||
double thetaMin, thetaMax, thetaStep;
|
||||
public:
|
||||
HoughLinesPointSetTest()
|
||||
{
|
||||
rhoMin = get<0>(GetParam());
|
||||
rhoMax = get<1>(GetParam());
|
||||
rhoStep = (rhoMax - rhoMin) / 360.0f;
|
||||
thetaMin = get<2>(GetParam());
|
||||
thetaMax = get<3>(GetParam());
|
||||
thetaStep = CV_PI / 180.0f;
|
||||
Rho = 320.00000;
|
||||
Theta = 1.04719;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LinesType, typename LineType>
|
||||
void BaseHoughLineTest::run_test(int type, const char* xml_name)
|
||||
{
|
||||
string filename = cvtest::TS::ptr()->get_data_path() + picture_name;
|
||||
Mat src = imread(filename, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(src.empty()) << "Invalid test image: " << filename;
|
||||
|
||||
string xml = string(cvtest::TS::ptr()->get_data_path()) + "imgproc/" + xml_name;
|
||||
|
||||
Mat dst;
|
||||
Canny(src, dst, 100, 150, 3);
|
||||
ASSERT_FALSE(dst.empty()) << "Failed Canny edge detector";
|
||||
|
||||
LinesType lines;
|
||||
if (type == STANDART)
|
||||
HoughLines(dst, lines, rhoStep, thetaStep, threshold, 0, 0);
|
||||
else if (type == PROBABILISTIC)
|
||||
HoughLinesP(dst, lines, rhoStep, thetaStep, threshold, minLineLength, maxGap);
|
||||
|
||||
String test_case_name = format("lines_%s_%.0f_%.2f_%d_%d_%d", picture_name.c_str(), rhoStep, thetaStep,
|
||||
threshold, minLineLength, maxGap);
|
||||
test_case_name = getTestCaseName(test_case_name);
|
||||
|
||||
#ifdef GENERATE_DATA
|
||||
{
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
ASSERT_TRUE(!fs.isOpened() || fs[test_case_name].empty());
|
||||
}
|
||||
{
|
||||
FileStorage fs(xml, FileStorage::APPEND);
|
||||
EXPECT_TRUE(fs.isOpened()) << "Cannot open sanity data file: " << xml;
|
||||
fs << test_case_name << Mat(lines);
|
||||
}
|
||||
#else
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
FileNode node = fs[test_case_name];
|
||||
ASSERT_FALSE(node.empty()) << "Missing test data: " << test_case_name << std::endl << "XML: " << xml;
|
||||
|
||||
Mat exp_lines_;
|
||||
read(fs[test_case_name], exp_lines_, Mat());
|
||||
fs.release();
|
||||
LinesType exp_lines;
|
||||
exp_lines_.copyTo(exp_lines);
|
||||
|
||||
int count = -1;
|
||||
if (type == STANDART)
|
||||
count = countMatIntersection<LineType>(Mat(exp_lines), Mat(lines), (float) thetaStep + FLT_EPSILON, (float) rhoStep + FLT_EPSILON);
|
||||
else if (type == PROBABILISTIC)
|
||||
count = countMatIntersection<LineType>(Mat(exp_lines), Mat(lines), 1e-4f, 0.f);
|
||||
|
||||
#if defined HAVE_IPP && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_HOUGH
|
||||
EXPECT_LE(std::abs((double)count - Mat(exp_lines).total()), Mat(exp_lines).total() * 0.25)
|
||||
<< "count=" << count << " expected=" << Mat(exp_lines).total();
|
||||
#else
|
||||
EXPECT_EQ(count, (int)Mat(exp_lines).total());
|
||||
#endif
|
||||
#endif // GENERATE_DATA
|
||||
}
|
||||
|
||||
void HoughLinesPointSetTest::run_test(void)
|
||||
{
|
||||
Mat lines_f, lines_i;
|
||||
vector<Point2f> pointf;
|
||||
vector<Point2i> pointi;
|
||||
vector<Vec3d> line_polar_f, line_polar_i;
|
||||
const float Points[20][2] = {
|
||||
{ 0.0f, 369.0f }, { 10.0f, 364.0f }, { 20.0f, 358.0f }, { 30.0f, 352.0f },
|
||||
{ 40.0f, 346.0f }, { 50.0f, 341.0f }, { 60.0f, 335.0f }, { 70.0f, 329.0f },
|
||||
{ 80.0f, 323.0f }, { 90.0f, 318.0f }, { 100.0f, 312.0f }, { 110.0f, 306.0f },
|
||||
{ 120.0f, 300.0f }, { 130.0f, 295.0f }, { 140.0f, 289.0f }, { 150.0f, 284.0f },
|
||||
{ 160.0f, 277.0f }, { 170.0f, 271.0f }, { 180.0f, 266.0f }, { 190.0f, 260.0f }
|
||||
};
|
||||
|
||||
// Float
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
pointf.push_back(Point2f(Points[i][0],Points[i][1]));
|
||||
}
|
||||
|
||||
HoughLinesPointSet(pointf, lines_f, 20, 1,
|
||||
rhoMin, rhoMax, rhoStep,
|
||||
thetaMin, thetaMax, thetaStep);
|
||||
|
||||
lines_f.copyTo( line_polar_f );
|
||||
|
||||
// Integer
|
||||
for( int i = 0; i < 20; i++ )
|
||||
{
|
||||
pointi.push_back( Point2i( (int)Points[i][0], (int)Points[i][1] ) );
|
||||
}
|
||||
|
||||
HoughLinesPointSet( pointi, lines_i, 20, 1,
|
||||
rhoMin, rhoMax, rhoStep,
|
||||
thetaMin, thetaMax, thetaStep );
|
||||
|
||||
lines_i.copyTo( line_polar_i );
|
||||
|
||||
EXPECT_EQ((int)(line_polar_f.at(0).val[1] * 100000.0f), (int)(Rho * 100000.0f));
|
||||
EXPECT_EQ((int)(line_polar_f.at(0).val[2] * 100000.0f), (int)(Theta * 100000.0f));
|
||||
EXPECT_EQ((int)(line_polar_i.at(0).val[1] * 100000.0f), (int)(Rho * 100000.0f));
|
||||
EXPECT_EQ((int)(line_polar_i.at(0).val[2] * 100000.0f), (int)(Theta * 100000.0f));
|
||||
}
|
||||
|
||||
TEST_P(StandartHoughLinesTest, regression)
|
||||
{
|
||||
run_test<Mat, Vec2f>(STANDART, "HoughLines.xml");
|
||||
}
|
||||
|
||||
TEST_P(ProbabilisticHoughLinesTest, regression)
|
||||
{
|
||||
run_test<Mat, Vec4i>(PROBABILISTIC, "HoughLinesP.xml");
|
||||
}
|
||||
|
||||
TEST_P(StandartHoughLinesTest, regression_Vec2f)
|
||||
{
|
||||
run_test<std::vector<Vec2f>, Vec2f>(STANDART, "HoughLines2f.xml");
|
||||
}
|
||||
|
||||
TEST_P(StandartHoughLinesTest, regression_Vec3f)
|
||||
{
|
||||
run_test<std::vector<Vec3f>, Vec3f>(STANDART, "HoughLines3f.xml");
|
||||
}
|
||||
|
||||
TEST_P(HoughLinesPointSetTest, regression)
|
||||
{
|
||||
run_test();
|
||||
}
|
||||
|
||||
TEST(HoughLinesPointSet, regression_21029)
|
||||
{
|
||||
std::vector<Point2f> points;
|
||||
points.push_back(Point2f(100, 100));
|
||||
points.push_back(Point2f(1000, 1000));
|
||||
points.push_back(Point2f(10000, 10000));
|
||||
points.push_back(Point2f(100000, 100000));
|
||||
|
||||
double rhoMin = 0;
|
||||
double rhoMax = 10;
|
||||
double rhoStep = 0.1;
|
||||
|
||||
double thetaMin = 85 * CV_PI / 180.0;
|
||||
double thetaMax = 95 * CV_PI / 180.0;
|
||||
double thetaStep = 1 * CV_PI / 180.0;
|
||||
|
||||
int lines_max = 5;
|
||||
int threshold = 100;
|
||||
|
||||
Mat lines;
|
||||
|
||||
HoughLinesPointSet(points, lines,
|
||||
lines_max, threshold,
|
||||
rhoMin, rhoMax, rhoStep,
|
||||
thetaMin, thetaMax, thetaStep
|
||||
);
|
||||
|
||||
EXPECT_TRUE(lines.empty());
|
||||
}
|
||||
|
||||
TEST(HoughLines, regression_21983)
|
||||
{
|
||||
Mat img(200, 200, CV_8UC1, Scalar(0));
|
||||
line(img, Point(0, 100), Point(100, 100), Scalar(255));
|
||||
std::vector<Vec2f> lines;
|
||||
HoughLines(img, lines, 1, CV_PI/180, 90, 0, 0, 0.001, 1.58);
|
||||
ASSERT_EQ(lines.size(), 1U);
|
||||
EXPECT_EQ(lines[0][0], 100);
|
||||
EXPECT_NEAR(lines[0][1], 1.57179642, 1e-4);
|
||||
}
|
||||
|
||||
TEST(HoughLines, regression_25038_vertical)
|
||||
{
|
||||
cv::Mat img = cv::Mat::zeros(8, 8, CV_8UC1);
|
||||
img.col(3).setTo(255);
|
||||
|
||||
cv::Mat lines;
|
||||
cv::HoughLines(img, lines, 0.5, CV_PI/4., 2);
|
||||
EXPECT_EQ(1, lines.cols);
|
||||
EXPECT_EQ(1, lines.rows);
|
||||
EXPECT_EQ(2, lines.channels());
|
||||
EXPECT_NEAR(3, lines.at<cv::Vec2f>(0)[0], 1e-5);
|
||||
EXPECT_NEAR(0, lines.at<cv::Vec2f>(0)[1], 1e-5);
|
||||
|
||||
cv::HoughLines(img, lines, 0.05, CV_PI/4., 2);
|
||||
EXPECT_EQ(1, lines.cols);
|
||||
EXPECT_EQ(1, lines.rows);
|
||||
EXPECT_EQ(2, lines.channels());
|
||||
EXPECT_NEAR(3, lines.at<cv::Vec2f>(0)[0], 1e-5);
|
||||
EXPECT_NEAR(0, lines.at<cv::Vec2f>(0)[1], 1e-5);
|
||||
}
|
||||
|
||||
TEST(HoughLines, regression_25038_even)
|
||||
{
|
||||
cv::Mat img = cv::Mat::zeros(8, 8, CV_8UC1);
|
||||
img.col(4).setTo(255);
|
||||
|
||||
cv::Mat lines;
|
||||
cv::HoughLines(img, lines, 0.5, CV_PI/4., 2);
|
||||
EXPECT_EQ(1, lines.cols);
|
||||
EXPECT_EQ(1, lines.rows);
|
||||
EXPECT_EQ(2, lines.channels());
|
||||
EXPECT_NEAR(4, lines.at<cv::Vec2f>(0)[0], 1e-5);
|
||||
EXPECT_NEAR(0, lines.at<cv::Vec2f>(0)[1], 1e-5);
|
||||
|
||||
cv::HoughLines(img, lines, 0.05, CV_PI/4., 2);
|
||||
EXPECT_EQ(1, lines.cols);
|
||||
EXPECT_EQ(1, lines.rows);
|
||||
EXPECT_EQ(2, lines.channels());
|
||||
EXPECT_NEAR(4, lines.at<cv::Vec2f>(0)[0], 1e-5);
|
||||
EXPECT_NEAR(0, lines.at<cv::Vec2f>(0)[1], 1e-5);
|
||||
}
|
||||
|
||||
TEST(HoughLines, regression_25038_horizontal)
|
||||
{
|
||||
cv::Mat img = cv::Mat::zeros(8, 8, CV_8UC1);
|
||||
img.row(3).setTo(255);
|
||||
|
||||
cv::Mat lines;
|
||||
cv::HoughLines(img, lines, 0.5, CV_PI/4., 2);
|
||||
EXPECT_EQ(1, lines.cols);
|
||||
EXPECT_EQ(1, lines.rows);
|
||||
EXPECT_EQ(2, lines.channels());
|
||||
EXPECT_NEAR(3, lines.at<cv::Vec2f>(0)[0], 1e-5);
|
||||
EXPECT_NEAR(CV_PI/2., lines.at<cv::Vec2f>(0)[1], 1e-5);
|
||||
|
||||
cv::HoughLines(img, lines, 0.05, CV_PI/4., 2);
|
||||
EXPECT_EQ(1, lines.cols);
|
||||
EXPECT_EQ(1, lines.rows);
|
||||
EXPECT_EQ(2, lines.channels());
|
||||
EXPECT_NEAR(3, lines.at<cv::Vec2f>(0)[0], 1e-5);
|
||||
EXPECT_NEAR(CV_PI/2., lines.at<cv::Vec2f>(0)[1], 1e-5);
|
||||
}
|
||||
|
||||
TEST(WeightedHoughLines, horizontal)
|
||||
{
|
||||
Mat img(25, 25, CV_8UC1, Scalar(0));
|
||||
// draw lines. from top to bottom, stronger to weaker.
|
||||
line(img, Point(0, 6), Point(25, 6), Scalar(240));
|
||||
line(img, Point(0, 12), Point(25, 12), Scalar(255));
|
||||
line(img, Point(0, 18), Point(25, 18), Scalar(220));
|
||||
|
||||
// detect lines
|
||||
std::vector<Vec2f> lines;
|
||||
int threshold{220*25-1};
|
||||
bool use_edgeval{true};
|
||||
HoughLines(img, lines, 1, CV_PI/180, threshold, 0, 0, 0.0, CV_PI, use_edgeval);
|
||||
|
||||
// check results
|
||||
ASSERT_EQ(3U, lines.size());
|
||||
// detected lines is assumed sorted from stronger to weaker.
|
||||
EXPECT_EQ(12, lines[0][0]);
|
||||
EXPECT_EQ(6, lines[1][0]);
|
||||
EXPECT_EQ(18, lines[2][0]);
|
||||
EXPECT_NEAR(CV_PI/2, lines[0][1], CV_PI/180 + 1e-6);
|
||||
EXPECT_NEAR(CV_PI/2, lines[1][1], CV_PI/180 + 1e-6);
|
||||
EXPECT_NEAR(CV_PI/2, lines[2][1], CV_PI/180 + 1e-6);
|
||||
}
|
||||
|
||||
TEST(WeightedHoughLines, diagonal)
|
||||
{
|
||||
Mat img(25, 25, CV_8UC1, Scalar(0));
|
||||
// draw lines.
|
||||
line(img, Point(0, 0), Point(25, 25), Scalar(128));
|
||||
line(img, Point(0, 25), Point(25, 0), Scalar(255));
|
||||
|
||||
// detect lines
|
||||
std::vector<Vec2f> lines;
|
||||
int threshold{128*25-1};
|
||||
bool use_edgeval{true};
|
||||
HoughLines(img, lines, 1, CV_PI/180, threshold, 0, 0, 0.0, CV_PI, use_edgeval);
|
||||
|
||||
// check results
|
||||
ASSERT_EQ(2U, lines.size());
|
||||
// detected lines is assumed sorted from stronger to weaker.
|
||||
EXPECT_EQ(18, lines[0][0]); // 25*sqrt(2)/2 = 17.67 ~ 18
|
||||
EXPECT_EQ(0, lines[1][0]);
|
||||
EXPECT_NEAR(CV_PI/4, lines[0][1], CV_PI/180 + 1e-6);
|
||||
EXPECT_NEAR(CV_PI*3/4, lines[1][1], CV_PI/180 + 1e-6);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P( ImgProc, StandartHoughLinesTest, testing::Combine(testing::Values( "shared/pic5.png", "../stitching/a1.png" ),
|
||||
testing::Values( 1, 10 ),
|
||||
testing::Values( 0.05, 0.1 ),
|
||||
testing::Values( 80, 150 )
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P( ImgProc, ProbabilisticHoughLinesTest, testing::Combine(testing::Values( "shared/pic5.png", "shared/pic1.png" ),
|
||||
testing::Values( 5, 10 ),
|
||||
testing::Values( 0.05, 0.1 ),
|
||||
testing::Values( 75, 150 ),
|
||||
testing::Values( 0, 10 ),
|
||||
testing::Values( 0, 4 )
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P( Imgproc, HoughLinesPointSetTest, testing::Combine(testing::Values( 0.0f, 120.0f ),
|
||||
testing::Values( 360.0f, 480.0f ),
|
||||
testing::Values( 0.0f, (CV_PI / 18.0f) ),
|
||||
testing::Values( (CV_PI / 2.0f), (CV_PI * 5.0f / 12.0f) )
|
||||
));
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,84 @@
|
||||
/*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_ImgprocUMatTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ImgprocUMatTest() {}
|
||||
~CV_ImgprocUMatTest() {}
|
||||
protected:
|
||||
void run(int)
|
||||
{
|
||||
string imgpath = string(ts->get_data_path()) + "shared/lena.png";
|
||||
Mat img = imread(imgpath, IMREAD_COLOR), gray, smallimg, result;
|
||||
UMat uimg = img.getUMat(ACCESS_READ), ugray, usmallimg, uresult;
|
||||
|
||||
cvtColor(img, gray, COLOR_BGR2GRAY);
|
||||
resize(gray, smallimg, Size(), 0.75, 0.75, INTER_LINEAR_EXACT);
|
||||
equalizeHist(smallimg, result);
|
||||
|
||||
cvtColor(uimg, ugray, COLOR_BGR2GRAY);
|
||||
resize(ugray, usmallimg, Size(), 0.75, 0.75, INTER_LINEAR_EXACT);
|
||||
equalizeHist(usmallimg, uresult);
|
||||
|
||||
#if 0
|
||||
imshow("orig", uimg);
|
||||
imshow("small", usmallimg);
|
||||
imshow("equalized gray", uresult);
|
||||
waitKey();
|
||||
destroyWindow("orig");
|
||||
destroyWindow("small");
|
||||
destroyWindow("equalized gray");
|
||||
#endif
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
|
||||
(void)uresult.getMat(ACCESS_READ);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Imgproc_UMat, regression) { CV_ImgprocUMatTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
// 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"
|
||||
#include <vector>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
Mat CropMid(InputArray src, int w, int h)
|
||||
{
|
||||
Mat mat = src.getMat();
|
||||
return mat(Rect(mat.cols / 2 - w / 2, mat.rows / 2 - h / 2, w, h));
|
||||
}
|
||||
|
||||
Mat GenerateTestImage(Size size)
|
||||
{
|
||||
Mat image = Mat::zeros(size.height * 2, size.width * 2, CV_32F);
|
||||
rectangle(image,
|
||||
Point(static_cast<int>(size.width * 0.1), static_cast<int>(size.height * 0.1)),
|
||||
Point(static_cast<int>(size.width * 0.9), static_cast<int>(size.height * 0.9)),
|
||||
Scalar(1),
|
||||
-1);
|
||||
return image;
|
||||
}
|
||||
|
||||
void TestPhaseCorrelationIterative(const Size& size, const double maxShift)
|
||||
{
|
||||
const auto iters = std::max(201., maxShift * 10 + 1);
|
||||
const Point2d shiftOffset(-maxShift * 0.5, -maxShift * 0.5);
|
||||
Mat image1 = GenerateTestImage(size);
|
||||
Mat crop1 = CropMid(image1, size.width, size.height);
|
||||
Mat image2 = image1.clone();
|
||||
|
||||
std::vector<double> pcErrors;
|
||||
std::vector<double> ipcErrors;
|
||||
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
const auto shift =
|
||||
Point2d(maxShift * i / (iters - 1), maxShift * i / (iters - 1)) + shiftOffset;
|
||||
const Mat Tmat = (Mat_<double>(2, 3) << 1., 0., shift.x, 0., 1., shift.y);
|
||||
warpAffine(image1, image2, Tmat, image2.size());
|
||||
Mat crop2 = CropMid(image2, size.width, size.height);
|
||||
const auto ipcshift = phaseCorrelateIterative(crop1, crop2);
|
||||
const auto pcshift = phaseCorrelate(crop1, crop2);
|
||||
|
||||
pcErrors.push_back(
|
||||
0.5 * std::abs(pcshift.x - shift.y) + 0.5 * std::abs(pcshift.y - shift.x));
|
||||
ipcErrors.push_back(
|
||||
0.5 * std::abs(ipcshift.x - shift.y) + 0.5 * std::abs(ipcshift.y - shift.x));
|
||||
|
||||
// error should be low
|
||||
EXPECT_NEAR(ipcshift.x - shift.x, 0.0, 0.1);
|
||||
EXPECT_NEAR(ipcshift.y - shift.y, 0.0, 0.1);
|
||||
}
|
||||
|
||||
cv::Scalar pcMean, pcStddev, ipcMean, ipcStddev;
|
||||
meanStdDev(ipcErrors, ipcMean, ipcStddev);
|
||||
meanStdDev(pcErrors, pcMean, pcStddev);
|
||||
|
||||
// average error should be low
|
||||
ASSERT_LT(ipcMean[0], 0.03);
|
||||
// average error should be less than non-iterative average error
|
||||
ASSERT_LT(ipcMean[0], pcMean[0]);
|
||||
// error stddev should be less than non-iterative error stddev
|
||||
ASSERT_LT(ipcStddev[0], pcStddev[0]);
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_PhaseCorrelationIterative, 256x128_accuracy)
|
||||
{
|
||||
TestPhaseCorrelationIterative(Size(256, 128), 1);
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelationIterative, 64x64_accuracy_shift_1)
|
||||
{
|
||||
TestPhaseCorrelationIterative(Size(64, 64), 1);
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelationIterative, 64x64_accuracy_shift_16)
|
||||
{
|
||||
TestPhaseCorrelationIterative(Size(64, 64), 16);
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelationIterative, 0x0_image)
|
||||
{
|
||||
ASSERT_ANY_THROW(TestPhaseCorrelationIterative(Size(0, 0), 1));
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelationIterative, 1x1_image)
|
||||
{
|
||||
ASSERT_ANY_THROW(TestPhaseCorrelationIterative(Size(1, 1), 1));
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelationIterative, accuracy_real_img)
|
||||
{
|
||||
Mat img = imread(cvtest::TS::ptr()->get_data_path() + "shared/airplane.png", IMREAD_GRAYSCALE);
|
||||
if (img.empty())
|
||||
return;
|
||||
img.convertTo(img, CV_64FC1);
|
||||
|
||||
const int xLen = 256;
|
||||
const int yLen = 256;
|
||||
const int xShift = 40;
|
||||
const int yShift = 14;
|
||||
|
||||
Mat roi1 = img(Rect(xShift, yShift, xLen, yLen));
|
||||
Mat roi2 = img(Rect(0, 0, xLen, yLen));
|
||||
|
||||
const Point2d ipcShift = phaseCorrelateIterative(roi1, roi2);
|
||||
|
||||
ASSERT_NEAR(ipcShift.x, (double)xShift, 1.);
|
||||
ASSERT_NEAR(ipcShift.y, (double)yShift, 1.);
|
||||
}
|
||||
|
||||
}} // namespace opencv_test
|
||||
@@ -0,0 +1,498 @@
|
||||
// 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"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const Size img_size(640, 480);
|
||||
const int LSD_TEST_SEED = 0x134679;
|
||||
const int EPOCHS = 20;
|
||||
|
||||
class LSDBase : public testing::Test
|
||||
{
|
||||
public:
|
||||
LSDBase() { }
|
||||
|
||||
protected:
|
||||
Mat test_image;
|
||||
vector<Vec4f> lines;
|
||||
RNG rng;
|
||||
int passedtests;
|
||||
|
||||
void GenerateWhiteNoise(Mat& image);
|
||||
void GenerateConstColor(Mat& image);
|
||||
void GenerateLines(Mat& image, const unsigned int numLines);
|
||||
void GenerateRotatedRect(Mat& image);
|
||||
virtual void SetUp();
|
||||
};
|
||||
|
||||
class Imgproc_LSD_ADV: public LSDBase
|
||||
{
|
||||
public:
|
||||
Imgproc_LSD_ADV() { }
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
class Imgproc_LSD_STD: public LSDBase
|
||||
{
|
||||
public:
|
||||
Imgproc_LSD_STD() { }
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
class Imgproc_LSD_NONE: public LSDBase
|
||||
{
|
||||
public:
|
||||
Imgproc_LSD_NONE() { }
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
class Imgproc_LSD_Common : public LSDBase
|
||||
{
|
||||
public:
|
||||
Imgproc_LSD_Common() { }
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
void LSDBase::GenerateWhiteNoise(Mat& image)
|
||||
{
|
||||
image = Mat(img_size, CV_8UC1);
|
||||
rng.fill(image, RNG::UNIFORM, 0, 256);
|
||||
}
|
||||
|
||||
void LSDBase::GenerateConstColor(Mat& image)
|
||||
{
|
||||
image = Mat(img_size, CV_8UC1, Scalar::all(rng.uniform(0, 256)));
|
||||
}
|
||||
|
||||
void LSDBase::GenerateLines(Mat& image, const unsigned int numLines)
|
||||
{
|
||||
image = Mat(img_size, CV_8UC1, Scalar::all(rng.uniform(0, 128)));
|
||||
|
||||
for(unsigned int i = 0; i < numLines; ++i)
|
||||
{
|
||||
int y = rng.uniform(10, img_size.width - 10);
|
||||
Point p1(y, 10);
|
||||
Point p2(y, img_size.height - 10);
|
||||
line(image, p1, p2, Scalar(255), 3);
|
||||
}
|
||||
}
|
||||
|
||||
void LSDBase::GenerateRotatedRect(Mat& image)
|
||||
{
|
||||
image = Mat::zeros(img_size, CV_8UC1);
|
||||
|
||||
Point center(rng.uniform(img_size.width/4, img_size.width*3/4),
|
||||
rng.uniform(img_size.height/4, img_size.height*3/4));
|
||||
Size rect_size(rng.uniform(img_size.width/8, img_size.width/6),
|
||||
rng.uniform(img_size.height/8, img_size.height/6));
|
||||
float angle = rng.uniform(0.f, 360.f);
|
||||
|
||||
Point2f vertices[4];
|
||||
|
||||
RotatedRect rRect = RotatedRect(center, rect_size, angle);
|
||||
|
||||
rRect.points(vertices);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
line(image, vertices[i], vertices[(i + 1) % 4], Scalar(255), 3);
|
||||
}
|
||||
}
|
||||
|
||||
void LSDBase::SetUp()
|
||||
{
|
||||
lines.clear();
|
||||
test_image = Mat();
|
||||
rng = RNG(LSD_TEST_SEED);
|
||||
passedtests = 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_F(Imgproc_LSD_ADV, whiteNoise)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateWhiteNoise(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_ADV);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(40u >= lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_ADV, constColor)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_ADV);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(0u == lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_ADV, lines)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
const unsigned int numOfLines = 1;
|
||||
GenerateLines(test_image, numOfLines);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_ADV);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(numOfLines * 2 == lines.size()) ++passedtests; // * 2 because of Gibbs effect
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_ADV, rotatedRect)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateRotatedRect(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_ADV);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(2u <= lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_STD, whiteNoise)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateWhiteNoise(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(50u >= lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_STD, constColor)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(0u == lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_STD, lines)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
const unsigned int numOfLines = 1;
|
||||
GenerateLines(test_image, numOfLines);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(numOfLines * 2 == lines.size()) ++passedtests; // * 2 because of Gibbs effect
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_STD, rotatedRect)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateRotatedRect(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(4u <= lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_NONE, whiteNoise)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateWhiteNoise(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_NONE);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(50u >= lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_NONE, constColor)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_NONE);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(0u == lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_NONE, lines)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
const unsigned int numOfLines = 1;
|
||||
GenerateLines(test_image, numOfLines);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_NONE);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(numOfLines * 2 == lines.size()) ++passedtests; // * 2 because of Gibbs effect
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_NONE, rotatedRect)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateRotatedRect(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_NONE);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
if(8u <= lines.size()) ++passedtests;
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_Common, supportsVec4iResult)
|
||||
{
|
||||
for (int i = 0; i < EPOCHS; ++i)
|
||||
{
|
||||
GenerateWhiteNoise(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->detect(test_image, lines);
|
||||
|
||||
std::vector<Vec4i> linesVec4i;
|
||||
detector->detect(test_image, linesVec4i);
|
||||
|
||||
if (lines.size() == linesVec4i.size())
|
||||
{
|
||||
bool pass = true;
|
||||
for (size_t lineIndex = 0; pass && lineIndex < lines.size(); lineIndex++)
|
||||
{
|
||||
for (int ch = 0; ch < 4; ch++)
|
||||
{
|
||||
if (cv::saturate_cast<int>(lines[lineIndex][ch]) != linesVec4i[lineIndex][ch])
|
||||
{
|
||||
pass = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pass)
|
||||
++passedtests;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(EPOCHS, passedtests);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_Common, drawSegmentsVec4f)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
|
||||
std::vector<Vec4f> linesVec4f;
|
||||
RNG cr(0); // constant seed for deterministic test
|
||||
for (int j = 0; j < 10; j++) {
|
||||
linesVec4f.push_back(
|
||||
Vec4f(float(cr) * test_image.cols, float(cr) * test_image.rows, float(cr) * test_image.cols, float(cr) * test_image.rows));
|
||||
}
|
||||
|
||||
Mat actual = Mat::zeros(test_image.size(), CV_8UC3);
|
||||
Mat expected = Mat::zeros(test_image.size(), CV_8UC3);
|
||||
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->drawSegments(actual, linesVec4f);
|
||||
|
||||
// something should be drawn
|
||||
ASSERT_EQ(sum(actual == expected) != Scalar::all(0), true);
|
||||
|
||||
for (size_t lineIndex = 0; lineIndex < linesVec4f.size(); lineIndex++)
|
||||
{
|
||||
const Vec4f &v = linesVec4f[lineIndex];
|
||||
const Point2f b(v[0], v[1]);
|
||||
const Point2f e(v[2], v[3]);
|
||||
line(expected, b, e, Scalar(0, 0, 255), 1);
|
||||
}
|
||||
|
||||
ASSERT_EQ(sum(actual != expected) == Scalar::all(0), true);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_Common, drawSegmentsVec4i)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
|
||||
std::vector<Vec4i> linesVec4i;
|
||||
RNG cr(0); // constant seed for deterministic test
|
||||
for (int j = 0; j < 10; j++) {
|
||||
linesVec4i.push_back(
|
||||
Vec4i(cr(test_image.cols), cr(test_image.rows), cr(test_image.cols), cr(test_image.rows)));
|
||||
}
|
||||
|
||||
Mat actual = Mat::zeros(test_image.size(), CV_8UC3);
|
||||
Mat expected = Mat::zeros(test_image.size(), CV_8UC3);
|
||||
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
detector->drawSegments(actual, linesVec4i);
|
||||
|
||||
// something should be drawn
|
||||
ASSERT_EQ(sum(actual == expected) != Scalar::all(0), true);
|
||||
|
||||
for (size_t lineIndex = 0; lineIndex < linesVec4i.size(); lineIndex++)
|
||||
{
|
||||
const Vec4f &v = linesVec4i[lineIndex];
|
||||
const Point2f b(v[0], v[1]);
|
||||
const Point2f e(v[2], v[3]);
|
||||
line(expected, b, e, Scalar(0, 0, 255), 1);
|
||||
}
|
||||
|
||||
ASSERT_EQ(sum(actual != expected) == Scalar::all(0), true);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_Common, compareSegmentsVec4f)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
|
||||
std::vector<Vec4f> lines1, lines2;
|
||||
lines1.push_back(Vec4f(0, 0, 100, 200));
|
||||
lines2.push_back(Vec4f(0, 0, 100, 200));
|
||||
int result1 = detector->compareSegments(test_image.size(), lines1, lines2);
|
||||
|
||||
ASSERT_EQ(result1, 0);
|
||||
|
||||
lines2.push_back(Vec4f(100, 100, 110, 100));
|
||||
int result2 = detector->compareSegments(test_image.size(), lines1, lines2);
|
||||
|
||||
ASSERT_EQ(result2, 11);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_Common, compareSegmentsVec4i)
|
||||
{
|
||||
GenerateConstColor(test_image);
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
|
||||
std::vector<Vec4i> lines1, lines2;
|
||||
lines1.push_back(Vec4i(0, 0, 100, 200));
|
||||
lines2.push_back(Vec4i(0, 0, 100, 200));
|
||||
int result1 = detector->compareSegments(test_image.size(), lines1, lines2);
|
||||
|
||||
ASSERT_EQ(result1, 0);
|
||||
|
||||
lines2.push_back(Vec4i(100, 100, 110, 100));
|
||||
int result2 = detector->compareSegments(test_image.size(), lines1, lines2);
|
||||
|
||||
ASSERT_EQ(result2, 11);
|
||||
}
|
||||
|
||||
TEST_F(Imgproc_LSD_Common, drawSegmentsEmpty)
|
||||
{
|
||||
Ptr<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
|
||||
Mat1b img = Mat1b::zeros(240, 320);
|
||||
|
||||
std::vector<Vec4i> lines_4i;
|
||||
detector->detect(img, lines_4i);
|
||||
|
||||
Mat3b img_color = Mat3b::zeros(240, 320);
|
||||
ASSERT_NO_THROW(
|
||||
detector->drawSegments(img_color, lines_4i);
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(Imgproc_fitLine_vector_3d, regression)
|
||||
{
|
||||
std::vector<Point3f> points_vector;
|
||||
|
||||
Point3f p21(4,4,4);
|
||||
Point3f p22(8,8,8);
|
||||
|
||||
points_vector.push_back(p21);
|
||||
points_vector.push_back(p22);
|
||||
|
||||
std::vector<float> line;
|
||||
|
||||
cv::fitLine(points_vector, line, DIST_L2, 0 ,0 ,0);
|
||||
|
||||
ASSERT_EQ(line.size(), (size_t)6);
|
||||
|
||||
}
|
||||
|
||||
TEST(Imgproc_fitLine_vector_2d, regression)
|
||||
{
|
||||
std::vector<Point2f> points_vector;
|
||||
|
||||
Point2f p21(4,4);
|
||||
Point2f p22(8,8);
|
||||
Point2f p23(16,16);
|
||||
|
||||
points_vector.push_back(p21);
|
||||
points_vector.push_back(p22);
|
||||
points_vector.push_back(p23);
|
||||
|
||||
std::vector<float> line;
|
||||
|
||||
cv::fitLine(points_vector, line, DIST_L2, 0 ,0 ,0);
|
||||
|
||||
ASSERT_EQ(line.size(), (size_t)4);
|
||||
}
|
||||
|
||||
TEST(Imgproc_fitLine_Mat_2dC2, regression)
|
||||
{
|
||||
cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2);
|
||||
std::vector<float> line1;
|
||||
|
||||
cv::fitLine(mat1, line1, DIST_L2, 0 ,0 ,0);
|
||||
|
||||
ASSERT_EQ(line1.size(), (size_t)4);
|
||||
}
|
||||
|
||||
TEST(Imgproc_fitLine_Mat_2dC1, regression)
|
||||
{
|
||||
cv::Matx<int, 3, 2> mat2;
|
||||
std::vector<float> line2;
|
||||
|
||||
cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0);
|
||||
|
||||
ASSERT_EQ(line2.size(), (size_t)4);
|
||||
}
|
||||
|
||||
TEST(Imgproc_fitLine_Mat_3dC3, regression)
|
||||
{
|
||||
cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3);
|
||||
std::vector<float> line1;
|
||||
|
||||
cv::fitLine(mat1, line1, DIST_L2, 0 ,0 ,0);
|
||||
|
||||
ASSERT_EQ(line1.size(), (size_t)6);
|
||||
}
|
||||
|
||||
TEST(Imgproc_fitLine_Mat_3dC1, regression)
|
||||
{
|
||||
cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1);
|
||||
std::vector<float> line2;
|
||||
|
||||
cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0);
|
||||
|
||||
ASSERT_EQ(line2.size(), (size_t)6);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -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")
|
||||
@@ -0,0 +1,154 @@
|
||||
/*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"
|
||||
|
||||
#define CV_TEST_DXT_MUL_CONJ 8
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/// phase correlation
|
||||
class CV_PhaseCorrelatorTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_PhaseCorrelatorTest();
|
||||
protected:
|
||||
void run( int );
|
||||
};
|
||||
|
||||
CV_PhaseCorrelatorTest::CV_PhaseCorrelatorTest() {}
|
||||
|
||||
void CV_PhaseCorrelatorTest::run( int )
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
|
||||
Mat r1 = Mat::ones(Size(129, 128), CV_64F);
|
||||
Mat r2 = Mat::ones(Size(129, 128), CV_64F);
|
||||
|
||||
double expectedShiftX = -10.0;
|
||||
double expectedShiftY = -20.0;
|
||||
|
||||
// draw 10x10 rectangles @ (100, 100) and (90, 80) should see ~(-10, -20) shift here...
|
||||
cv::rectangle(r1, Point(100, 100), Point(110, 110), Scalar(0, 0, 0), cv::FILLED);
|
||||
cv::rectangle(r2, Point(90, 80), Point(100, 90), Scalar(0, 0, 0), cv::FILLED);
|
||||
|
||||
Mat hann;
|
||||
createHanningWindow(hann, r1.size(), CV_64F);
|
||||
Point2d phaseShift = phaseCorrelate(r1, r2, hann);
|
||||
|
||||
// test accuracy should be less than 1 pixel...
|
||||
if(std::abs(expectedShiftX - phaseShift.x) >= 1 || std::abs(expectedShiftY - phaseShift.y) >= 1)
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelatorTest, accuracy) { CV_PhaseCorrelatorTest test; test.safe_run(); }
|
||||
|
||||
TEST(Imgproc_PhaseCorrelatorTest, accuracy_real_img)
|
||||
{
|
||||
Mat img = imread(cvtest::TS::ptr()->get_data_path() + "shared/airplane.png", IMREAD_GRAYSCALE);
|
||||
img.convertTo(img, CV_64FC1);
|
||||
|
||||
const int xLen = 129;
|
||||
const int yLen = 129;
|
||||
const int xShift = 40;
|
||||
const int yShift = 14;
|
||||
|
||||
Mat roi1 = img(Rect(xShift, yShift, xLen, yLen));
|
||||
Mat roi2 = img(Rect(0, 0, xLen, yLen));
|
||||
|
||||
Mat hann;
|
||||
createHanningWindow(hann, roi1.size(), CV_64F);
|
||||
Point2d phaseShift = phaseCorrelate(roi1, roi2, hann);
|
||||
|
||||
ASSERT_NEAR(phaseShift.x, (double)xShift, 1.);
|
||||
ASSERT_NEAR(phaseShift.y, (double)yShift, 1.);
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelatorTest, accuracy_1d_odd_fft) {
|
||||
Mat r1 = Mat::ones(Size(129, 1), CV_64F)*255; // 129 will be completed to 135 before FFT
|
||||
Mat r2 = Mat::ones(Size(129, 1), CV_64F)*255;
|
||||
|
||||
const int xShift = 10;
|
||||
|
||||
for(int i = 6; i < 20; i++)
|
||||
{
|
||||
r1.at<double>(i) = 1;
|
||||
r2.at<double>(i + xShift) = 1;
|
||||
}
|
||||
|
||||
Point2d phaseShift = phaseCorrelate(r1, r2);
|
||||
|
||||
ASSERT_NEAR(phaseShift.x, (double)xShift, 1.);
|
||||
}
|
||||
|
||||
TEST(Imgproc_PhaseCorrelatorTest, float32_overflow) {
|
||||
// load
|
||||
Mat im = imread(cvtest::TS::ptr()->get_data_path() + "shared/baboon.png", IMREAD_GRAYSCALE);
|
||||
ASSERT_EQ(im.type(), CV_8UC1);
|
||||
|
||||
// convert to 32F, scale values as if original image was 16U
|
||||
constexpr auto u8Max = std::numeric_limits<std::uint8_t>::max();
|
||||
constexpr auto u16Max = std::numeric_limits<std::uint16_t>::max();
|
||||
im.convertTo(im, CV_32FC1, double(u16Max) / double(u8Max));
|
||||
|
||||
// enlarge and create ROIs
|
||||
const auto w = im.cols * 5;
|
||||
const auto h = im.rows * 5;
|
||||
const auto roiW = (w * 2) / 3; // 50% overlap
|
||||
Mat imLarge;
|
||||
resize(im, imLarge, { w, h });
|
||||
const auto roiLeft = imLarge(Rect(0, 0, roiW, h));
|
||||
const auto roiRight = imLarge(Rect(w - roiW, 0, roiW, h));
|
||||
|
||||
// correlate
|
||||
double response = 0.0;
|
||||
Point2d phaseShift = phaseCorrelate(roiLeft, roiRight, cv::noArray(), &response);
|
||||
ASSERT_TRUE(std::isnormal(phaseShift.x) || 0.0 == phaseShift.x);
|
||||
ASSERT_TRUE(std::isnormal(phaseShift.y) || 0.0 == phaseShift.y);
|
||||
ASSERT_TRUE(std::isnormal(response) || 0.0 == response);
|
||||
EXPECT_NEAR(std::abs(phaseShift.x), w / 3.0, 1.0);
|
||||
EXPECT_NEAR(std::abs(phaseShift.y), 0.0, 1.0);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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/ts/ts_gtest.h"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/geometry.hpp"
|
||||
|
||||
#include "opencv2/core/private.hpp"
|
||||
|
||||
#include "opencv2/core/softfloat.hpp" // softfloat, uint32_t
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Imgproc_PyrUp, pyrUp_regression_22184)
|
||||
{
|
||||
Mat src(100,100,CV_16UC3,Scalar(255,255,255));
|
||||
Mat dst(100 * 2 + 1, 100 * 2 + 1, CV_16UC3, Scalar(0,0,0));
|
||||
pyrUp(src, dst, Size(dst.cols, dst.rows));
|
||||
double min_val = 0;
|
||||
minMaxLoc(dst, &min_val);
|
||||
ASSERT_GT(cvRound(min_val), 0);
|
||||
}
|
||||
|
||||
TEST(Imgproc_PyrUp, pyrUp_regression_22194)
|
||||
{
|
||||
Mat src(13, 13,CV_16UC3,Scalar(0,0,0));
|
||||
{
|
||||
int swidth = src.cols;
|
||||
int sheight = src.rows;
|
||||
int cn = src.channels();
|
||||
int count = 0;
|
||||
for (int y = 0; y < sheight; y++)
|
||||
{
|
||||
ushort *src_c = src.ptr<ushort>(y);
|
||||
for (int x = 0; x < swidth * cn; x++)
|
||||
{
|
||||
src_c[x] = (count++) % 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
Mat dst(src.cols * 2 - 1, src.rows * 2 - 1, CV_16UC3, Scalar(0,0,0));
|
||||
pyrUp(src, dst, Size(dst.cols, dst.rows));
|
||||
|
||||
{
|
||||
ushort *dst_c = dst.ptr<ushort>(dst.rows - 1);
|
||||
ASSERT_EQ(dst_c[0], 6);
|
||||
ASSERT_EQ(dst_c[1], 6);
|
||||
ASSERT_EQ(dst_c[2], 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
// 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"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static const int fixedShiftU8 = 8;
|
||||
|
||||
template <typename T, int fixedShift>
|
||||
void eval4(int64_t xcoeff0, int64_t xcoeff1, int64_t ycoeff0, int64_t ycoeff1, int cn,
|
||||
uint8_t* src_pt00, uint8_t* src_pt01, uint8_t* src_pt10, uint8_t* src_pt11, uint8_t* dst_pt)
|
||||
{
|
||||
static const int64_t fixedRound = ((1LL << (fixedShift * 2)) >> 1);
|
||||
int64_t val = (((T*)src_pt00)[cn] * xcoeff0 + ((T*)src_pt01)[cn] * xcoeff1) * ycoeff0 +
|
||||
(((T*)src_pt10)[cn] * xcoeff0 + ((T*)src_pt11)[cn] * xcoeff1) * ycoeff1 ;
|
||||
((T*)dst_pt)[cn] = saturate_cast<T>((val + fixedRound) >> (fixedShift * 2));
|
||||
}
|
||||
|
||||
TEST(Resize_Bitexact, Linear8U)
|
||||
{
|
||||
static const int64_t fixedOne = (1L << fixedShiftU8);
|
||||
|
||||
struct testmode
|
||||
{
|
||||
int type;
|
||||
Size sz;
|
||||
} modes[] = {
|
||||
{ CV_8UC1, Size( 512, 768) }, // 1/2 1
|
||||
{ CV_8UC3, Size( 512, 768) },
|
||||
{ CV_8UC1, Size(1024, 384) }, // 1 1/2
|
||||
{ CV_8UC4, Size(1024, 384) },
|
||||
{ CV_8UC1, Size( 512, 384) }, // 1/2 1/2
|
||||
{ CV_8UC2, Size( 512, 384) },
|
||||
{ CV_8UC3, Size( 512, 384) },
|
||||
{ CV_8UC4, Size( 512, 384) },
|
||||
{ CV_8UC1, Size( 256, 192) }, // 1/4 1/4
|
||||
{ CV_8UC2, Size( 256, 192) },
|
||||
{ CV_8UC3, Size( 256, 192) },
|
||||
{ CV_8UC4, Size( 256, 192) },
|
||||
{ CV_8UC1, Size( 4, 3) }, // 1/256 1/256
|
||||
{ CV_8UC2, Size( 4, 3) },
|
||||
{ CV_8UC3, Size( 4, 3) },
|
||||
{ CV_8UC4, Size( 4, 3) },
|
||||
{ CV_8UC1, Size( 342, 384) }, // 1/3 1/2
|
||||
{ CV_8UC1, Size( 342, 256) }, // 1/3 1/3
|
||||
{ CV_8UC2, Size( 342, 256) },
|
||||
{ CV_8UC3, Size( 342, 256) },
|
||||
{ CV_8UC4, Size( 342, 256) },
|
||||
{ CV_8UC1, Size( 512, 256) }, // 1/2 1/3
|
||||
{ CV_8UC1, Size( 146, 110) }, // 1/7 1/7
|
||||
{ CV_8UC3, Size( 146, 110) },
|
||||
{ CV_8UC4, Size( 146, 110) },
|
||||
{ CV_8UC1, Size( 931, 698) }, // 10/11 10/11
|
||||
{ CV_8UC2, Size( 931, 698) },
|
||||
{ CV_8UC3, Size( 931, 698) },
|
||||
{ CV_8UC4, Size( 931, 698) },
|
||||
{ CV_8UC1, Size( 853, 640) }, // 10/12 10/12
|
||||
{ CV_8UC3, Size( 853, 640) },
|
||||
{ CV_8UC4, Size( 853, 640) },
|
||||
{ CV_8UC1, Size(1004, 753) }, // 251/256 251/256
|
||||
{ CV_8UC2, Size(1004, 753) },
|
||||
{ CV_8UC3, Size(1004, 753) },
|
||||
{ CV_8UC4, Size(1004, 753) },
|
||||
{ CV_8UC1, Size(2048,1536) }, // 2 2
|
||||
{ CV_8UC2, Size(2048,1536) },
|
||||
{ CV_8UC4, Size(2048,1536) },
|
||||
{ CV_8UC1, Size(3072,2304) }, // 3 3
|
||||
{ CV_8UC3, Size(3072,2304) },
|
||||
{ CV_8UC1, Size(7168,5376) } // 7 7
|
||||
};
|
||||
|
||||
for (int modeind = 0, _modecnt = sizeof(modes) / sizeof(modes[0]); modeind < _modecnt; ++modeind)
|
||||
{
|
||||
int type = modes[modeind].type, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int dcols = modes[modeind].sz.width, drows = modes[modeind].sz.height;
|
||||
int cols = 1024, rows = 768;
|
||||
|
||||
double inv_scale_x = (double)dcols / cols;
|
||||
double inv_scale_y = (double)drows / rows;
|
||||
softdouble scale_x = softdouble::one() / softdouble(inv_scale_x);
|
||||
softdouble scale_y = softdouble::one() / softdouble(inv_scale_y);
|
||||
|
||||
Mat src(rows, cols, type), refdst(drows, dcols, type), dst;
|
||||
RNG rnd(0x123456789abcdefULL);
|
||||
for (int j = 0; j < rows; j++)
|
||||
{
|
||||
uint8_t* line = src.ptr(j);
|
||||
for (int i = 0; i < cols; i++)
|
||||
for (int c = 0; c < cn; c++)
|
||||
{
|
||||
double val = j < rows / 2 ? ( i < cols / 2 ? ((sin((i + 1)*CV_PI / 256.)*sin((j + 1)*CV_PI / 256.)*sin((cn + 4)*CV_PI / 8.) + 1.)*128.) :
|
||||
(((i / 128 + j / 128) % 2) * 250 + (j / 128) % 2) ) :
|
||||
( i < cols / 2 ? ((i / 128) * (85 - j / 256 * 40) * ((j / 128) % 2) + (7 - i / 128) * (85 - j / 256 * 40) * ((j / 128 + 1) % 2)) :
|
||||
((uchar)rnd) ) ;
|
||||
if (depth == CV_8U)
|
||||
line[i*cn + c] = (uint8_t)val;
|
||||
else if (depth == CV_16U)
|
||||
((uint16_t*)line)[i*cn + c] = (uint16_t)val;
|
||||
else if (depth == CV_16S)
|
||||
((int16_t*)line)[i*cn + c] = (int16_t)val;
|
||||
else if (depth == CV_32S)
|
||||
((int32_t*)line)[i*cn + c] = (int32_t)val;
|
||||
else
|
||||
CV_Assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < drows; j++)
|
||||
{
|
||||
softdouble src_row_flt = scale_y*(softdouble(j) + softdouble(0.5)) - softdouble(0.5);
|
||||
int src_row = cvFloor(src_row_flt);
|
||||
int64_t ycoeff1 = cvRound64((src_row_flt - softdouble(src_row))*softdouble(fixedOne));
|
||||
int64_t ycoeff0 = fixedOne - ycoeff1;
|
||||
|
||||
for (int i = 0; i < dcols; i++)
|
||||
{
|
||||
softdouble src_col_flt = scale_x*(softdouble(i) + softdouble(0.5)) - softdouble(0.5);
|
||||
int src_col = cvFloor(src_col_flt);
|
||||
int64_t xcoeff1 = cvRound64((src_col_flt - softdouble(src_col))*softdouble(fixedOne));
|
||||
int64_t xcoeff0 = fixedOne - xcoeff1;
|
||||
|
||||
uint8_t* dst_pt = refdst.ptr(j, i);
|
||||
uint8_t* src_pt00 = src.ptr( src_row < 0 ? 0 : src_row >= rows ? rows - 1 : src_row ,
|
||||
src_col < 0 ? 0 : src_col >= cols ? cols - 1 : src_col );
|
||||
uint8_t* src_pt01 = src.ptr( src_row < 0 ? 0 : src_row >= rows ? rows - 1 : src_row ,
|
||||
(src_col + 1) < 0 ? 0 : (src_col + 1) >= cols ? cols - 1 : (src_col + 1));
|
||||
uint8_t* src_pt10 = src.ptr((src_row + 1) < 0 ? 0 : (src_row + 1) >= rows ? rows - 1 : (src_row + 1),
|
||||
src_col < 0 ? 0 : src_col >= cols ? cols - 1 : src_col );
|
||||
uint8_t* src_pt11 = src.ptr((src_row + 1) < 0 ? 0 : (src_row + 1) >= rows ? rows - 1 : (src_row + 1),
|
||||
(src_col + 1) < 0 ? 0 : (src_col + 1) >= cols ? cols - 1 : (src_col + 1));
|
||||
for (int c = 0; c < cn; c++)
|
||||
{
|
||||
if (depth == CV_8U)
|
||||
eval4< uint8_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt);
|
||||
else if (depth == CV_16U)
|
||||
eval4<uint16_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt);
|
||||
else if (depth == CV_16S)
|
||||
eval4< int16_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt);
|
||||
else if (depth == CV_32S)
|
||||
eval4< int32_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt);
|
||||
else
|
||||
CV_Assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cv::resize(src, dst, Size(dcols, drows), 0, 0, cv::INTER_LINEAR_EXACT);
|
||||
EXPECT_GE(0, cvtest::norm(refdst, dst, cv::NORM_L1))
|
||||
<< "Resize " << cn << "-chan mat from " << cols << "x" << rows << " to " << dcols << "x" << drows << " failed with max diff " << cvtest::norm(refdst, dst, cv::NORM_INF);
|
||||
}
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(Resize_Bitexact, int)
|
||||
{
|
||||
public:
|
||||
int depth;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
}
|
||||
|
||||
double CountDiff(const Mat& src)
|
||||
{
|
||||
Mat dstExact; cv::resize(src, dstExact, Size(), 2, 1, INTER_NEAREST_EXACT);
|
||||
Mat dstNonExact; cv::resize(src, dstNonExact, Size(), 2, 1, INTER_NEAREST);
|
||||
|
||||
return cv::norm(dstExact, dstNonExact, NORM_INF);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(Resize_Bitexact, Nearest8U_vsNonExact)
|
||||
{
|
||||
Mat mat_color, mat_gray;
|
||||
Mat src_color = imread(cvtest::findDataFile("shared/lena.png"));
|
||||
Mat src_gray; cv::cvtColor(src_color, src_gray, COLOR_BGR2GRAY);
|
||||
src_color.convertTo(mat_color, depth);
|
||||
src_gray.convertTo(mat_gray, depth);
|
||||
|
||||
EXPECT_EQ(CountDiff(mat_color), 0) << "color, type: " << depth;
|
||||
EXPECT_EQ(CountDiff(mat_gray), 0) << "gray, type: " << depth;
|
||||
}
|
||||
|
||||
// Now INTER_NEAREST's convention and INTER_NEAREST_EXACT's one are different.
|
||||
INSTANTIATE_TEST_CASE_P(DISABLED_Imgproc, Resize_Bitexact,
|
||||
testing::Values(CV_8U, CV_16U, CV_32F, CV_64F)
|
||||
);
|
||||
|
||||
TEST(Resize_Bitexact, Nearest8U)
|
||||
{
|
||||
Mat src[6], dst[6];
|
||||
|
||||
// 2x decimation
|
||||
src[0] = (Mat_<uint8_t>(1, 6) << 0, 1, 2, 3, 4, 5);
|
||||
dst[0] = (Mat_<uint8_t>(1, 3) << 1, 3, 5);
|
||||
|
||||
// decimation odd to 1
|
||||
src[1] = (Mat_<uint8_t>(1, 5) << 0, 1, 2, 3, 4);
|
||||
dst[1] = (Mat_<uint8_t>(1, 1) << 2);
|
||||
|
||||
// decimation n*2-1 to n
|
||||
src[2] = (Mat_<uint8_t>(1, 5) << 0, 1, 2, 3, 4);
|
||||
dst[2] = (Mat_<uint8_t>(1, 3) << 0, 2, 4);
|
||||
|
||||
// decimation n*2+1 to n
|
||||
src[3] = (Mat_<uint8_t>(1, 5) << 0, 1, 2, 3, 4);
|
||||
dst[3] = (Mat_<uint8_t>(1, 2) << 1, 3);
|
||||
|
||||
// zoom
|
||||
src[4] = (Mat_<uint8_t>(3, 5) <<
|
||||
0, 1, 2, 3, 4,
|
||||
5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14);
|
||||
dst[4] = (Mat_<uint8_t>(5, 7) <<
|
||||
0, 1, 1, 2, 3, 3, 4,
|
||||
0, 1, 1, 2, 3, 3, 4,
|
||||
5, 6, 6, 7, 8, 8, 9,
|
||||
10, 11, 11, 12, 13, 13, 14,
|
||||
10, 11, 11, 12, 13, 13, 14);
|
||||
|
||||
src[5] = (Mat_<uint8_t>(2, 3) <<
|
||||
0, 1, 2,
|
||||
3, 4, 5);
|
||||
dst[5] = (Mat_<uint8_t>(4, 6) <<
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
3, 3, 4, 4, 5, 5,
|
||||
3, 3, 4, 4, 5, 5);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Mat calc;
|
||||
resize(src[i], calc, dst[i].size(), 0, 0, INTER_NEAREST_EXACT);
|
||||
EXPECT_EQ(cvtest::norm(calc, dst[i], cv::NORM_L1), 0);
|
||||
|
||||
resize(src[i].t(), calc, dst[i].t().size(), 0, 0, INTER_NEAREST_EXACT);
|
||||
EXPECT_EQ(cvtest::norm(calc, dst[i].t(), cv::NORM_L1), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Regression test for #28429: INTER_NEAREST_EXACT matches Pillow's
|
||||
// center-of-pixel nearest-neighbor mapping.
|
||||
TEST(Resize_Bitexact, NearestExact_PillowCompat)
|
||||
{
|
||||
auto center_pixel_map = [](int src_dim, int dst_dim, std::vector<int>& mapping) {
|
||||
softdouble scale = softdouble(src_dim) / softdouble(dst_dim);
|
||||
softdouble f = scale * softdouble(0.5);
|
||||
mapping.resize(dst_dim);
|
||||
for (int i = 0; i < dst_dim; i++)
|
||||
{
|
||||
mapping[i] = std::min(cvTrunc(f), src_dim - 1);
|
||||
f += scale;
|
||||
}
|
||||
};
|
||||
|
||||
// Test dimension pairs including multiples of 64 that triggered the bug
|
||||
const int cases[][4] = {
|
||||
{128, 147, 160, 160}, // original reproducer from #28429
|
||||
{128, 128, 160, 160}, // square with problematic height
|
||||
{192, 192, 256, 256}, // another multiple of 64
|
||||
{129, 147, 160, 160}, // non-problematic control case
|
||||
};
|
||||
|
||||
for (const auto& c : cases)
|
||||
{
|
||||
int src_h = c[0], src_w = c[1], dst_h = c[2], dst_w = c[3];
|
||||
|
||||
std::vector<int> x_map, y_map;
|
||||
center_pixel_map(src_w, dst_w, x_map);
|
||||
center_pixel_map(src_h, dst_h, y_map);
|
||||
|
||||
Mat src(src_h, src_w, CV_8UC3);
|
||||
randu(src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat result;
|
||||
resize(src, result, Size(dst_w, dst_h), 0, 0, INTER_NEAREST_EXACT);
|
||||
|
||||
int nerrs = 0;
|
||||
for (int y = 0; y < dst_h; y++)
|
||||
{
|
||||
for (int x = 0; x < dst_w; x++)
|
||||
{
|
||||
Vec3b expected = src.at<Vec3b>(y_map[y], x_map[x]);
|
||||
Vec3b actual = result.at<Vec3b>(y, x);
|
||||
nerrs += expected != actual;
|
||||
if (nerrs <= 10) {
|
||||
EXPECT_EQ(expected, actual)
|
||||
<< "Mismatch at dst(" << y << "," << x << ") -> src("
|
||||
<< y_map[y] << "," << x_map[x] << ") for "
|
||||
<< src_h << "x" << src_w << " -> " << dst_h << "x" << dst_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_EQ(nerrs, 0) << "nerrs=" << nerrs << " when"
|
||||
<< " src_h=" << src_h << ", src_w=" << src_w
|
||||
<< " dst_h=" << dst_h << ", dst_w=" << dst_w;
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,309 @@
|
||||
// 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"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static const int fixedShiftU8 = 8;
|
||||
static const int64_t fixedOneU8 = (1L << fixedShiftU8);
|
||||
static const int fixedShiftU16 = 16;
|
||||
static const int64_t fixedOneU16 = (1L << fixedShiftU16);
|
||||
|
||||
int64_t vU8[][9] = {
|
||||
{ fixedOneU8 }, // size 1, sigma 0
|
||||
{ fixedOneU8 >> 2, fixedOneU8 >> 1, fixedOneU8 >> 2 }, // size 3, sigma 0
|
||||
{ fixedOneU8 >> 4, fixedOneU8 >> 2, 6 * (fixedOneU8 >> 4), fixedOneU8 >> 2, fixedOneU8 >> 4 }, // size 5, sigma 0
|
||||
{ fixedOneU8 >> 5, 7 * (fixedOneU8 >> 6), 7 * (fixedOneU8 >> 5), 9 * (fixedOneU8 >> 5), 7 * (fixedOneU8 >> 5), 7 * (fixedOneU8 >> 6), fixedOneU8 >> 5 }, // size 7, sigma 0
|
||||
{ 4, 13, 30, 51, 60, 51, 30, 13, 4 }, // size 9, sigma 0
|
||||
#if 1
|
||||
#define CV_TEST_INACCURATE_GAUSSIAN_BLUR
|
||||
{ 81, 94, 81 }, // size 3, sigma 1.75
|
||||
{ 65, 126, 65 }, // size 3, sigma 0.875
|
||||
{ 0, 7, 242, 7, 0 }, // size 5, sigma 0.375
|
||||
{ 4, 56, 136, 56, 4 } // size 5, sigma 0.75
|
||||
#endif
|
||||
};
|
||||
|
||||
int64_t vU16[][9] = {
|
||||
{ fixedOneU16 }, // size 1, sigma 0
|
||||
{ fixedOneU16 >> 2, fixedOneU16 >> 1, fixedOneU16 >> 2 }, // size 3, sigma 0
|
||||
{ fixedOneU16 >> 4, fixedOneU16 >> 2, 6 * (fixedOneU16 >> 4), fixedOneU16 >> 2, fixedOneU16 >> 4 }, // size 5, sigma 0
|
||||
{ fixedOneU16 >> 5, 7 * (fixedOneU16 >> 6), 7 * (fixedOneU16 >> 5), 9 * (fixedOneU16 >> 5), 7 * (fixedOneU16 >> 5), 7 * (fixedOneU16 >> 6), fixedOneU16 >> 5 }, // size 7, sigma 0
|
||||
{ 4<<8, 13<<8, 30<<8, 51<<8, 60<<8, 51<<8, 30<<8, 13<<8, 4<<8 } // size 9, sigma 0
|
||||
};
|
||||
|
||||
template <typename T, int fixedShift>
|
||||
T eval(Mat src, vector<int64_t> kernelx, vector<int64_t> kernely)
|
||||
{
|
||||
static const int64_t fixedRound = ((1LL << (fixedShift * 2)) >> 1);
|
||||
int64_t val = 0;
|
||||
for (size_t j = 0; j < kernely.size(); j++)
|
||||
{
|
||||
int64_t lineval = 0;
|
||||
for (size_t i = 0; i < kernelx.size(); i++)
|
||||
lineval += src.at<T>((int)j, (int)i) * kernelx[i];
|
||||
val += lineval * kernely[j];
|
||||
}
|
||||
return saturate_cast<T>((val + fixedRound) >> (fixedShift * 2));
|
||||
}
|
||||
|
||||
struct testmode
|
||||
{
|
||||
int type;
|
||||
Size sz;
|
||||
Size kernel;
|
||||
double sigma_x;
|
||||
double sigma_y;
|
||||
vector<int64_t> kernel_x;
|
||||
vector<int64_t> kernel_y;
|
||||
};
|
||||
|
||||
int bordermodes[] = {
|
||||
BORDER_CONSTANT | BORDER_ISOLATED,
|
||||
BORDER_REPLICATE | BORDER_ISOLATED,
|
||||
BORDER_REFLECT | BORDER_ISOLATED,
|
||||
BORDER_WRAP | BORDER_ISOLATED,
|
||||
BORDER_REFLECT_101 | BORDER_ISOLATED
|
||||
// BORDER_CONSTANT,
|
||||
// BORDER_REPLICATE,
|
||||
// BORDER_REFLECT,
|
||||
// BORDER_WRAP,
|
||||
// BORDER_REFLECT_101
|
||||
};
|
||||
|
||||
template <int fixedShift>
|
||||
void checkMode(const testmode& mode)
|
||||
{
|
||||
int type = mode.type, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int dcols = mode.sz.width, drows = mode.sz.height;
|
||||
Size kernel = mode.kernel;
|
||||
|
||||
int rows = drows + 20, cols = dcols + 20;
|
||||
Mat src(rows, cols, type), refdst(drows, dcols, type), dst;
|
||||
for (int j = 0; j < rows; j++)
|
||||
{
|
||||
uint8_t* line = src.ptr(j);
|
||||
for (int i = 0; i < cols; i++)
|
||||
for (int c = 0; c < cn; c++)
|
||||
{
|
||||
RNG rnd(0x123456789abcdefULL);
|
||||
double val = j < rows / 2 ? (i < cols / 2 ? ((sin((i + 1)*CV_PI / 256.)*sin((j + 1)*CV_PI / 256.)*sin((cn + 4)*CV_PI / 8.) + 1.)*128.) :
|
||||
(((i / 128 + j / 128) % 2) * 250 + (j / 128) % 2)) :
|
||||
(i < cols / 2 ? ((i / 128) * (85 - j / 256 * 40) * ((j / 128) % 2) + (7 - i / 128) * (85 - j / 256 * 40) * ((j / 128 + 1) % 2)) :
|
||||
((uchar)rnd));
|
||||
if (depth == CV_8U)
|
||||
line[i*cn + c] = (uint8_t)val;
|
||||
else if (depth == CV_16U)
|
||||
((uint16_t*)line)[i*cn + c] = (uint16_t)val;
|
||||
else if (depth == CV_16S)
|
||||
((int16_t*)line)[i*cn + c] = (int16_t)val;
|
||||
else if (depth == CV_32S)
|
||||
((int32_t*)line)[i*cn + c] = (int32_t)val;
|
||||
else
|
||||
CV_Assert(0);
|
||||
}
|
||||
}
|
||||
Mat src_roi = src(Rect(10, 10, dcols, drows));
|
||||
|
||||
|
||||
for (int borderind = 0, _bordercnt = sizeof(bordermodes) / sizeof(bordermodes[0]); borderind < _bordercnt; ++borderind)
|
||||
{
|
||||
Mat src_border;
|
||||
cv::copyMakeBorder(src_roi, src_border, kernel.height / 2, kernel.height / 2, kernel.width / 2, kernel.width / 2, bordermodes[borderind]);
|
||||
for (int c = 0; c < src_border.channels(); c++)
|
||||
{
|
||||
int fromTo[2] = { c, 0 };
|
||||
int toFrom[2] = { 0, c };
|
||||
Mat src_chan(src_border.size(), CV_MAKETYPE(src_border.depth(),1));
|
||||
Mat dst_chan(refdst.size(), CV_MAKETYPE(refdst.depth(), 1));
|
||||
mixChannels(src_border, src_chan, fromTo, 1);
|
||||
for (int j = 0; j < drows; j++)
|
||||
for (int i = 0; i < dcols; i++)
|
||||
{
|
||||
if (depth == CV_8U)
|
||||
dst_chan.at<uint8_t>(j, i) = eval<uint8_t, fixedShift>(src_chan(Rect(i,j,kernel.width,kernel.height)), mode.kernel_x, mode.kernel_y);
|
||||
else if (depth == CV_16U)
|
||||
dst_chan.at<uint16_t>(j, i) = eval<uint16_t, fixedShift>(src_chan(Rect(i, j, kernel.width, kernel.height)), mode.kernel_x, mode.kernel_y);
|
||||
else if (depth == CV_16S)
|
||||
dst_chan.at<int16_t>(j, i) = eval<int16_t, fixedShift>(src_chan(Rect(i, j, kernel.width, kernel.height)), mode.kernel_x, mode.kernel_y);
|
||||
else if (depth == CV_32S)
|
||||
dst_chan.at<int32_t>(j, i) = eval<int32_t, fixedShift>(src_chan(Rect(i, j, kernel.width, kernel.height)), mode.kernel_x, mode.kernel_y);
|
||||
else
|
||||
CV_Assert(0);
|
||||
}
|
||||
mixChannels(dst_chan, refdst, toFrom, 1);
|
||||
}
|
||||
|
||||
cv::GaussianBlur(src_roi, dst, kernel, mode.sigma_x, mode.sigma_y, bordermodes[borderind]);
|
||||
|
||||
EXPECT_GE(0, cvtest::norm(refdst, dst, cv::NORM_L1))
|
||||
<< "GaussianBlur " << cn << "-chan mat " << drows << "x" << dcols << " by kernel " << kernel << " sigma(" << mode.sigma_x << ";" << mode.sigma_y << ") failed with max diff " << cvtest::norm(refdst, dst, cv::NORM_INF);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GaussianBlur_Bitexact, Linear8U)
|
||||
{
|
||||
testmode modes[] = {
|
||||
{ CV_8UC1, Size( 1, 1), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 2, 2), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 3, 1), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 1, 3), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 3, 3), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 3, 3), Size(5, 5), 0, 0, vector<int64_t>(vU8[2], vU8[2]+5), vector<int64_t>(vU8[2], vU8[2]+5) },
|
||||
{ CV_8UC1, Size( 3, 3), Size(7, 7), 0, 0, vector<int64_t>(vU8[3], vU8[3]+7), vector<int64_t>(vU8[3], vU8[3]+7) },
|
||||
{ CV_8UC1, Size( 5, 5), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 5, 5), Size(5, 5), 0, 0, vector<int64_t>(vU8[2], vU8[2]+5), vector<int64_t>(vU8[2], vU8[2]+5) },
|
||||
{ CV_8UC1, Size( 3, 5), Size(5, 5), 0, 0, vector<int64_t>(vU8[2], vU8[2]+5), vector<int64_t>(vU8[2], vU8[2]+5) },
|
||||
{ CV_8UC1, Size( 5, 5), Size(5, 5), 0, 0, vector<int64_t>(vU8[2], vU8[2]+5), vector<int64_t>(vU8[2], vU8[2]+5) },
|
||||
{ CV_8UC1, Size( 5, 5), Size(7, 7), 0, 0, vector<int64_t>(vU8[3], vU8[3]+7), vector<int64_t>(vU8[3], vU8[3]+7) },
|
||||
{ CV_8UC1, Size( 7, 7), Size(7, 7), 0, 0, vector<int64_t>(vU8[3], vU8[3]+7), vector<int64_t>(vU8[3], vU8[3]+7) },
|
||||
{ CV_8UC1, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC2, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC3, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC4, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU8[1], vU8[1]+3), vector<int64_t>(vU8[1], vU8[1]+3) },
|
||||
{ CV_8UC1, Size( 256, 128), Size(5, 5), 0, 0, vector<int64_t>(vU8[2], vU8[2]+5), vector<int64_t>(vU8[2], vU8[2]+5) },
|
||||
{ CV_8UC1, Size( 256, 128), Size(7, 7), 0, 0, vector<int64_t>(vU8[3], vU8[3]+7), vector<int64_t>(vU8[3], vU8[3]+7) },
|
||||
{ CV_8UC1, Size( 256, 128), Size(9, 9), 0, 0, vector<int64_t>(vU8[4], vU8[4]+9), vector<int64_t>(vU8[4], vU8[4]+9) },
|
||||
#ifdef CV_TEST_INACCURATE_GAUSSIAN_BLUR
|
||||
{ CV_8UC1, Size( 256, 128), Size(3, 3), 1.75, 0.875, vector<int64_t>(vU8[5], vU8[5]+3), vector<int64_t>(vU8[6], vU8[6]+3) },
|
||||
{ CV_8UC2, Size( 256, 128), Size(3, 3), 1.75, 0.875, vector<int64_t>(vU8[5], vU8[5]+3), vector<int64_t>(vU8[6], vU8[6]+3) },
|
||||
{ CV_8UC3, Size( 256, 128), Size(3, 3), 1.75, 0.875, vector<int64_t>(vU8[5], vU8[5]+3), vector<int64_t>(vU8[6], vU8[6]+3) },
|
||||
{ CV_8UC4, Size( 256, 128), Size(3, 3), 1.75, 0.875, vector<int64_t>(vU8[5], vU8[5]+3), vector<int64_t>(vU8[6], vU8[6]+3) },
|
||||
{ CV_8UC1, Size( 256, 128), Size(5, 5), 0.375, 0.75, vector<int64_t>(vU8[7], vU8[7]+5), vector<int64_t>(vU8[8], vU8[8]+5) }
|
||||
#endif
|
||||
};
|
||||
|
||||
for (int modeind = 0, _modecnt = sizeof(modes) / sizeof(modes[0]); modeind < _modecnt; ++modeind)
|
||||
{
|
||||
checkMode<fixedShiftU8>(modes[modeind]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GaussianBlur_Bitexact, Linear16U)
|
||||
{
|
||||
testmode modes[] = {
|
||||
{ CV_16UC1, Size( 1, 1), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 2, 2), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 3, 1), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 1, 3), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 3, 3), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 3, 3), Size(5, 5), 0, 0, vector<int64_t>(vU16[2], vU16[2]+5), vector<int64_t>(vU16[2], vU16[2]+5) },
|
||||
{ CV_16UC1, Size( 3, 3), Size(7, 7), 0, 0, vector<int64_t>(vU16[3], vU16[3]+7), vector<int64_t>(vU16[3], vU16[3]+7) },
|
||||
{ CV_16UC1, Size( 5, 5), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 5, 5), Size(5, 5), 0, 0, vector<int64_t>(vU16[2], vU16[2]+5), vector<int64_t>(vU16[2], vU16[2]+5) },
|
||||
{ CV_16UC1, Size( 3, 5), Size(5, 5), 0, 0, vector<int64_t>(vU16[2], vU16[2]+5), vector<int64_t>(vU16[2], vU16[2]+5) },
|
||||
{ CV_16UC1, Size( 5, 5), Size(5, 5), 0, 0, vector<int64_t>(vU16[2], vU16[2]+5), vector<int64_t>(vU16[2], vU16[2]+5) },
|
||||
{ CV_16UC1, Size( 5, 5), Size(7, 7), 0, 0, vector<int64_t>(vU16[3], vU16[3]+7), vector<int64_t>(vU16[3], vU16[3]+7) },
|
||||
{ CV_16UC1, Size( 7, 7), Size(7, 7), 0, 0, vector<int64_t>(vU16[3], vU16[3]+7), vector<int64_t>(vU16[3], vU16[3]+7) },
|
||||
{ CV_16UC1, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC2, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC3, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC4, Size( 256, 128), Size(3, 3), 0, 0, vector<int64_t>(vU16[1], vU16[1]+3), vector<int64_t>(vU16[1], vU16[1]+3) },
|
||||
{ CV_16UC1, Size( 256, 128), Size(5, 5), 0, 0, vector<int64_t>(vU16[2], vU16[2]+5), vector<int64_t>(vU16[2], vU16[2]+5) },
|
||||
{ CV_16UC1, Size( 256, 128), Size(7, 7), 0, 0, vector<int64_t>(vU16[3], vU16[3]+7), vector<int64_t>(vU16[3], vU16[3]+7) },
|
||||
{ CV_16UC1, Size( 256, 128), Size(9, 9), 0, 0, vector<int64_t>(vU16[4], vU16[4]+9), vector<int64_t>(vU16[4], vU16[4]+9) },
|
||||
};
|
||||
|
||||
for (int modeind = 0, _modecnt = sizeof(modes) / sizeof(modes[0]); modeind < _modecnt; ++modeind)
|
||||
{
|
||||
checkMode<16>(modes[modeind]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GaussianBlur_Bitexact, regression_15015)
|
||||
{
|
||||
Mat src(100,100,CV_8UC3,Scalar(255,255,255));
|
||||
Mat dst;
|
||||
GaussianBlur(src, dst, Size(5, 5), 0);
|
||||
ASSERT_EQ(0.0, cvtest::norm(dst, src, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(GaussianBlur_Bitexact, overflow_20121)
|
||||
{
|
||||
Mat src(100, 100, CV_16UC1, Scalar(65535));
|
||||
Mat dst;
|
||||
GaussianBlur(src, dst, cv::Size(9, 9), 0.0);
|
||||
double min_val;
|
||||
minMaxLoc(dst, &min_val);
|
||||
ASSERT_EQ(cvRound(min_val), 65535);
|
||||
}
|
||||
|
||||
static void checkGaussianBlur_8Uvs32F(const Mat& src8u, const Mat& src32f, int N, double sigma)
|
||||
{
|
||||
Mat dst8u; GaussianBlur(src8u, dst8u, Size(N, N), sigma); // through bit-exact path
|
||||
Mat dst8u_32f; dst8u.convertTo(dst8u_32f, CV_32F);
|
||||
|
||||
Mat dst32f; GaussianBlur(src32f, dst32f, Size(N, N), sigma); // without bit-exact computations
|
||||
|
||||
double normINF_32f = cv::norm(dst8u_32f, dst32f, NORM_INF);
|
||||
EXPECT_LE(normINF_32f, 1.0);
|
||||
}
|
||||
|
||||
TEST(GaussianBlur_Bitexact, regression_9863)
|
||||
{
|
||||
Mat src8u = imread(cvtest::findDataFile("shared/lena.png"));
|
||||
Mat src32f; src8u.convertTo(src32f, CV_32F);
|
||||
|
||||
checkGaussianBlur_8Uvs32F(src8u, src32f, 151, 30);
|
||||
}
|
||||
|
||||
TEST(GaussianBlur_Bitexact, overflow_20792)
|
||||
{
|
||||
Mat src(128, 128, CV_16UC1, Scalar(255));
|
||||
Mat dst;
|
||||
double sigma = theRNG().uniform(0.0, 0.2); // a peaky kernel
|
||||
GaussianBlur(src, dst, Size(7, 7), sigma, 0.9);
|
||||
int count = (int)countNonZero(dst);
|
||||
int nintyPercent = (int)(src.rows*src.cols * 0.9);
|
||||
EXPECT_GT(count, nintyPercent);
|
||||
}
|
||||
|
||||
CV_ENUM(GaussInputType, CV_8U, CV_16S);
|
||||
CV_ENUM(GaussBorder, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101);
|
||||
|
||||
struct GaussianBlurVsBitexact: public testing::TestWithParam<tuple<GaussInputType, int, double, GaussBorder>>
|
||||
{
|
||||
virtual void SetUp()
|
||||
{
|
||||
orig = imread(findDataFile("shared/lena.png"));
|
||||
EXPECT_FALSE(orig.empty()) << "Cannot find test image shared/lena.png";
|
||||
}
|
||||
|
||||
Mat orig;
|
||||
};
|
||||
|
||||
// NOTE: The test was designed for IPP (-DOPENCV_IPP_GAUSSIAN_BLUR=ON)
|
||||
// Should be extended after new HAL integration
|
||||
TEST_P(GaussianBlurVsBitexact, approx)
|
||||
{
|
||||
auto testParams = GetParam();
|
||||
int dtype = get<0>(testParams);
|
||||
int ksize = get<1>(testParams);
|
||||
double sigma = get<2>(testParams);
|
||||
int border = get<3>(testParams);
|
||||
|
||||
Mat src;
|
||||
orig.convertTo(src, dtype);
|
||||
|
||||
cv::Mat gt;
|
||||
GaussianBlur(src, gt, Size(ksize, ksize), sigma, sigma, border, ALGO_HINT_ACCURATE);
|
||||
|
||||
cv::Mat dst;
|
||||
GaussianBlur(src, dst, Size(ksize, ksize), sigma, sigma, border, ALGO_HINT_APPROX);
|
||||
|
||||
EXPECT_LE(cvtest::norm(dst, gt, NORM_INF), 1);
|
||||
EXPECT_LE(cvtest::norm(dst, gt, NORM_L1 | NORM_RELATIVE), 0.06); // Less 6% of different pixels
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, GaussianBlurVsBitexact,
|
||||
testing::Combine(
|
||||
GaussInputType::all(),
|
||||
testing::Values(3, 5, 7),
|
||||
testing::Values(0.75, 1.25),
|
||||
GaussBorder::all()
|
||||
)
|
||||
);
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,328 @@
|
||||
// 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.
|
||||
|
||||
/*
|
||||
StackBlur - a fast almost Gaussian Blur
|
||||
Theory: http://underdestruction.com/2004/02/25/stackblur-2004
|
||||
The code has been borrowed from (https://github.com/flozz/StackBlur).
|
||||
|
||||
Below is the original copyright
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2010 Mario Klingemann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
template<typename T>
|
||||
void _stackblurRef(const Mat& src, Mat& dst, Size ksize)
|
||||
{
|
||||
CV_Assert(!src.empty());
|
||||
CV_Assert(ksize.width > 0 && ksize.height > 0 && ksize.height % 2 == 1 && ksize.width % 2 == 1);
|
||||
|
||||
dst.create(src.size(), src.type());
|
||||
const int CN = src.channels();
|
||||
|
||||
int rowsImg = src.rows;
|
||||
int colsImg = src.cols;
|
||||
int wm = colsImg - 1;
|
||||
|
||||
int radiusW = ksize.width / 2;
|
||||
int stackLenW = ksize.width;
|
||||
const float mulW = 1.0f / (((float )radiusW + 1.0f) * ((float )radiusW + 1.0f));
|
||||
|
||||
// Horizontal direction
|
||||
std::vector<T> stack(stackLenW * CN);
|
||||
for (int row = 0; row < rowsImg; row++)
|
||||
{
|
||||
std::vector<float> sum(CN, 0);
|
||||
std::vector<float> sumIn(CN, 0);
|
||||
std::vector<float> sumOut(CN, 0);
|
||||
|
||||
const T* srcPtr = src.ptr<T>(row);
|
||||
|
||||
for (int i = 0; i <= radiusW; i++)
|
||||
{
|
||||
for (int ci = 0; ci < CN; ci++)
|
||||
{
|
||||
T tmp = *(srcPtr + ci);
|
||||
stack[i * CN + ci] = tmp;
|
||||
sum[ci] += tmp * (i + 1);
|
||||
sumOut[ci] += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i <= radiusW; i++)
|
||||
{
|
||||
if (i <= wm) srcPtr += CN;
|
||||
for(int ci = 0; ci < CN; ci++)
|
||||
{
|
||||
T tmp = *(srcPtr + ci);
|
||||
stack[(i + radiusW) * CN + ci] = tmp;
|
||||
sum[ci] += tmp * (radiusW + 1 - i);
|
||||
sumIn[ci] += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
int sp = radiusW;
|
||||
int xp = radiusW ;
|
||||
if (xp > wm) xp = wm;
|
||||
|
||||
T* dstPtr = dst.ptr<T>(row);
|
||||
srcPtr = src.ptr<T>(row) + xp * CN;
|
||||
|
||||
int stackStart= 0;
|
||||
|
||||
for (int i = 0; i < colsImg; i++)
|
||||
{
|
||||
stackStart = sp + stackLenW - radiusW;
|
||||
|
||||
if (stackStart >= stackLenW) stackStart -= stackLenW;
|
||||
|
||||
for(int ci = 0; ci < CN; ci++)
|
||||
{
|
||||
*(dstPtr + ci) = cv::saturate_cast<T>(sum[ci] * mulW);
|
||||
sum[ci] -= sumOut[ci];
|
||||
sumOut[ci] -= stack[stackStart*CN + ci];
|
||||
}
|
||||
|
||||
const T* srcNew = srcPtr;
|
||||
|
||||
if(xp < wm)
|
||||
srcNew += CN;
|
||||
|
||||
for (int ci = 0; ci < CN; ci++)
|
||||
{
|
||||
stack[stackStart * CN + ci] = *(srcNew + ci);
|
||||
sumIn[ci] += *(srcNew + ci);
|
||||
sum[ci] += sumIn[ci];
|
||||
}
|
||||
|
||||
int sp1 = sp + 1;
|
||||
if (sp1 >= stackLenW)
|
||||
sp1 = 0;
|
||||
|
||||
for(int ci = 0; ci < CN; ci++)
|
||||
{
|
||||
T tmp = stack[sp1*CN + ci];
|
||||
sumOut[ci] += tmp;
|
||||
sumIn[ci] -= tmp;
|
||||
}
|
||||
|
||||
dstPtr += CN;
|
||||
|
||||
if (xp < wm)
|
||||
{
|
||||
xp++;
|
||||
srcPtr += CN;
|
||||
}
|
||||
|
||||
++sp;
|
||||
if (sp >= stackLenW)
|
||||
sp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical direction
|
||||
int hm = rowsImg - 1;
|
||||
int widthElem = colsImg * CN;
|
||||
int radiusH = ksize.height / 2;
|
||||
int stackLenH = ksize.height;
|
||||
const float mulH = 1.0f / (((float )radiusH + 1.0f) * ((float )radiusH + 1.0f));
|
||||
|
||||
stack.resize(stackLenH, 0);
|
||||
for (int col = 0; col < widthElem; col++)
|
||||
{
|
||||
const T* srcPtr =dst.ptr<T>() + col;
|
||||
float sum0 = 0;
|
||||
float sumIn0 = 0;
|
||||
float sumOut0 = 0;
|
||||
|
||||
for (int i = 0; i <= radiusH; i++)
|
||||
{
|
||||
T tmp = (T)(*srcPtr);
|
||||
stack[i] = tmp;
|
||||
sum0 += tmp * (i + 1);
|
||||
sumOut0 += tmp;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= radiusH; i++)
|
||||
{
|
||||
if (i <= hm) srcPtr += widthElem;
|
||||
T tmp = (T)(*srcPtr);
|
||||
stack[i + radiusH] = tmp;
|
||||
sum0 += tmp * (radiusH - i + 1);
|
||||
sumIn0 += tmp;
|
||||
}
|
||||
|
||||
int sp = radiusH;
|
||||
int yp = radiusH;
|
||||
|
||||
if (yp > hm) yp = hm;
|
||||
|
||||
T* dstPtr = dst.ptr<T>() + col;
|
||||
srcPtr = dst.ptr<T>(yp) + col;
|
||||
|
||||
const T* srcNew;
|
||||
|
||||
int stackStart = 0;
|
||||
|
||||
for (int i = 0; i < rowsImg; i++)
|
||||
{
|
||||
stackStart = sp + stackLenH - radiusH;
|
||||
if (stackStart >= stackLenH) stackStart -= stackLenH;
|
||||
|
||||
*(dstPtr) = saturate_cast<T>(sum0 * mulH);
|
||||
sum0 -= sumOut0;
|
||||
sumOut0 -= stack[stackStart];
|
||||
srcNew = srcPtr;
|
||||
|
||||
if (yp < hm)
|
||||
srcNew += widthElem;
|
||||
|
||||
stack[stackStart] = *(srcNew);
|
||||
sumIn0 += *(srcNew);
|
||||
sum0 += sumIn0;
|
||||
|
||||
int sp1 = sp + 1;
|
||||
sp1 &= -(sp1 < stackLenH);
|
||||
|
||||
sumOut0 += stack[sp1];
|
||||
sumIn0 -= stack[sp1];
|
||||
|
||||
dstPtr += widthElem;
|
||||
|
||||
if (yp < hm)
|
||||
{
|
||||
yp++;
|
||||
srcPtr += widthElem;
|
||||
}
|
||||
|
||||
++sp;
|
||||
if (sp >= stackLenH) sp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stackBlurRef(const Mat& img, Mat& dst, Size ksize)
|
||||
{
|
||||
if(img.depth() == CV_8U)
|
||||
_stackblurRef<uchar>(img, dst, ksize);
|
||||
else if (img.depth() == CV_16S)
|
||||
_stackblurRef<short>(img, dst, ksize);
|
||||
else if (img.depth() == CV_16U)
|
||||
_stackblurRef<ushort>(img, dst, ksize);
|
||||
else if (img.depth() == CV_32F)
|
||||
_stackblurRef<float>(img, dst, ksize);
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented,
|
||||
("Unsupported Mat type in stackBlurRef, "
|
||||
"the supported formats are: CV_8U, CV_16U, CV_16S and CV_32F."));
|
||||
}
|
||||
|
||||
std::vector<Size> kernelSizeVec = {
|
||||
Size(3, 3),
|
||||
Size(5, 5),
|
||||
Size(101, 101),
|
||||
Size(3, 9)
|
||||
};
|
||||
|
||||
typedef testing::TestWithParam<tuple<int, int, int> > StackBlur;
|
||||
|
||||
TEST_P (StackBlur, regression)
|
||||
{
|
||||
Mat img_ = imread(findDataFile("shared/fruits.png"), 1);
|
||||
const int cn = get<0>(GetParam());
|
||||
const int kIndex = get<1>(GetParam());
|
||||
const int dtype = get<2>(GetParam());
|
||||
|
||||
Size ksize = kernelSizeVec[kIndex];
|
||||
|
||||
Mat img, dstRef, dst;
|
||||
convert(img_, img, dtype);
|
||||
|
||||
vector<Mat> channels;
|
||||
split(img, channels);
|
||||
channels.push_back(channels[0]); // channels size is 4.
|
||||
|
||||
Mat imgCn;
|
||||
if (cn == 1)
|
||||
imgCn = channels[0];
|
||||
else if (cn == 4)
|
||||
merge(channels, imgCn);
|
||||
else
|
||||
imgCn = img;
|
||||
|
||||
stackBlurRef(imgCn, dstRef, ksize);
|
||||
stackBlur(imgCn, dst, ksize);
|
||||
EXPECT_LE(cvtest::norm(dstRef, dst, NORM_INF), 2.);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Imgproc, StackBlur,
|
||||
testing::Combine(
|
||||
testing::Values(1, 3, 4),
|
||||
testing::Values(0, 1, 2, 3),
|
||||
testing::Values(CV_8U, CV_16S, CV_16U, CV_32F)
|
||||
)
|
||||
);
|
||||
|
||||
typedef testing::TestWithParam<tuple<int> > StackBlur_GaussianBlur;
|
||||
|
||||
// StackBlur should produce similar results as GaussianBlur output.
|
||||
TEST_P(StackBlur_GaussianBlur, compare)
|
||||
{
|
||||
Mat img_ = imread(findDataFile("shared/fruits.png"), 1);
|
||||
const int dtype = get<0>(GetParam());
|
||||
|
||||
Size ksize(3, 3);
|
||||
Mat img, dstS, dstG;
|
||||
convert(img_, img, dtype);
|
||||
|
||||
stackBlur(img, dstS, ksize);
|
||||
GaussianBlur(img, dstG, ksize, 0);
|
||||
|
||||
EXPECT_LE(cvtest::norm(dstS, dstG, NORM_INF), 13.);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Imgproc, StackBlur_GaussianBlur, testing::Values(CV_8U, CV_16S, CV_16U, CV_32F));
|
||||
|
||||
TEST(Imgproc_StackBlur, regression_28233)
|
||||
{
|
||||
Mat src1(1, 1, CV_8UC1, Scalar(123));
|
||||
Mat dst1;
|
||||
EXPECT_NO_THROW(stackBlur(src1, dst1, Size(9, 1)));
|
||||
EXPECT_EQ(dst1.at<uchar>(0, 0), 123);
|
||||
|
||||
Mat src2(3, 3, CV_8UC1, Scalar(50));
|
||||
Mat dst2;
|
||||
EXPECT_NO_THROW(stackBlur(src2, dst2, Size(11, 11)));
|
||||
EXPECT_EQ(dst2.at<uchar>(1, 1), 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(MorphShapes, getStructuringElementDiamond)
|
||||
{
|
||||
cv::Mat element = cv::getStructuringElement(cv::MORPH_DIAMOND, cv::Size(5,5));
|
||||
cv::Mat expected = (cv::Mat_<uchar>(5,5) <<
|
||||
0,0,1,0,0,
|
||||
0,1,1,1,0,
|
||||
1,1,1,1,1,
|
||||
0,1,1,1,0,
|
||||
0,0,1,0,0);
|
||||
EXPECT_EQ(0, cvtest::norm(element, expected, cv::NORM_INF));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,344 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Imgproc_MatchTemplate, bug_9597) {
|
||||
const uint8_t img[] = {
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 247, 247, 247, 247, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 247, 247, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245};
|
||||
const uint8_t tmpl[] = {
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
|
||||
245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245 };
|
||||
cv::Mat cvimg(cv::Size(61, 82), CV_8UC1, (void*)img, cv::Mat::AUTO_STEP);
|
||||
cv::Mat cvtmpl(cv::Size(17, 17), CV_8UC1, (void*)tmpl, cv::Mat::AUTO_STEP);
|
||||
cv::Mat result;
|
||||
cv::matchTemplate(cvimg, cvtmpl, result, cv::TM_SQDIFF);
|
||||
double minValue;
|
||||
cv::minMaxLoc(result, &minValue, NULL, NULL, NULL);
|
||||
ASSERT_GE(minValue, 0);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
static void matchTemplate_reference(Mat & img, Mat & templ, Mat & result, const int method)
|
||||
{
|
||||
CV_Assert(cv::TM_SQDIFF <= method && method <= cv::TM_CCOEFF_NORMED);
|
||||
|
||||
const Size res_sz(img.cols - templ.cols + 1, img.rows - templ.rows + 1);
|
||||
result.create(res_sz, CV_32FC1);
|
||||
|
||||
const int depth = img.depth();
|
||||
const int cn = img.channels();
|
||||
const int area = templ.size().area();
|
||||
const int width_n = templ.cols * cn;
|
||||
const int height = templ.rows;
|
||||
int a_step = (int)(img.step / img.elemSize1());
|
||||
int b_step = (int)(templ.step / templ.elemSize1());
|
||||
|
||||
Scalar b_mean = Scalar::all(0);
|
||||
Scalar b_sdv = Scalar::all(0);
|
||||
cv::meanStdDev(templ, b_mean, b_sdv);
|
||||
|
||||
double b_sum2 = 0.;
|
||||
for (int i = 0; i < cn; i++ )
|
||||
b_sum2 += (b_sdv.val[i] * b_sdv.val[i] + b_mean.val[i] * b_mean.val[i]) * area;
|
||||
|
||||
if (b_sdv.val[0] * b_sdv.val[0] + b_sdv.val[1] * b_sdv.val[1] +
|
||||
b_sdv.val[2] * b_sdv.val[2] + b_sdv.val[3] * b_sdv.val[3] < DBL_EPSILON &&
|
||||
method == cv::TM_CCOEFF_NORMED)
|
||||
{
|
||||
result = Scalar::all(1.);
|
||||
return;
|
||||
}
|
||||
|
||||
double b_denom = 1.;
|
||||
if (method & 1) // _NORMED
|
||||
{
|
||||
b_denom = 0;
|
||||
if (method != cv::TM_CCOEFF_NORMED)
|
||||
{
|
||||
b_denom = b_sum2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < cn; i++)
|
||||
b_denom += b_sdv.val[i] * b_sdv.val[i] * area;
|
||||
}
|
||||
b_denom = sqrt(b_denom);
|
||||
if (b_denom == 0)
|
||||
b_denom = 1.;
|
||||
}
|
||||
|
||||
for (int i = 0; i < result.rows; i++)
|
||||
{
|
||||
for (int j = 0; j < result.cols; j++)
|
||||
{
|
||||
Scalar a_sum(0), a_sum2(0);
|
||||
Scalar ccorr(0);
|
||||
double value = 0.;
|
||||
|
||||
if (depth == CV_8U)
|
||||
{
|
||||
const uchar* a = img.ptr<uchar>(i, j); // ??? ->data.ptr + i*img->step + j*cn;
|
||||
const uchar* b = templ.ptr<uchar>();
|
||||
|
||||
if( cn == 1 || method < cv::TM_CCOEFF )
|
||||
{
|
||||
for (int k = 0; k < height; k++, a += a_step, b += b_step)
|
||||
for (int l = 0; l < width_n; l++)
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int k = 0; k < height; k++, a += a_step, b += b_step)
|
||||
for (int l = 0; l < width_n; l += 3)
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
ccorr.val[1] += a[l+1]*b[l+1];
|
||||
ccorr.val[2] += a[l+2]*b[l+2];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum.val[1] += a[l+1];
|
||||
a_sum.val[2] += a[l+2];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
a_sum2.val[1] += a[l+1]*a[l+1];
|
||||
a_sum2.val[2] += a[l+2]*a[l+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else // CV_32F
|
||||
{
|
||||
const float* a = img.ptr<float>(i, j); // ???? (const float*)(img->data.ptr + i*img->step) + j*cn;
|
||||
const float* b = templ.ptr<float>();
|
||||
|
||||
if( cn == 1 || method < cv::TM_CCOEFF )
|
||||
{
|
||||
for (int k = 0; k < height; k++, a += a_step, b += b_step)
|
||||
for (int l = 0; l < width_n; l++)
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int k = 0; k < height; k++, a += a_step, b += b_step)
|
||||
for (int l = 0; l < width_n; l += 3)
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
ccorr.val[1] += a[l+1]*b[l+1];
|
||||
ccorr.val[2] += a[l+2]*b[l+2];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum.val[1] += a[l+1];
|
||||
a_sum.val[2] += a[l+2];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
a_sum2.val[1] += a[l+1]*a[l+1];
|
||||
a_sum2.val[2] += a[l+2]*a[l+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( method )
|
||||
{
|
||||
case cv::TM_CCORR:
|
||||
case cv::TM_CCORR_NORMED:
|
||||
value = ccorr.val[0];
|
||||
break;
|
||||
case cv::TM_SQDIFF:
|
||||
case cv::TM_SQDIFF_NORMED:
|
||||
value = (a_sum2.val[0] + b_sum2 - 2*ccorr.val[0]);
|
||||
break;
|
||||
default:
|
||||
value = (ccorr.val[0] - a_sum.val[0]*b_mean.val[0]+
|
||||
ccorr.val[1] - a_sum.val[1]*b_mean.val[1]+
|
||||
ccorr.val[2] - a_sum.val[2]*b_mean.val[2]);
|
||||
}
|
||||
|
||||
if( method & 1 )
|
||||
{
|
||||
double denom;
|
||||
|
||||
// calc denominator
|
||||
if( method != cv::TM_CCOEFF_NORMED )
|
||||
{
|
||||
denom = a_sum2.val[0] + a_sum2.val[1] + a_sum2.val[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
denom = a_sum2.val[0] - (a_sum.val[0]*a_sum.val[0])/area;
|
||||
denom += a_sum2.val[1] - (a_sum.val[1]*a_sum.val[1])/area;
|
||||
denom += a_sum2.val[2] - (a_sum.val[2]*a_sum.val[2])/area;
|
||||
}
|
||||
denom = sqrt(MAX(denom,0))*b_denom;
|
||||
if( fabs(value) < denom )
|
||||
value /= denom;
|
||||
else if( fabs(value) < denom*1.125 )
|
||||
value = value > 0 ? 1 : -1;
|
||||
else
|
||||
value = method != cv::TM_SQDIFF_NORMED ? 0 : 1;
|
||||
}
|
||||
result.at<float>(i, j) = (float)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
CV_ENUM(MatchModes, TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED);
|
||||
|
||||
typedef testing::TestWithParam<testing::tuple<perf::MatDepth, int, MatchModes>> matchTemplate_Modes;
|
||||
|
||||
TEST_P(matchTemplate_Modes, accuracy)
|
||||
{
|
||||
const int data_type = CV_MAKE_TYPE(get<0>(GetParam()), get<1>(GetParam()));
|
||||
const int method = get<2>(GetParam());
|
||||
RNG & rng = TS::ptr()->get_rng();
|
||||
|
||||
for (int ITER = 0; ITER < 20; ++ITER)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("iteration %d", ITER));
|
||||
|
||||
const Size imgSize(rng.uniform(128, 320), rng.uniform(128, 240));
|
||||
const Size templSize(rng.uniform(1, 30), rng.uniform(1, 30));
|
||||
Mat img(imgSize, data_type, Scalar::all(0));
|
||||
Mat templ(templSize, data_type, Scalar::all(0));
|
||||
cvtest::randUni(rng, img, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, templ, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
Mat result;
|
||||
cv::matchTemplate(img, templ, result, method);
|
||||
|
||||
Mat reference;
|
||||
matchTemplate_reference(img, templ, reference, method);
|
||||
|
||||
EXPECT_MAT_NEAR_RELATIVE(result, reference, 1e-3);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/,
|
||||
matchTemplate_Modes,
|
||||
testing::Combine(
|
||||
testing::Values(CV_8U, CV_32F),
|
||||
testing::Values(1, 3),
|
||||
testing::Values(TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED)));
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,290 @@
|
||||
// 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"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
CV_ENUM(MatchTemplType, cv::TM_CCORR, cv::TM_CCORR_NORMED,
|
||||
cv::TM_SQDIFF, cv::TM_SQDIFF_NORMED,
|
||||
cv::TM_CCOEFF, cv::TM_CCOEFF_NORMED)
|
||||
|
||||
class Imgproc_MatchTemplateWithMask : public TestWithParam<std::tuple<MatType,MatType>>
|
||||
{
|
||||
protected:
|
||||
// Member functions inherited from ::testing::Test
|
||||
void SetUp() override;
|
||||
|
||||
// Matrices for test calculations (always CV_32)
|
||||
Mat img_;
|
||||
Mat templ_;
|
||||
Mat mask_;
|
||||
Mat templ_masked_;
|
||||
Mat img_roi_masked_;
|
||||
// Matrices for call to matchTemplate (have test type)
|
||||
Mat img_testtype_;
|
||||
Mat templ_testtype_;
|
||||
Mat mask_testtype_;
|
||||
Mat result_;
|
||||
|
||||
// Constants
|
||||
static const Size IMG_SIZE;
|
||||
static const Size TEMPL_SIZE;
|
||||
static const Point TEST_POINT;
|
||||
};
|
||||
|
||||
// Arbitraryly chosen test constants
|
||||
const Size Imgproc_MatchTemplateWithMask::IMG_SIZE(160, 100);
|
||||
const Size Imgproc_MatchTemplateWithMask::TEMPL_SIZE(21, 13);
|
||||
const Point Imgproc_MatchTemplateWithMask::TEST_POINT(8, 9);
|
||||
|
||||
void Imgproc_MatchTemplateWithMask::SetUp()
|
||||
{
|
||||
int type = std::get<0>(GetParam());
|
||||
int type_mask = std::get<1>(GetParam());
|
||||
|
||||
// Matrices are created with the depth to test (for the call to matchTemplate()), but are also
|
||||
// converted to CV_32 for the test calculations, because matchTemplate() also only operates on
|
||||
// and returns CV_32.
|
||||
img_testtype_.create(IMG_SIZE, type);
|
||||
templ_testtype_.create(TEMPL_SIZE, type);
|
||||
mask_testtype_.create(TEMPL_SIZE, type_mask);
|
||||
|
||||
randu(img_testtype_, 0, 10);
|
||||
randu(templ_testtype_, 0, 10);
|
||||
randu(mask_testtype_, 0, 5);
|
||||
|
||||
img_testtype_.convertTo(img_, CV_32F);
|
||||
templ_testtype_.convertTo(templ_, CV_32F);
|
||||
mask_testtype_.convertTo(mask_, CV_32F);
|
||||
if (CV_MAT_DEPTH(type_mask) == CV_8U)
|
||||
{
|
||||
// CV_8U masks are interpreted as binary masks
|
||||
mask_.setTo(Scalar::all(1), mask_ != 0);
|
||||
}
|
||||
if (mask_.channels() != templ_.channels())
|
||||
{
|
||||
std::vector<Mat> mask_channels(templ_.channels(), mask_);
|
||||
merge(mask_channels.data(), templ_.channels(), mask_);
|
||||
}
|
||||
|
||||
Rect roi(TEST_POINT, TEMPL_SIZE);
|
||||
img_roi_masked_ = img_(roi).mul(mask_);
|
||||
templ_masked_ = templ_.mul(mask_);
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask, CompareNaiveImplSQDIFF)
|
||||
{
|
||||
matchTemplate(img_testtype_, templ_testtype_, result_, cv::TM_SQDIFF, mask_testtype_);
|
||||
// Naive implementation for one point
|
||||
Mat temp = img_roi_masked_ - templ_masked_;
|
||||
Scalar temp_s = sum(temp.mul(temp));
|
||||
double val = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
|
||||
EXPECT_NEAR(val, result_.at<float>(TEST_POINT), TEMPL_SIZE.area()*abs(val)*FLT_EPSILON);
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask, CompareNaiveImplSQDIFF_NORMED)
|
||||
{
|
||||
matchTemplate(img_testtype_, templ_testtype_, result_, cv::TM_SQDIFF_NORMED, mask_testtype_);
|
||||
// Naive implementation for one point
|
||||
Mat temp = img_roi_masked_ - templ_masked_;
|
||||
Scalar temp_s = sum(temp.mul(temp));
|
||||
double val = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
|
||||
// Normalization
|
||||
temp_s = sum(templ_masked_.mul(templ_masked_));
|
||||
double norm = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
temp_s = sum(img_roi_masked_.mul(img_roi_masked_));
|
||||
norm *= temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
norm = sqrt(norm);
|
||||
val /= norm;
|
||||
|
||||
EXPECT_NEAR(val, result_.at<float>(TEST_POINT), TEMPL_SIZE.area()*abs(val)*FLT_EPSILON);
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask, CompareNaiveImplCCORR)
|
||||
{
|
||||
matchTemplate(img_testtype_, templ_testtype_, result_, cv::TM_CCORR, mask_testtype_);
|
||||
// Naive implementation for one point
|
||||
Scalar temp_s = sum(templ_masked_.mul(img_roi_masked_));
|
||||
double val = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
|
||||
EXPECT_NEAR(val, result_.at<float>(TEST_POINT), TEMPL_SIZE.area()*abs(val)*FLT_EPSILON);
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask, CompareNaiveImplCCORR_NORMED)
|
||||
{
|
||||
matchTemplate(img_testtype_, templ_testtype_, result_, cv::TM_CCORR_NORMED, mask_testtype_);
|
||||
// Naive implementation for one point
|
||||
Scalar temp_s = sum(templ_masked_.mul(img_roi_masked_));
|
||||
double val = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
|
||||
// Normalization
|
||||
temp_s = sum(templ_masked_.mul(templ_masked_));
|
||||
double norm = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
temp_s = sum(img_roi_masked_.mul(img_roi_masked_));
|
||||
norm *= temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
norm = sqrt(norm);
|
||||
val /= norm;
|
||||
|
||||
EXPECT_NEAR(val, result_.at<float>(TEST_POINT), TEMPL_SIZE.area()*abs(val)*FLT_EPSILON);
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask, CompareNaiveImplCCOEFF)
|
||||
{
|
||||
matchTemplate(img_testtype_, templ_testtype_, result_, cv::TM_CCOEFF, mask_testtype_);
|
||||
// Naive implementation for one point
|
||||
Scalar temp_s = sum(mask_);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (temp_s[i] != 0.0)
|
||||
temp_s[i] = 1.0 / temp_s[i];
|
||||
else
|
||||
temp_s[i] = 1.0;
|
||||
}
|
||||
Mat temp = mask_.clone(); temp = temp_s; // Workaround to multiply Mat by Scalar
|
||||
Mat temp2 = mask_.clone(); temp2 = sum(templ_masked_); // Workaround to multiply Mat by Scalar
|
||||
Mat templx = templ_masked_ - mask_.mul(temp).mul(temp2);
|
||||
temp2 = sum(img_roi_masked_); // Workaround to multiply Mat by Scalar
|
||||
Mat imgx = img_roi_masked_ - mask_.mul(temp).mul(temp2);
|
||||
temp_s = sum(templx.mul(imgx));
|
||||
double val = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
|
||||
EXPECT_NEAR(val, result_.at<float>(TEST_POINT), TEMPL_SIZE.area()*abs(val)*FLT_EPSILON);
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask, CompareNaiveImplCCOEFF_NORMED)
|
||||
{
|
||||
matchTemplate(img_testtype_, templ_testtype_, result_, cv::TM_CCOEFF_NORMED, mask_testtype_);
|
||||
// Naive implementation for one point
|
||||
Scalar temp_s = sum(mask_);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (temp_s[i] != 0.0)
|
||||
temp_s[i] = 1.0 / temp_s[i];
|
||||
else
|
||||
temp_s[i] = 1.0;
|
||||
}
|
||||
Mat temp = mask_.clone(); temp = temp_s; // Workaround to multiply Mat by Scalar
|
||||
Mat temp2 = mask_.clone(); temp2 = sum(templ_masked_); // Workaround to multiply Mat by Scalar
|
||||
Mat templx = templ_masked_ - mask_.mul(temp).mul(temp2);
|
||||
temp2 = sum(img_roi_masked_); // Workaround to multiply Mat by Scalar
|
||||
Mat imgx = img_roi_masked_ - mask_.mul(temp).mul(temp2);
|
||||
temp_s = sum(templx.mul(imgx));
|
||||
double val = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
|
||||
// Normalization
|
||||
temp_s = sum(templx.mul(templx));
|
||||
double norm = temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
temp_s = sum(imgx.mul(imgx));
|
||||
norm *= temp_s[0] + temp_s[1] + temp_s[2] + temp_s[3];
|
||||
norm = sqrt(norm);
|
||||
val /= norm;
|
||||
|
||||
EXPECT_NEAR(val, result_.at<float>(TEST_POINT), TEMPL_SIZE.area()*abs(val)*FLT_EPSILON);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SingleChannelMask, Imgproc_MatchTemplateWithMask,
|
||||
Combine(
|
||||
Values(CV_32FC1, CV_32FC3, CV_8UC1, CV_8UC3),
|
||||
Values(CV_32FC1, CV_8UC1)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MultiChannelMask, Imgproc_MatchTemplateWithMask,
|
||||
Combine(
|
||||
Values(CV_32FC3, CV_8UC3),
|
||||
Values(CV_32FC3, CV_8UC3)));
|
||||
|
||||
class Imgproc_MatchTemplateWithMask2 : public TestWithParam<std::tuple<MatType,MatType,
|
||||
MatchTemplType>>
|
||||
{
|
||||
protected:
|
||||
// Member functions inherited from ::testing::Test
|
||||
void SetUp() override;
|
||||
|
||||
// Data members
|
||||
Mat img_;
|
||||
Mat templ_;
|
||||
Mat mask_;
|
||||
Mat result_withoutmask_;
|
||||
Mat result_withmask_;
|
||||
|
||||
// Constants
|
||||
static const Size IMG_SIZE;
|
||||
static const Size TEMPL_SIZE;
|
||||
};
|
||||
|
||||
// Arbitraryly chosen test constants
|
||||
const Size Imgproc_MatchTemplateWithMask2::IMG_SIZE(160, 100);
|
||||
const Size Imgproc_MatchTemplateWithMask2::TEMPL_SIZE(21, 13);
|
||||
|
||||
void Imgproc_MatchTemplateWithMask2::SetUp()
|
||||
{
|
||||
int type = std::get<0>(GetParam());
|
||||
int type_mask = std::get<1>(GetParam());
|
||||
|
||||
img_.create(IMG_SIZE, type);
|
||||
templ_.create(TEMPL_SIZE, type);
|
||||
mask_.create(TEMPL_SIZE, type_mask);
|
||||
|
||||
randu(img_, 0, 100);
|
||||
randu(templ_, 0, 100);
|
||||
|
||||
if (CV_MAT_DEPTH(type_mask) == CV_8U)
|
||||
{
|
||||
// CV_8U implies binary mask, so all nonzero values should work
|
||||
randu(mask_, 1, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
mask_ = Scalar(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_MatchTemplateWithMask2, CompareWithAndWithoutMask)
|
||||
{
|
||||
int method = std::get<2>(GetParam());
|
||||
|
||||
matchTemplate(img_, templ_, result_withmask_, method, mask_);
|
||||
matchTemplate(img_, templ_, result_withoutmask_, method);
|
||||
|
||||
// Get maximum result for relative error calculation
|
||||
double min_val, max_val;
|
||||
minMaxLoc(abs(result_withmask_), &min_val, &max_val);
|
||||
|
||||
// Get maximum of absolute diff for comparison
|
||||
double mindiff, maxdiff;
|
||||
minMaxLoc(abs(result_withmask_ - result_withoutmask_), &mindiff, &maxdiff);
|
||||
|
||||
EXPECT_LT(maxdiff, max_val*TEMPL_SIZE.area()*FLT_EPSILON);
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SingleChannelMask, Imgproc_MatchTemplateWithMask2,
|
||||
Combine(
|
||||
Values(CV_32FC1, CV_32FC3, CV_8UC1, CV_8UC3),
|
||||
Values(CV_32FC1, CV_8UC1),
|
||||
Values(cv::TM_SQDIFF, cv::TM_SQDIFF_NORMED, cv::TM_CCORR, cv::TM_CCORR_NORMED,
|
||||
cv::TM_CCOEFF, cv::TM_CCOEFF_NORMED)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MultiChannelMask, Imgproc_MatchTemplateWithMask2,
|
||||
Combine(
|
||||
Values(CV_32FC3, CV_8UC3),
|
||||
Values(CV_32FC3, CV_8UC3),
|
||||
Values(cv::TM_SQDIFF, cv::TM_SQDIFF_NORMED, cv::TM_CCORR, cv::TM_CCORR_NORMED,
|
||||
cv::TM_CCOEFF, cv::TM_CCOEFF_NORMED)));
|
||||
|
||||
TEST(Imgproc_MatchTemplateWithMask, bug_26389) {
|
||||
const Mat image = Mat::ones(Size(10, 10), CV_8UC1);
|
||||
const Mat templ = Mat::ones(Size(10, 7), CV_8UC1);
|
||||
const Mat mask = Mat::ones(Size(10, 7), CV_8UC1);
|
||||
|
||||
for (const int method : {TM_CCOEFF, TM_CCOEFF_NORMED})
|
||||
{
|
||||
Mat result;
|
||||
matchTemplate(image, templ, result, method, mask);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,264 @@
|
||||
/*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 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 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
BIGDATA_TEST(Imgproc_Threshold, huge)
|
||||
{
|
||||
Mat m(65000, 40000, CV_8U);
|
||||
ASSERT_FALSE(m.isContinuous());
|
||||
|
||||
uint64 i, n = (uint64)m.rows*m.cols;
|
||||
for( i = 0; i < n; i++ )
|
||||
m.data[i] = (uchar)(i & 255);
|
||||
|
||||
cv::threshold(m, m, 127, 255, cv::THRESH_BINARY);
|
||||
int nz = cv::countNonZero(m); // FIXIT 'int' is not enough here (overflow is possible with other inputs)
|
||||
ASSERT_EQ((uint64)nz, n / 2);
|
||||
}
|
||||
|
||||
TEST(Imgproc_Threshold, threshold_dryrun)
|
||||
{
|
||||
Size sz(16, 16);
|
||||
Mat input_original(sz, CV_8U, Scalar::all(2));
|
||||
Mat input = input_original.clone();
|
||||
std::vector<int> threshTypes = {THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV};
|
||||
std::vector<int> threshFlags = {0, THRESH_OTSU, THRESH_TRIANGLE};
|
||||
for(int threshType : threshTypes)
|
||||
{
|
||||
for(int threshFlag : threshFlags)
|
||||
{
|
||||
const int _threshType = threshType | threshFlag | THRESH_DRYRUN;
|
||||
cv::threshold(input, input, 2.0, 0.0, _threshType);
|
||||
EXPECT_MAT_NEAR(input, input_original, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef tuple < bool, int, int, int, int > Imgproc_Threshold_Masked_Params_t;
|
||||
|
||||
typedef testing::TestWithParam< Imgproc_Threshold_Masked_Params_t > Imgproc_Threshold_Masked_Fixed;
|
||||
|
||||
TEST_P(Imgproc_Threshold_Masked_Fixed, threshold_mask_fixed)
|
||||
{
|
||||
bool useROI = get<0>(GetParam());
|
||||
int depth = get<1>(GetParam());
|
||||
int cn = get<2>(GetParam());
|
||||
int threshType = get<3>(GetParam());
|
||||
int threshFlag = get<4>(GetParam());
|
||||
|
||||
const int _threshType = threshType | threshFlag;
|
||||
Size sz(127, 127);
|
||||
Size wrapperSize = useROI ? Size(sz.width+4, sz.height+4) : sz;
|
||||
Mat wrapper(wrapperSize, CV_MAKETYPE(depth, cn));
|
||||
Mat input = useROI ? Mat(wrapper, Rect(Point(), sz)) : wrapper;
|
||||
cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
Mat mask = cv::Mat::zeros(sz, CV_8UC1);
|
||||
cv::RotatedRect ellipseRect((cv::Point2f)cv::Point(sz.width/2, sz.height/2), (cv::Size2f)sz, 0);
|
||||
cv::ellipse(mask, ellipseRect, cv::Scalar::all(255), cv::FILLED);//for very different mask alignments
|
||||
|
||||
Mat output_with_mask = cv::Mat::zeros(sz, input.type());
|
||||
cv::thresholdWithMask(input, output_with_mask, mask, 127, 255, _threshType);
|
||||
|
||||
cv::bitwise_not(mask, mask);
|
||||
input.copyTo(output_with_mask, mask);
|
||||
|
||||
Mat output_without_mask;
|
||||
cv::threshold(input, output_without_mask, 127, 255, _threshType);
|
||||
input.copyTo(output_without_mask, mask);
|
||||
|
||||
EXPECT_MAT_NEAR(output_with_mask, output_without_mask, 0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgproc_Threshold_Masked_Fixed,
|
||||
testing::Combine(
|
||||
testing::Values(false, true),//use roi
|
||||
testing::Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F),//depth
|
||||
testing::Values(1, 3),//channels
|
||||
testing::Values(THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV),// threshTypes
|
||||
testing::Values(0)
|
||||
)
|
||||
);
|
||||
|
||||
typedef testing::TestWithParam< Imgproc_Threshold_Masked_Params_t > Imgproc_Threshold_Masked_Auto;
|
||||
|
||||
TEST_P(Imgproc_Threshold_Masked_Auto, threshold_mask_auto)
|
||||
{
|
||||
bool useROI = get<0>(GetParam());
|
||||
int depth = get<1>(GetParam());
|
||||
int cn = get<2>(GetParam());
|
||||
int threshType = get<3>(GetParam());
|
||||
int threshFlag = get<4>(GetParam());
|
||||
|
||||
if (threshFlag == THRESH_TRIANGLE && depth != CV_8U)
|
||||
throw SkipTestException("THRESH_TRIANGLE option supports CV_8UC1 input only");
|
||||
|
||||
const int _threshType = threshType | threshFlag;
|
||||
Size sz(127, 127);
|
||||
Size wrapperSize = useROI ? Size(sz.width+4, sz.height+4) : sz;
|
||||
Mat wrapper(wrapperSize, CV_MAKETYPE(depth, cn));
|
||||
Mat input = useROI ? Mat(wrapper, Rect(Point(), sz)) : wrapper;
|
||||
cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
//for OTSU and TRIANGLE, we use a rectangular mask that can be just cropped
|
||||
//in order to compute the threshold of the non-masked version
|
||||
Mat mask = cv::Mat::zeros(sz, CV_8UC1);
|
||||
cv::Rect roiRect(sz.width/4, sz.height/4, sz.width/2, sz.height/2);
|
||||
cv::rectangle(mask, roiRect, cv::Scalar::all(255), cv::FILLED);
|
||||
|
||||
Mat output_with_mask = cv::Mat::zeros(sz, input.type());
|
||||
const double autoThreshWithMask = cv::thresholdWithMask(input, output_with_mask, mask, 127, 255, _threshType);
|
||||
output_with_mask = Mat(output_with_mask, roiRect);
|
||||
|
||||
Mat output_without_mask;
|
||||
const double autoThresholdWithoutMask = cv::threshold(Mat(input, roiRect), output_without_mask, 127, 255, _threshType);
|
||||
|
||||
ASSERT_EQ(autoThreshWithMask, autoThresholdWithoutMask);
|
||||
EXPECT_MAT_NEAR(output_with_mask, output_without_mask, 0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgproc_Threshold_Masked_Auto,
|
||||
testing::Combine(
|
||||
testing::Values(false, true),//use roi
|
||||
testing::Values(CV_8U, CV_16U),//depth
|
||||
testing::Values(1),//channels
|
||||
testing::Values(THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV),// threshTypes
|
||||
testing::Values(THRESH_OTSU, THRESH_TRIANGLE)
|
||||
)
|
||||
);
|
||||
|
||||
TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_16085)
|
||||
{
|
||||
Size sz(16, 16);
|
||||
Mat input(sz, CV_32F, Scalar::all(2));
|
||||
Mat result;
|
||||
cv::threshold(input, result, 2.0, 0.0, THRESH_TOZERO);
|
||||
EXPECT_EQ(0, cv::norm(result, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_21258)
|
||||
{
|
||||
Size sz(16, 16);
|
||||
float val = nextafterf(16.0f, 0.0f); // 0x417fffff, all bits in mantissa are 1
|
||||
Mat input(sz, CV_32F, Scalar::all(val));
|
||||
Mat result;
|
||||
cv::threshold(input, result, val, 0.0, THRESH_TOZERO);
|
||||
EXPECT_EQ(0, cv::norm(result, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_21258_Min)
|
||||
{
|
||||
Size sz(16, 16);
|
||||
float min_val = -std::numeric_limits<float>::max();
|
||||
Mat input(sz, CV_32F, Scalar::all(min_val));
|
||||
Mat result;
|
||||
cv::threshold(input, result, min_val, 0.0, THRESH_TOZERO);
|
||||
EXPECT_EQ(0, cv::norm(result, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_21258_Max)
|
||||
{
|
||||
Size sz(16, 16);
|
||||
float max_val = std::numeric_limits<float>::max();
|
||||
Mat input(sz, CV_32F, Scalar::all(max_val));
|
||||
Mat result;
|
||||
cv::threshold(input, result, max_val, 0.0, THRESH_TOZERO);
|
||||
EXPECT_EQ(0, cv::norm(result, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_AdaptiveThreshold, mean)
|
||||
{
|
||||
const string input_path = cvtest::findDataFile("../cv/shared/baboon.png");
|
||||
Mat input = imread(input_path, IMREAD_GRAYSCALE);
|
||||
Mat result;
|
||||
|
||||
cv::adaptiveThreshold(input, result, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, 8);
|
||||
|
||||
const string gt_path = cvtest::findDataFile("../cv/imgproc/adaptive_threshold1.png");
|
||||
Mat gt = imread(gt_path, IMREAD_GRAYSCALE);
|
||||
EXPECT_EQ(0, cv::norm(result, gt, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_AdaptiveThreshold, mean_inv)
|
||||
{
|
||||
const string input_path = cvtest::findDataFile("../cv/shared/baboon.png");
|
||||
Mat input = imread(input_path, IMREAD_GRAYSCALE);
|
||||
Mat result;
|
||||
|
||||
cv::adaptiveThreshold(input, result, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV, 15, 8);
|
||||
|
||||
const string gt_path = cvtest::findDataFile("../cv/imgproc/adaptive_threshold1.png");
|
||||
Mat gt = imread(gt_path, IMREAD_GRAYSCALE);
|
||||
gt = Mat(gt.rows, gt.cols, CV_8UC1, cv::Scalar(255)) - gt;
|
||||
EXPECT_EQ(0, cv::norm(result, gt, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_AdaptiveThreshold, gauss)
|
||||
{
|
||||
const string input_path = cvtest::findDataFile("../cv/shared/baboon.png");
|
||||
Mat input = imread(input_path, IMREAD_GRAYSCALE);
|
||||
Mat result;
|
||||
|
||||
cv::adaptiveThreshold(input, result, 200, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 21, -5);
|
||||
|
||||
const string gt_path = cvtest::findDataFile("../cv/imgproc/adaptive_threshold2.png");
|
||||
Mat gt = imread(gt_path, IMREAD_GRAYSCALE);
|
||||
EXPECT_EQ(0, cv::norm(result, gt, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Imgproc_AdaptiveThreshold, gauss_inv)
|
||||
{
|
||||
const string input_path = cvtest::findDataFile("../cv/shared/baboon.png");
|
||||
Mat input = imread(input_path, IMREAD_GRAYSCALE);
|
||||
Mat result;
|
||||
|
||||
cv::adaptiveThreshold(input, result, 200, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, -5);
|
||||
|
||||
const string gt_path = cvtest::findDataFile("../cv/imgproc/adaptive_threshold2.png");
|
||||
Mat gt = imread(gt_path, IMREAD_GRAYSCALE);
|
||||
gt = Mat(gt.rows, gt.cols, CV_8UC1, cv::Scalar(200)) - gt;
|
||||
EXPECT_EQ(0, cv::norm(result, gt, NORM_INF));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,43 @@
|
||||
/*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"
|
||||
Reference in New Issue
Block a user