Skip to content

Commit eb04b2b

Browse files
Added N-dim submat selection with vectors
Currently, to select a submatrix of a N-dimensional matrix, it requires two lines of code while only one line of code is required if using a 2D array. I added functionality to be able to select an N-dim submatrix using a vector list instead of a Range pointer. This allows initializer lists to be used for a one-line selection.
1 parent c038d1b commit eb04b2b

File tree

5 files changed

+118
-0
lines changed

5 files changed

+118
-0
lines changed

modules/core/include/opencv2/core/mat.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,16 @@ class CV_EXPORTS Mat
925925
*/
926926
Mat(const Mat& m, const Range* ranges);
927927

928+
/** @overload
929+
@param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied
930+
by these constructors. Instead, the header pointing to m data or its sub-array is constructed and
931+
associated with it. The reference counter, if any, is incremented. So, when you modify the matrix
932+
formed using such a constructor, you also modify the corresponding elements of m . If you want to
933+
have an independent copy of the sub-array, use Mat::clone() .
934+
@param ranges Array of selected ranges of m along each dimensionality.
935+
*/
936+
Mat(const Mat& m, const std::vector<Range>& ranges);
937+
928938
/** @overload
929939
@param vec STL vector whose elements form the matrix. The matrix has a single column and the number
930940
of rows equal to the number of vector elements. Type of the matrix matches the type of vector
@@ -1516,6 +1526,11 @@ class CV_EXPORTS Mat
15161526
*/
15171527
Mat operator()( const Range* ranges ) const;
15181528

1529+
/** @overload
1530+
@param ranges Array of selected ranges along each array dimension.
1531+
*/
1532+
Mat operator()(const std::vector<Range>& ranges) const;
1533+
15191534
// //! converts header to CvMat; no data is copied
15201535
// operator CvMat() const;
15211536
// //! converts header to CvMatND; no data is copied
@@ -2054,6 +2069,8 @@ template<typename _Tp> class Mat_ : public Mat
20542069
Mat_(const Mat_& m, const Rect& roi);
20552070
//! selects a submatrix, n-dim version
20562071
Mat_(const Mat_& m, const Range* ranges);
2072+
//! selects a submatrix, n-dim version
2073+
Mat_(const Mat_& m, const std::vector<Range>& ranges);
20572074
//! from a matrix expression
20582075
explicit Mat_(const MatExpr& e);
20592076
//! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column
@@ -2123,6 +2140,7 @@ template<typename _Tp> class Mat_ : public Mat
21232140
Mat_ operator()( const Range& rowRange, const Range& colRange ) const;
21242141
Mat_ operator()( const Rect& roi ) const;
21252142
Mat_ operator()( const Range* ranges ) const;
2143+
Mat_ operator()(const std::vector<Range>& ranges) const;
21262144

21272145
//! more convenient forms of row and element access operators
21282146
_Tp* operator [](int y);
@@ -2227,6 +2245,7 @@ class CV_EXPORTS UMat
22272245
UMat(const UMat& m, const Range& rowRange, const Range& colRange=Range::all());
22282246
UMat(const UMat& m, const Rect& roi);
22292247
UMat(const UMat& m, const Range* ranges);
2248+
UMat(const UMat& m, const std::vector<Range>& ranges);
22302249
//! builds matrix from std::vector with or without copying the data
22312250
template<typename _Tp> explicit UMat(const std::vector<_Tp>& vec, bool copyData=false);
22322251
//! builds matrix from cv::Vec; the data is copied by default
@@ -2333,6 +2352,7 @@ class CV_EXPORTS UMat
23332352
UMat operator()( Range rowRange, Range colRange ) const;
23342353
UMat operator()( const Rect& roi ) const;
23352354
UMat operator()( const Range* ranges ) const;
2355+
UMat operator()(const std::vector<Range>& ranges) const;
23362356

23372357
//! returns true iff the matrix data is continuous
23382358
// (i.e. when there are no gaps between successive rows).

modules/core/include/opencv2/core/mat.inl.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,12 @@ Mat Mat::operator()(const Range* ranges) const
736736
return Mat(*this, ranges);
737737
}
738738

739+
inline
740+
Mat Mat::operator()(const std::vector<Range>& ranges) const
741+
{
742+
return Mat(*this, ranges);
743+
}
744+
739745
inline
740746
bool Mat::isContinuous() const
741747
{
@@ -1383,6 +1389,11 @@ Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges)
13831389
: Mat(m, ranges)
13841390
{}
13851391

