Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0be4f3f

Browse files
committed
implement ArgMax and ArgMin
1 parentc7e0888 commit0be4f3f

File tree

7 files changed

+339
-2
lines changed

7 files changed

+339
-2
lines changed

‎modules/core/include/opencv2/core.hpp‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,12 +819,36 @@ mixChannels , or split .
819819
@param minLoc pointer to the returned minimum location (in 2D case); NULL is used if not required.
820820
@param maxLoc pointer to the returned maximum location (in 2D case); NULL is used if not required.
821821
@param mask optional mask used to select a sub-array.
822-
@sa max, min, compare, inRange, extractImageCOI, mixChannels, split, Mat::reshape
822+
@sa max, min,reduceMinMax,compare, inRange, extractImageCOI, mixChannels, split, Mat::reshape
823823
*/
824824
CV_EXPORTS_WvoidminMaxLoc(InputArray src, CV_OUTdouble* minVal,
825825
CV_OUTdouble* maxVal =0, CV_OUT Point* minLoc =0,
826826
CV_OUT Point* maxLoc =0, InputArray mask = noArray());
827827

828+
enumclassReduceMinMaxMode
829+
{
830+
FIRST_MIN =0,//!< get index of first min occurrence
831+
LAST_MIN =1,//!< get index of last min occurrence
832+
FIRST_MAX =2,//!< get index of first max occurrence
833+
LAST_MAX =3,//!< get index of last max occurrence
834+
};
835+
836+
/**
837+
* @brief Finds indices of min or max elements along provided axis
838+
*
839+
* @note
840+
* - If input or output array is not continuous, this function will create an internal copy.
841+
* - NaN handling is left unspecified, see patchNaNs().
842+
* - The returned index is always in bounds of input matrix.
843+
*
844+
* @param src input single-channel array.
845+
* @param dst output array of type CV_32SC1 with the same dimensionality as src,
846+
* except for axis being reduced - it should be set to 1.
847+
* @param mode whether to get the index of first or last occurrence of min or max.
848+
* @param axis axis to reduce along.
849+
* @sa minMaxLoc, min, max, compare, reduce
850+
*/
851+
CV_EXPORTS_WvoidreduceMinMax(InputArray src, OutputArray dst, ReduceMinMaxMode mode,int axis);
828852

829853
/** @brief Finds the global minimum and maximum in an array
830854
@@ -886,7 +910,7 @@ a single row. 1 means that the matrix is reduced to a single column.
886910
@param rtype reduction operation that could be one of #ReduceTypes
887911
@param dtype when negative, the output vector will have the same type as the input matrix,
888912
otherwise, its type will be CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels()).
889-
@sa repeat
913+
@sa repeat, reduceMinMax
890914
*/
891915
CV_EXPORTS_Wvoidreduce(InputArray src, OutputArray dst,int dim,int rtype,int dtype = -1);
892916

‎modules/core/perf/perf_reduce.cpp‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,35 @@ PERF_TEST_P(Size_MatType_ROp, reduceC,
6565
SANITY_CHECK(vec,1);
6666
}
6767

68+
typedef tuple<Size, MatType, cv::ReduceMinMaxMode,int> Size_MatType_RMode_t;
69+
typedef perf::TestBaseWithParam<Size_MatType_RMode_t> Size_MatType_RMode;
70+
71+
PERF_TEST_P(Size_MatType_RMode, reduceMinMax, testing::Combine(
72+
testing::Values(TYPICAL_MAT_SIZES),
73+
testing::Values(CV_8U, CV_32F),
74+
testing::Values(cv::ReduceMinMaxMode::FIRST_MIN, cv::ReduceMinMaxMode::LAST_MAX),
75+
testing::Values(0,1)
76+
)
77+
)
78+
{
79+
Size srcSize = get<0>(GetParam());
80+
int matType = get<1>(GetParam());
81+
ReduceMinMaxMode mode = get<2>(GetParam());
82+
int axis = get<3>(GetParam());
83+
84+
Matsrc(srcSize, matType);
85+
86+
std::vector<int>dstSize(src.dims);
87+
std::copy(src.size.p, src.size.p + src.dims, dstSize.begin());
88+
dstSize[axis] =1;
89+
90+
Matdst(dstSize, CV_32S,0.);
91+
92+
declare.in(src, WARMUP_RNG).out(dst);
93+
94+
TEST_CYCLE()cv::reduceMinMax(src, dst, mode, axis);
95+
96+
SANITY_CHECK_NOTHING();
97+
}
98+
6899
}// namespace

‎modules/core/src/minmax.cpp‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
#include"opencl_kernels_core.hpp"
88
#include"opencv2/core/openvx/ovx_defs.hpp"
99
#include"stat.hpp"
10+
#include"utils/depth_dispatch.hpp"
11+
12+
#include<algorithm>
1013

