mirror of
https://github.com/opencv/opencv.git
synced 2025-06-16 14:50:52 +08:00
Merge pull request #8949 from alalek:fix_sortIdx
This commit is contained in:
commit
437ca0b62a
@ -4384,11 +4384,10 @@ static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags )
|
|||||||
{
|
{
|
||||||
CV_INSTRUMENT_REGION_IPP()
|
CV_INSTRUMENT_REGION_IPP()
|
||||||
|
|
||||||
bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
|
bool sortRows = (flags & 1) == SORT_EVERY_ROW;
|
||||||
bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
|
bool sortDescending = (flags & SORT_DESCENDING) != 0;
|
||||||
int depth = src.depth();
|
int depth = src.depth();
|
||||||
IppDataType type = ippiGetDataType(depth);
|
IppDataType type = ippiGetDataType(depth);
|
||||||
Ipp32s elemSize = (Ipp32s)src.elemSize1();
|
|
||||||
|
|
||||||
IppSortIndexFunc ippsSortRadixIndex = getSortIndexFunc(depth, sortDescending);
|
IppSortIndexFunc ippsSortRadixIndex = getSortIndexFunc(depth, sortDescending);
|
||||||
if(!ippsSortRadixIndex)
|
if(!ippsSortRadixIndex)
|
||||||
@ -4405,7 +4404,7 @@ static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags )
|
|||||||
|
|
||||||
for(int i = 0; i < src.rows; i++)
|
for(int i = 0; i < src.rows; i++)
|
||||||
{
|
{
|
||||||
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (void*)src.ptr(i), elemSize, (Ipp32s*)dst.ptr(i), src.cols, buffer) < 0)
|
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (const void*)src.ptr(i), (Ipp32s)src.step[1], (Ipp32s*)dst.ptr(i), src.cols, buffer) < 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4422,13 +4421,13 @@ static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags )
|
|||||||
|
|
||||||
buffer.allocate(bufferSize);
|
buffer.allocate(bufferSize);
|
||||||
|
|
||||||
Ipp32s pixStride = elemSize*dst.cols;
|
Ipp32s srcStep = (Ipp32s)src.step[0];
|
||||||
for(int i = 0; i < src.cols; i++)
|
for(int i = 0; i < src.cols; i++)
|
||||||
{
|
{
|
||||||
subRect.x = i;
|
subRect.x = i;
|
||||||
dstSub = Mat(dst, subRect);
|
dstSub = Mat(dst, subRect);
|
||||||
|
|
||||||
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (void*)src.ptr(0, i), pixStride, (Ipp32s*)dstRow.ptr(), src.rows, buffer) < 0)
|
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (const void*)src.ptr(0, i), srcStep, (Ipp32s*)dstRow.ptr(), src.rows, buffer) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
dstRow = dstRow.reshape(1, dstSub.rows);
|
dstRow = dstRow.reshape(1, dstSub.rows);
|
||||||
|
@ -41,17 +41,10 @@
|
|||||||
//M*/
|
//M*/
|
||||||
|
|
||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
|
#include "opencv2/ts/ocl_test.hpp" // T-API like tests
|
||||||
|
|
||||||
#include <string>
|
namespace cvtest {
|
||||||
#include <iostream>
|
namespace {
|
||||||
#include <fstream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <limits>
|
|
||||||
#include <numeric>
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
class CV_OperationsTest : public cvtest::BaseTest
|
class CV_OperationsTest : public cvtest::BaseTest
|
||||||
{
|
{
|
||||||
@ -1120,8 +1113,8 @@ void CV_OperationsTest::run( int /* start_from */)
|
|||||||
if (!TestTemplateMat())
|
if (!TestTemplateMat())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* if (!TestMatND())
|
if (!TestMatND())
|
||||||
return;*/
|
return;
|
||||||
|
|
||||||
if (!TestSparseMat())
|
if (!TestSparseMat())
|
||||||
return;
|
return;
|
||||||
@ -1254,3 +1247,145 @@ TEST(MatTestRoi, adjustRoiOverflow)
|
|||||||
|
|
||||||
ASSERT_EQ(roi.rows, m.rows);
|
ASSERT_EQ(roi.rows, m.rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CV_ENUM(SortRowCol, SORT_EVERY_COLUMN, SORT_EVERY_ROW)
|
||||||
|
CV_ENUM(SortOrder, SORT_ASCENDING, SORT_DESCENDING)
|
||||||
|
|
||||||
|
PARAM_TEST_CASE(sortIdx, MatDepth, SortRowCol, SortOrder, Size, bool)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
Size size;
|
||||||
|
int flags;
|
||||||
|
bool use_roi;
|
||||||
|
|
||||||
|
Mat src, src_roi;
|
||||||
|
Mat dst, dst_roi;
|
||||||
|
|
||||||
|
virtual void SetUp()
|
||||||
|
{
|
||||||
|
int depth = GET_PARAM(0);
|
||||||
|
int rowFlags = GET_PARAM(1);
|
||||||
|
int orderFlags = GET_PARAM(2);
|
||||||
|
size = GET_PARAM(3);
|
||||||
|
use_roi = GET_PARAM(4);
|
||||||
|
|
||||||
|
type = CV_MAKE_TYPE(depth, 1);
|
||||||
|
|
||||||
|
flags = rowFlags | orderFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateTestData()
|
||||||
|
{
|
||||||
|
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||||
|
randomSubMat(src, src_roi, size, srcBorder, type, -100, 100);
|
||||||
|
|
||||||
|
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||||
|
randomSubMat(dst, dst_roi, size, dstBorder, CV_32S, 5, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void check_(const cv::Mat& values_, const cv::Mat_<int>& idx_)
|
||||||
|
{
|
||||||
|
cv::Mat_<T>& values = (cv::Mat_<T>&)values_;
|
||||||
|
cv::Mat_<int>& idx = (cv::Mat_<int>&)idx_;
|
||||||
|
size_t N = values.total();
|
||||||
|
std::vector<bool> processed(N, false);
|
||||||
|
int prevIdx = idx(0);
|
||||||
|
T prevValue = values(prevIdx);
|
||||||
|
processed[prevIdx] = true;
|
||||||
|
for (size_t i = 1; i < N; i++)
|
||||||
|
{
|
||||||
|
int nextIdx = idx((int)i);
|
||||||
|
T value = values(nextIdx);
|
||||||
|
ASSERT_EQ(false, processed[nextIdx]) << "Indexes must be unique. i=" << i << " idx=" << nextIdx << std::endl << idx;
|
||||||
|
processed[nextIdx] = true;
|
||||||
|
if ((flags & SORT_DESCENDING) == SORT_DESCENDING)
|
||||||
|
ASSERT_GE(prevValue, value) << "i=" << i << " prevIdx=" << prevIdx << " idx=" << nextIdx;
|
||||||
|
else
|
||||||
|
ASSERT_LE(prevValue, value) << "i=" << i << " prevIdx=" << prevIdx << " idx=" << nextIdx;
|
||||||
|
prevValue = value;
|
||||||
|
prevIdx = nextIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void validate()
|
||||||
|
{
|
||||||
|
ASSERT_EQ(CV_32SC1, dst_roi.type());
|
||||||
|
ASSERT_EQ(size, dst_roi.size());
|
||||||
|
bool isColumn = (flags & SORT_EVERY_COLUMN) == SORT_EVERY_COLUMN;
|
||||||
|
size_t N = isColumn ? src_roi.cols : src_roi.rows;
|
||||||
|
Mat values_row((int)N, 1, type), idx_row((int)N, 1, CV_32S);
|
||||||
|
for (size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
SCOPED_TRACE(cv::format("row/col=%d", (int)i));
|
||||||
|
if (isColumn)
|
||||||
|
{
|
||||||
|
src_roi.col((int)i).copyTo(values_row);
|
||||||
|
dst_roi.col((int)i).copyTo(idx_row);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src_roi.row((int)i).copyTo(values_row);
|
||||||
|
dst_roi.row((int)i).copyTo(idx_row);
|
||||||
|
}
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case CV_8U: check_<uchar>(values_row, idx_row); break;
|
||||||
|
case CV_8S: check_<char>(values_row, idx_row); break;
|
||||||
|
case CV_16S: check_<short>(values_row, idx_row); break;
|
||||||
|
case CV_32S: check_<int>(values_row, idx_row); break;
|
||||||
|
case CV_32F: check_<float>(values_row, idx_row); break;
|
||||||
|
case CV_64F: check_<double>(values_row, idx_row); break;
|
||||||
|
default: ASSERT_FALSE(true) << "Unsupported type: " << type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(sortIdx, simple)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 5; j++)
|
||||||
|
{
|
||||||
|
generateTestData();
|
||||||
|
|
||||||
|
cv::sortIdx(src_roi, dst_roi, flags);
|
||||||
|
validate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(Core, sortIdx, Combine(
|
||||||
|
Values(CV_8U, CV_8S, CV_16S, CV_32S, CV_32F, CV_64F), // depth
|
||||||
|
Values(SORT_EVERY_COLUMN, SORT_EVERY_ROW),
|
||||||
|
Values(SORT_ASCENDING, SORT_DESCENDING),
|
||||||
|
Values(Size(3, 3), Size(16, 8)),
|
||||||
|
::testing::Bool()
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Core_sortIdx, regression_8941)
|
||||||
|
{
|
||||||
|
cv::Mat src = (cv::Mat_<int>(3, 3) <<
|
||||||
|
1, 2, 3,
|
||||||
|
0, 9, 5,
|
||||||
|
8, 1, 6
|
||||||
|
);
|
||||||
|
cv::Mat expected = (cv::Mat_<int>(3, 1) <<
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
cv::Mat result;
|
||||||
|
cv::sortIdx(src.col(0), result, CV_SORT_EVERY_COLUMN | CV_SORT_ASCENDING);
|
||||||
|
#if 0
|
||||||
|
std::cout << src.col(0) << std::endl;
|
||||||
|
std::cout << result << std::endl;
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected.size(), result.size());
|
||||||
|
EXPECT_EQ(0, cvtest::norm(expected, result, NORM_INF)) <<
|
||||||
|
"result=" << std::endl << result << std::endl <<
|
||||||
|
"expected=" << std::endl << expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
|
|
||||||
#include "cvconfig.h"
|
#include "cvconfig.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
#ifdef WINRT
|
#ifdef WINRT
|
||||||
#pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
|
#pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
|
||||||
#endif
|
#endif
|
||||||
@ -46,14 +54,10 @@ namespace cvtest
|
|||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::string;
|
using std::string;
|
||||||
using cv::RNG;
|
using namespace cv;
|
||||||
using cv::Mat;
|
using testing::Values;
|
||||||
using cv::Scalar;
|
using testing::Combine;
|
||||||
using cv::Size;
|
|
||||||
using cv::Point;
|
|
||||||
using cv::Rect;
|
|
||||||
using cv::InputArray;
|
|
||||||
using cv::noArray;
|
|
||||||
|
|
||||||
class SkipTestException: public cv::Exception
|
class SkipTestException: public cv::Exception
|
||||||
{
|
{
|
||||||
@ -632,10 +636,12 @@ int main(int argc, char **argv) \
|
|||||||
|
|
||||||
} //namespace cvtest
|
} //namespace cvtest
|
||||||
|
|
||||||
#endif // OPENCV_TS_HPP
|
|
||||||
|
|
||||||
#include "opencv2/ts/ts_perf.hpp"
|
#include "opencv2/ts/ts_perf.hpp"
|
||||||
|
|
||||||
|
namespace cvtest {
|
||||||
|
using perf::MatDepth;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WINRT
|
#ifdef WINRT
|
||||||
#ifndef __FSTREAM_EMULATED__
|
#ifndef __FSTREAM_EMULATED__
|
||||||
#define __FSTREAM_EMULATED__
|
#define __FSTREAM_EMULATED__
|
||||||
@ -734,3 +740,5 @@ public:
|
|||||||
} // namespace std
|
} // namespace std
|
||||||
#endif // __FSTREAM_EMULATED__
|
#endif // __FSTREAM_EMULATED__
|
||||||
#endif // WINRT
|
#endif // WINRT
|
||||||
|
|
||||||
|
#endif // OPENCV_TS_HPP
|
||||||
|
@ -109,6 +109,7 @@ namespace cvtest
|
|||||||
|
|
||||||
CV_EXPORTS testing::AssertionResult assertMatNear(const char* expr1, const char* expr2, const char* eps_expr, cv::InputArray m1, cv::InputArray m2, double eps);
|
CV_EXPORTS testing::AssertionResult assertMatNear(const char* expr1, const char* expr2, const char* eps_expr, cv::InputArray m1, cv::InputArray m2, double eps);
|
||||||
|
|
||||||
|
#undef EXPECT_MAT_NEAR
|
||||||
#define EXPECT_MAT_NEAR(m1, m2, eps) EXPECT_PRED_FORMAT3(cvtest::assertMatNear, m1, m2, eps)
|
#define EXPECT_MAT_NEAR(m1, m2, eps) EXPECT_PRED_FORMAT3(cvtest::assertMatNear, m1, m2, eps)
|
||||||
#define ASSERT_MAT_NEAR(m1, m2, eps) ASSERT_PRED_FORMAT3(cvtest::assertMatNear, m1, m2, eps)
|
#define ASSERT_MAT_NEAR(m1, m2, eps) ASSERT_PRED_FORMAT3(cvtest::assertMatNear, m1, m2, eps)
|
||||||
|
|
||||||
@ -153,6 +154,7 @@ namespace cvtest
|
|||||||
|
|
||||||
CV_EXPORTS double checkSimilarity(cv::InputArray m1, cv::InputArray m2);
|
CV_EXPORTS double checkSimilarity(cv::InputArray m1, cv::InputArray m2);
|
||||||
|
|
||||||
|
#undef EXPECT_MAT_SIMILAR
|
||||||
#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \
|
#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \
|
||||||
{ \
|
{ \
|
||||||
ASSERT_EQ(mat1.type(), mat2.type()); \
|
ASSERT_EQ(mat1.type(), mat2.type()); \
|
||||||
|
@ -94,6 +94,7 @@ do \
|
|||||||
EXPECT_LE(TestUtils::checkNorm1(mat), eps) \
|
EXPECT_LE(TestUtils::checkNorm1(mat), eps) \
|
||||||
} while ((void)0, 0)
|
} while ((void)0, 0)
|
||||||
|
|
||||||
|
#undef EXPECT_MAT_NEAR
|
||||||
#define EXPECT_MAT_NEAR(mat1, mat2, eps) \
|
#define EXPECT_MAT_NEAR(mat1, mat2, eps) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
@ -178,6 +179,7 @@ do \
|
|||||||
<< "Size: " << name ## _roi.size() << std::endl; \
|
<< "Size: " << name ## _roi.size() << std::endl; \
|
||||||
} while ((void)0, 0)
|
} while ((void)0, 0)
|
||||||
|
|
||||||
|
#undef EXPECT_MAT_SIMILAR
|
||||||
#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \
|
#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
@ -325,7 +327,7 @@ struct CV_EXPORTS TSTestWithParam : public TestUtils, public ::testing::TestWith
|
|||||||
};
|
};
|
||||||
|
|
||||||
#undef PARAM_TEST_CASE
|
#undef PARAM_TEST_CASE
|
||||||
#define PARAM_TEST_CASE(name, ...) struct name : public TSTestWithParam< std::tr1::tuple< __VA_ARGS__ > >
|
#define PARAM_TEST_CASE(name, ...) struct name : public ::cvtest::ocl::TSTestWithParam< std::tr1::tuple< __VA_ARGS__ > >
|
||||||
|
|
||||||
#ifndef IMPLEMENT_PARAM_CLASS
|
#ifndef IMPLEMENT_PARAM_CLASS
|
||||||
#define IMPLEMENT_PARAM_CLASS(name, type) \
|
#define IMPLEMENT_PARAM_CLASS(name, type) \
|
||||||
|
Loading…
Reference in New Issue
Block a user