1392+
template<typename _Tp> inline
1393+
Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const std::vector<Range>& ranges)
1394+
: Mat(m, ranges)
1395+
{}
1396+
13861397
template<typename _Tp> inline
13871398
Mat_<_Tp>::Mat_(const Mat& m)
13881399
: Mat()
@@ -1614,6 +1625,12 @@ Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const
16141625
return Mat_<_Tp>(*this, ranges);
16151626
}
16161627

1628+
template<typename _Tp> inline
1629+
Mat_<_Tp> Mat_<_Tp>::operator()(const std::vector<Range>& ranges) const
1630+
{
1631+
return Mat_<_Tp>(*this, ranges);
1632+
}
1633+
16171634
template<typename _Tp> inline
16181635
_Tp* Mat_<_Tp>::operator [](int y)
16191636
{
@@ -3540,6 +3557,12 @@ UMat UMat::operator()(const Range* ranges) const
35403557
return UMat(*this, ranges);
35413558
}
35423559

3560+
inline
3561+
UMat UMat::operator()(const std::vector<Range>& ranges) const
3562+
{
3563+
return UMat(*this, ranges);
3564+
}
3565+
35433566
inline
35443567
bool UMat::isContinuous() const
35453568
{

modules/core/src/matrix.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,31 @@ Mat::Mat(const Mat& m, const Range* ranges)
583583
updateContinuityFlag(*this);
584584
}
585585

586+
Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
587+
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
588+
datalimit(0), allocator(0), u(0), size(&rows)
589+
{
590+
int d = m.dims;
591+
592+
CV_Assert((int)ranges.size() == d);
593+
for (int i = 0; i < d; i++)
594+
{
595+
Range r = ranges[i];
596+
CV_Assert(r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]));
597+
}
598+
*this = m;
599+
for (int i = 0; i < d; i++)
600+
{
601+
Range r = ranges[i];
602+
if (r != Range::all() && r != Range(0, size.p[i]))
603+
{
604+
size.p[i] = r.end - r.start;
605+
data += r.start*step.p[i];
606+
flags |= SUBMATRIX_FLAG;
607+
}
608+
}
609+
updateContinuityFlag(*this);
610+
}
586611

587612
static Mat cvMatNDToMat(const CvMatND* m, bool copyData)
588613
{

modules/core/src/umatrix.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,31 @@ UMat::UMat(const UMat& m, const Range* ranges)
512512
updateContinuityFlag(*this);
513513
}
514514

515+
UMat::UMat(const UMat& m, const std::vector<Range>& ranges)
516+
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
517+
{
518+
int i, d = m.dims;
519+
520+
CV_Assert((int)ranges.size() == d);
521+
for (i = 0; i < d; i++)
522+
{
523+
Range r = ranges[i];
524+
CV_Assert(r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]));
525+
}
526+
*this = m;
527+
for (i = 0; i < d; i++)
528+
{
529+
Range r = ranges[i];
530+
if (r != Range::all() && r != Range(0, size.p[i]))
531+
{
532+
size.p[i] = r.end - r.start;
533+
offset += r.start*step.p[i];
534+
flags |= SUBMATRIX_FLAG;
535+
}
536+
}
537+
updateContinuityFlag(*this);
538+
}
539+
515540
UMat UMat::diag(int d) const
516541
{
517542
CV_Assert( dims <= 2 );

modules/core/test/test_mat.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,3 +1546,28 @@ TEST(Mat, regression_5917_clone_empty)
15461546

15471547
ASSERT_NO_THROW(cloned = source.clone());
15481548
}
1549+
1550+
TEST(Mat, regression_7873_mat_vector_initialize)
1551+
{
1552+
std::vector<int> dims;
1553+
dims.push_back(12);
1554+
dims.push_back(3);
1555+
dims.push_back(2);
1556+
Mat multi_mat(dims, CV_32FC1, cv::Scalar(0));
1557+
1558+
ASSERT_EQ(3, multi_mat.dims);
1559+
ASSERT_EQ(12, multi_mat.size[0]);
1560+
ASSERT_EQ(3, multi_mat.size[1]);
1561+
ASSERT_EQ(2, multi_mat.size[2]);
1562+
1563+
std::vector<Range> ranges;
1564+
ranges.push_back(Range(1, 2));
1565+
ranges.push_back(Range::all());
1566+
ranges.push_back(Range::all());
1567+
Mat sub_mat = multi_mat(ranges);
1568+
1569+
ASSERT_EQ(3, sub_mat.dims);
1570+
ASSERT_EQ(1, sub_mat.size[0]);
1571+
ASSERT_EQ(3, sub_mat.size[1]);
1572+
ASSERT_EQ(2, sub_mat.size[2]);
1573+
}

0 commit comments

Comments
 (0)