1114
#undef HAVE_IPP
1215
#undef CV_IPP_RUN_FAST
@@ -1570,3 +1573,100 @@ void cv::minMaxLoc( InputArray _img, double* minVal, double* maxVal,
15701573
if( maxLoc )
15711574
std::swap(maxLoc->x, maxLoc->y);
15721575
}
1576+
1577+
template<typename T>
1578+
structreduceMinMaxImpl
1579+
{
1580+
voidoperator()(const cv::Mat& src, cv::Mat& dst, cv::ReduceMinMaxMode mode,constint axis)const
1581+
{
1582+
switch(mode)
1583+
{
1584+
case cv::ReduceMinMaxMode::FIRST_MIN:
1585+
reduceMinMaxApply<std::less>(src, dst, axis);
1586+
break;
1587+
case cv::ReduceMinMaxMode::LAST_MIN:
1588+
reduceMinMaxApply<std::less_equal>(src, dst, axis);
1589+
break;
1590+
case cv::ReduceMinMaxMode::FIRST_MAX:
1591+
reduceMinMaxApply<std::greater>(src, dst, axis);
1592+
break;
1593+
case cv::ReduceMinMaxMode::LAST_MAX:
1594+
reduceMinMaxApply<std::greater_equal>(src, dst, axis);
1595+
break;
1596+
}
1597+
}
1598+
1599+
template<template<class>classCmp>
1600+
staticvoidreduceMinMaxApply(const cv::Mat& src, cv::Mat& dst,constint axis)
1601+
{
1602+
Cmp<T> cmp;
1603+
1604+
constauto *src_ptr = src.ptr<T>();
1605+
auto *dst_ptr = dst.ptr<int32_t>();
1606+
1607+
constsize_t outer_size = src.total(0, axis);
1608+
constauto mid_size =static_cast<size_t>(src.size[axis]);
1609+
1610+
constsize_t outer_step = src.total(axis);
1611+
constsize_t dst_step = dst.total(axis);
1612+
1613+
constsize_t mid_step = src.total(axis +1);
1614+
1615+
for (size_t outer =0; outer < outer_size; ++outer)
1616+
{
1617+
constsize_t outer_offset = outer * outer_step;
1618+
constsize_t dst_offset = outer * dst_step;
1619+
for (size_t mid =0; mid != mid_size; ++mid)
1620+
{
1621+
constsize_t src_offset = outer_offset + mid * mid_step;
1622+
for (size_t inner =0; inner < mid_step; inner++)
1623+
{
1624+
int32_t& index = dst_ptr[dst_offset + inner];
1625+
1626+
constsize_t prev = outer_offset + index * mid_step + inner;
1627+
constsize_t curr = src_offset + inner;
1628+
1629+
if (cmp(src_ptr[curr], src_ptr[prev]))
1630+
{
1631+
index =static_cast<int32_t>(mid);
1632+
}
1633+
}
1634+
}
1635+
}
1636+
}
1637+
};
1638+
1639+
voidcv::reduceMinMax(InputArray src, OutputArray dst, ReduceMinMaxMode mode,int axis)
1640+
{
1641+
CV_INSTRUMENT_REGION();
1642+
1643+
cv::Mat srcMat = src.getMat();
1644+
axis = (axis + srcMat.dims) % srcMat.dims;
1645+
CV_Assert(srcMat.channels() ==1 && axis >=0 && axis < srcMat.dims);
1646+
1647+
std::vector<int>sizes(srcMat.dims);
1648+
std::copy(srcMat.size.p, srcMat.size.p + srcMat.dims, sizes.begin());
1649+
sizes[axis] =1;
1650+
1651+
dst.create(srcMat.dims, sizes.data(), CV_32SC1);// indices
1652+
cv::Mat dstMat = dst.getMat();
1653+
dstMat.setTo(cv::Scalar::all(0));
1654+
1655+
if (!srcMat.isContinuous())
1656+
{
1657+
srcMat = srcMat.clone();
1658+
}
1659+
1660+
bool needs_copy = !dstMat.isContinuous();
1661+
if (needs_copy)
1662+
{
1663+
dstMat = dstMat.clone();
1664+
}
1665+
1666+
cv::utils::depthDispatch<reduceMinMaxImpl>(srcMat.depth(), srcMat, dstMat, mode, axis);
1667+
1668+
if (needs_copy)
1669+
{
1670+
dstMat.copyTo(dst);
1671+
}
1672+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
#ifndef OPENCV_DEPTH_DISPATCH_HPP
6+
#defineOPENCV_DEPTH_DISPATCH_HPP
7+
8+
namespacecv {
9+
namespaceutils {
10+
11+
template<template<typename>classFunctor,typename... Args>
12+
voiddepthDispatch(constint depth, Args&&... args)
13+
{
14+
switch (depth)
15+
{
16+
case CV_8U:
17+
Functor<uint8_t>{}(std::forward<Args>(args)...);
18+
break;
19+
case CV_8S:
20+
Functor<int8_t>{}(std::forward<Args>(args)...);
21+
break;
22+
case CV_16U:
23+
Functor<uint16_t>{}(std::forward<Args>(args)...);
24+
break;
25+
case CV_16S:
26+
Functor<int16_t>{}(std::forward<Args>(args)...);
27+
break;
28+
case CV_32S:
29+
Functor<int32_t>{}(std::forward<Args>(args)...);
30+
break;
31+
case CV_32F:
32+
Functor<float>{}(std::forward<Args>(args)...);
33+
break;
34+
case CV_64F:
35+
Functor<double>{}(std::forward<Args>(args)...);
36+
break;
37+
case CV_16F:
38+
default:
39+
CV_Error(cv::Error::BadDepth,"Unsupported matrix type.");
40+
};
41+
}
42+
43+
}}
44+
45+
#endif//OPENCV_DEPTH_DISPATCH_HPP

‎modules/core/test/test_arithm.cpp‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,47 @@ struct MinMaxLocOp : public BaseElemWiseOp
13871387
}
13881388
};
13891389

1390+
structreduceArgMaxOp :publicBaseElemWiseOp
1391+
{
1392+
reduceArgMaxOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA,1,1, Scalar::all(0))
1393+
{
1394+
context = ARITHM_MAX_NDIMS*2 +2;
1395+
};
1396+
intgetRandomType(RNG& rng)override
1397+
{
1398+
returncvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S,1,1);
1399+
}
1400+
voidgetRandomSize(RNG& rng, vector<int>& size)override
1401+
{
1402+
cvtest::randomSize(rng,2, ARITHM_MAX_NDIMS,6, size);
1403+
}
1404+
voidgenerateScalars(int depth, RNG& rng)override
1405+
{
1406+
BaseElemWiseOp::generateScalars(depth, rng);
1407+
mode =static_cast<cv::ReduceMinMaxMode>(randInt(rng) &0b11);
1408+
axis =randInt(rng);
1409+
}
1410+
intgetAxis(const Mat& src)
1411+
{
1412+
int dims = src.dims;
1413+
returnstatic_cast<int>(axis % (2 * dims)) - dims;// [-dims; dims - 1]
1414+
}
1415+
voidop(const vector<Mat>& src, Mat& dst,const Mat&)override
1416+
{
1417+
const Mat& inp = src[0];
1418+
int axis_ =getAxis(inp);
1419+
cv::reduceMinMax(inp, dst, mode, axis_);
1420+
}
1421+
voidrefop(const vector<Mat>& src, Mat& dst,const Mat&)override
1422+
{
1423+
const Mat& inp = src[0];
1424+
int axis_ =getAxis(inp);
1425+
cvtest::reduceMinMax(inp, dst, mode, axis_);
1426+
}
1427+
cv::ReduceMinMaxMode mode;
1428+
uint32_t axis;
1429+
};
1430+
13901431

13911432
typedef Ptr<BaseElemWiseOp> ElemWiseOpPtr;
13921433
classElemWiseTest : public ::testing::TestWithParam<ElemWiseOpPtr> {};
@@ -1492,6 +1533,7 @@ INSTANTIATE_TEST_CASE_P(Core_MeanStdDev, ElemWiseTest, ::testing::Values(ElemWis
14921533
INSTANTIATE_TEST_CASE_P(Core_Sum, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SumOp)));
14931534
INSTANTIATE_TEST_CASE_P(Core_Norm, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new NormOp)));
14941535
INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MinMaxLocOp)));
1536+
INSTANTIATE_TEST_CASE_P(Core_reduceArgMax, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new reduceArgMaxOp)));
14951537
INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CartToPolarToCartOp)));
14961538

14971539

‎modules/ts/include/opencv2/ts.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ void initInverseRectificationMap( const Mat& a, const Mat& k, const Mat& R, cons
330330

331331
voidminMaxLoc(const Mat& src,double* minval,double* maxval,
332332
vector<int>* minloc, vector<int>* maxloc,const Mat& mask=Mat());
333+
voidreduceMinMax(const Mat& src, Mat& dst, cv::ReduceMinMaxMode mode,int axis);
333334
doublenorm(InputArray src,int normType, InputArray mask=noArray());
334335
doublenorm(InputArray src1, InputArray src2,int normType, InputArray mask=noArray());
335336
Scalarmean(const Mat& src,const Mat& mask=Mat());

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp