mirror of
https://github.com/opencv/opencv.git
synced 2025-06-06 00:43:52 +08:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
commit
e0265c67c6
@ -110,6 +110,29 @@
|
||||
year = {2010},
|
||||
url = {http://ingmec.ual.es/~jlblanco/papers/jlblanco2010geometry3D_techrep.pdf}
|
||||
}
|
||||
@inproceedings{Bolelli2017,
|
||||
title = {{Two More Strategies to Speed Up Connected Components Labeling Algorithms}},
|
||||
author = {Bolelli, Federico and Cancilla, Michele and Grana, Costantino},
|
||||
year = 2017,
|
||||
booktitle = {Image Analysis and Processing - ICIAP 2017},
|
||||
publisher = {Springer},
|
||||
volume = 10485,
|
||||
pages = {48--58},
|
||||
doi = {10.1007/978-3-319-68548-9_5},
|
||||
isbn = {978-3-319-68547-2}
|
||||
}
|
||||
@article{Bolelli2019,
|
||||
title = {{Spaghetti Labeling: Directed Acyclic Graphs for Block-Based Connected Components Labeling}},
|
||||
author = {Bolelli, Federico and Allegretti, Stefano and Baraldi, Lorenzo and Grana, Costantino},
|
||||
year = 2019,
|
||||
journal = {IEEE Transactions on Image Processing},
|
||||
publisher = {IEEE},
|
||||
volume = 29,
|
||||
number = 1,
|
||||
pages = {1999--2012},
|
||||
doi = {10.1109/TIP.2019.2946979},
|
||||
issn = {1057-7149}
|
||||
}
|
||||
@article{Borgefors86,
|
||||
author = {Borgefors, Gunilla},
|
||||
title = {Distance transformations in digital images},
|
||||
@ -420,6 +443,16 @@
|
||||
volume = {51},
|
||||
pages = {378-384}
|
||||
}
|
||||
@article{Grana2010,
|
||||
title = {{Optimized Block-Based Connected Components Labeling With Decision Trees}},
|
||||
author = {Grana, Costantino and Borghesani, Daniele and Cucchiara, Rita},
|
||||
year = 2010,
|
||||
journal = {IEEE Transactions on Image Processing},
|
||||
volume = 19,
|
||||
number = 6,
|
||||
pages = {1596--1609},
|
||||
doi = {10.1109/TIP.2010.2044963}
|
||||
}
|
||||
@article{taubin1991,
|
||||
abstract = {The author addresses the problem of parametric representation and estimation of complex planar curves in 2-D surfaces in 3-D, and nonplanar space curves in 3-D. Curves and surfaces can be defined either parametrically or implicitly, with the latter representation used here. A planar curve is the set of zeros of a smooth function of two variables <e1>x</e1>-<e1>y</e1>, a surface is the set of zeros of a smooth function of three variables <e1>x</e1>-<e1>y</e1>-<e1>z</e1>, and a space curve is the intersection of two surfaces, which are the set of zeros of two linearly independent smooth functions of three variables <e1>x</e1>-<e1>y</e1>-<e1>z</e1> For example, the surface of a complex object in 3-D can be represented as a subset of a single implicit surface, with similar results for planar and space curves. It is shown how this unified representation can be used for object recognition, object position estimation, and segmentation of objects into meaningful subobjects, that is, the detection of `interest regions' that are more complex than high curvature regions and, hence, more useful as features for object recognition},
|
||||
author = {Taubin, Gabriel},
|
||||
|
@ -390,7 +390,9 @@ typedef union Cv64suf
|
||||
}
|
||||
Cv64suf;
|
||||
|
||||
#ifndef OPENCV_ABI_COMPATIBILITY
|
||||
#define OPENCV_ABI_COMPATIBILITY 400
|
||||
#endif
|
||||
|
||||
#ifdef __OPENCV_BUILD
|
||||
# define DISABLE_OPENCV_3_COMPATIBILITY
|
||||
|
@ -170,7 +170,9 @@ public:
|
||||
STD_VECTOR = 3 << KIND_SHIFT,
|
||||
STD_VECTOR_VECTOR = 4 << KIND_SHIFT,
|
||||
STD_VECTOR_MAT = 5 << KIND_SHIFT,
|
||||
EXPR = 6 << KIND_SHIFT, //!< removed
|
||||
#if OPENCV_ABI_COMPATIBILITY < 500
|
||||
EXPR = 6 << KIND_SHIFT, //!< removed: https://github.com/opencv/opencv/pull/17046
|
||||
#endif
|
||||
OPENGL_BUFFER = 7 << KIND_SHIFT,
|
||||
CUDA_HOST_MEM = 8 << KIND_SHIFT,
|
||||
CUDA_GPU_MAT = 9 << KIND_SHIFT,
|
||||
@ -178,7 +180,9 @@ public:
|
||||
STD_VECTOR_UMAT =11 << KIND_SHIFT,
|
||||
STD_BOOL_VECTOR =12 << KIND_SHIFT,
|
||||
STD_VECTOR_CUDA_GPU_MAT = 13 << KIND_SHIFT,
|
||||
STD_ARRAY =14 << KIND_SHIFT,
|
||||
#if OPENCV_ABI_COMPATIBILITY < 500
|
||||
STD_ARRAY =14 << KIND_SHIFT, //!< removed: https://github.com/opencv/opencv/issues/18897
|
||||
#endif
|
||||
STD_ARRAY_MAT =15 << KIND_SHIFT
|
||||
};
|
||||
|
||||
|
@ -111,7 +111,7 @@ _InputArray::_InputArray(const std::vector<_Tp>& vec)
|
||||
|
||||
template<typename _Tp, std::size_t _Nm> inline
|
||||
_InputArray::_InputArray(const std::array<_Tp, _Nm>& arr)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_READ, arr.data(), Size(1, _Nm)); }
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, arr.data(), Size(1, _Nm)); }
|
||||
|
||||
template<std::size_t _Nm> inline
|
||||
_InputArray::_InputArray(const std::array<Mat, _Nm>& arr)
|
||||
@ -169,7 +169,7 @@ template<typename _Tp, std::size_t _Nm> inline
|
||||
_InputArray _InputArray::rawIn(const std::array<_Tp, _Nm>& arr)
|
||||
{
|
||||
_InputArray v;
|
||||
v.flags = FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_READ;
|
||||
v.flags = FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ;
|
||||
v.obj = (void*)arr.data();
|
||||
v.sz = Size(1, _Nm);
|
||||
return v;
|
||||
@ -191,7 +191,7 @@ inline bool _InputArray::isUMatVector() const { return kind() == _InputArray::S
|
||||
inline bool _InputArray::isMatx() const { return kind() == _InputArray::MATX; }
|
||||
inline bool _InputArray::isVector() const { return kind() == _InputArray::STD_VECTOR ||
|
||||
kind() == _InputArray::STD_BOOL_VECTOR ||
|
||||
kind() == _InputArray::STD_ARRAY; }
|
||||
(kind() == _InputArray::MATX && (sz.width <= 1 || sz.height <= 1)); }
|
||||
inline bool _InputArray::isGpuMat() const { return kind() == _InputArray::CUDA_GPU_MAT; }
|
||||
inline bool _InputArray::isGpuMatVector() const { return kind() == _InputArray::STD_VECTOR_CUDA_GPU_MAT; }
|
||||
|
||||
@ -210,7 +210,7 @@ _OutputArray::_OutputArray(std::vector<_Tp>& vec)
|
||||
|
||||
template<typename _Tp, std::size_t _Nm> inline
|
||||
_OutputArray::_OutputArray(std::array<_Tp, _Nm>& arr)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
|
||||
|
||||
template<std::size_t _Nm> inline
|
||||
_OutputArray::_OutputArray(std::array<Mat, _Nm>& arr)
|
||||
@ -242,7 +242,7 @@ _OutputArray::_OutputArray(const std::vector<_Tp>& vec)
|
||||
|
||||
template<typename _Tp, std::size_t _Nm> inline
|
||||
_OutputArray::_OutputArray(const std::array<_Tp, _Nm>& arr)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
|
||||
|
||||
template<std::size_t _Nm> inline
|
||||
_OutputArray::_OutputArray(const std::array<Mat, _Nm>& arr)
|
||||
@ -315,7 +315,7 @@ template<typename _Tp, std::size_t _Nm> inline
|
||||
_OutputArray _OutputArray::rawOut(std::array<_Tp, _Nm>& arr)
|
||||
{
|
||||
_OutputArray v;
|
||||
v.flags = FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_WRITE;
|
||||
v.flags = FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE;
|
||||
v.obj = (void*)arr.data();
|
||||
v.sz = Size(1, _Nm);
|
||||
return v;
|
||||
@ -336,7 +336,7 @@ _InputOutputArray::_InputOutputArray(std::vector<_Tp>& vec)
|
||||
|
||||
template<typename _Tp, std::size_t _Nm> inline
|
||||
_InputOutputArray::_InputOutputArray(std::array<_Tp, _Nm>& arr)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); }
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); }
|
||||
|
||||
template<std::size_t _Nm> inline
|
||||
_InputOutputArray::_InputOutputArray(std::array<Mat, _Nm>& arr)
|
||||
@ -368,7 +368,7 @@ _InputOutputArray::_InputOutputArray(const std::vector<_Tp>& vec)
|
||||
|
||||
template<typename _Tp, std::size_t _Nm> inline
|
||||
_InputOutputArray::_InputOutputArray(const std::array<_Tp, _Nm>& arr)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); }
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); }
|
||||
|
||||
template<std::size_t _Nm> inline
|
||||
_InputOutputArray::_InputOutputArray(const std::array<Mat, _Nm>& arr)
|
||||
@ -443,7 +443,7 @@ template<typename _Tp, std::size_t _Nm> inline
|
||||
_InputOutputArray _InputOutputArray::rawInOut(std::array<_Tp, _Nm>& arr)
|
||||
{
|
||||
_InputOutputArray v;
|
||||
v.flags = FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_RW;
|
||||
v.flags = FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW;
|
||||
v.obj = (void*)arr.data();
|
||||
v.sz = Size(1, _Nm);
|
||||
return v;
|
||||
|
@ -455,6 +455,27 @@ public class MatTest extends OpenCVTestCase {
|
||||
bytesNum = sm.get(1, 1, buff11);
|
||||
assertEquals(4, bytesNum);
|
||||
assertTrue(Arrays.equals(new short[] {340, 341, 0, 0}, buff11));
|
||||
|
||||
Mat m2 = new Mat(new int[]{ 5, 6, 8 }, CvType.CV_16S);
|
||||
short[] data = new short[(int)m2.total()];
|
||||
for (int i = 0; i < data.length; i++ ) {
|
||||
data[i] = (short)i;
|
||||
}
|
||||
m2.put(new int[] {0, 0, 0}, data);
|
||||
Mat matNonContinuous = m2.submat(new Range[]{new Range(1,4), new Range(2,5), new Range(3,6)});
|
||||
Mat matContinuous = matNonContinuous.clone();
|
||||
short[] outNonContinuous = new short[(int)matNonContinuous.total()];
|
||||
matNonContinuous.get(new int[] { 0, 0, 0 }, outNonContinuous);
|
||||
short[] outContinuous = new short[(int)matNonContinuous.total()];
|
||||
matContinuous.get(new int[] { 0, 0, 0 }, outContinuous);
|
||||
assertArrayEquals(outNonContinuous, outContinuous);
|
||||
Mat subMat2 = m2.submat(new Range[]{new Range(1,4), new Range(1,5), new Range(0,8)});
|
||||
Mat subMatClone2 = subMat2.clone();
|
||||
short[] outNonContinuous2 = new short[(int)subMat2.total()];
|
||||
subMat2.get(new int[] { 0, 1, 1 }, outNonContinuous2);
|
||||
short[] outContinuous2 = new short[(int)subMat2.total()];
|
||||
subMatClone2.get(new int[] { 0, 1, 1 }, outContinuous2);
|
||||
assertArrayEquals(outNonContinuous2, outContinuous2);
|
||||
}
|
||||
|
||||
public void testGetNativeObjAddr() {
|
||||
|
@ -1325,13 +1325,12 @@ void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
|
||||
memcpy( dstInner + srcroi.width, constBuf, right );
|
||||
}
|
||||
|
||||
dst += dststep*top;
|
||||
|
||||
for( i = 0; i < top; i++ )
|
||||
memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
|
||||
memcpy(dst + i * dststep, constBuf, dstroi.width);
|
||||
|
||||
dst += (top + srcroi.height) * dststep;
|
||||
for( i = 0; i < bottom; i++ )
|
||||
memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
|
||||
memcpy(dst + i * dststep, constBuf, dstroi.width);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ Mat _InputArray::getMat_(int i) const
|
||||
return m->getMat(accessFlags).row(i);
|
||||
}
|
||||
|
||||
if( k == MATX || k == STD_ARRAY )
|
||||
if (k == MATX)
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return Mat(sz, flags, obj);
|
||||
@ -172,7 +172,7 @@ void _InputArray::getMatVector(std::vector<Mat>& mv) const
|
||||
return;
|
||||
}
|
||||
|
||||
if( k == MATX || k == STD_ARRAY )
|
||||
if (k == MATX)
|
||||
{
|
||||
size_t n = sz.height, esz = CV_ELEM_SIZE(flags);
|
||||
mv.resize(n);
|
||||
@ -361,7 +361,10 @@ ogl::Buffer _InputArray::getOGlBuffer() const
|
||||
_InputArray::KindFlag _InputArray::kind() const
|
||||
{
|
||||
KindFlag k = flags & KIND_MASK;
|
||||
#if CV_VERSION_MAJOR < 5
|
||||
CV_DbgAssert(k != EXPR);
|
||||
CV_DbgAssert(k != STD_ARRAY);
|
||||
#endif
|
||||
return k;
|
||||
}
|
||||
|
||||
@ -391,7 +394,7 @@ Size _InputArray::size(int i) const
|
||||
return ((const UMat*)obj)->size();
|
||||
}
|
||||
|
||||
if( k == MATX || k == STD_ARRAY )
|
||||
if (k == MATX)
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return sz;
|
||||
@ -611,7 +614,7 @@ int _InputArray::dims(int i) const
|
||||
return ((const UMat*)obj)->dims;
|
||||
}
|
||||
|
||||
if( k == MATX || k == STD_ARRAY )
|
||||
if (k == MATX)
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return 2;
|
||||
@ -745,7 +748,7 @@ int _InputArray::type(int i) const
|
||||
if( k == UMAT )
|
||||
return ((const UMat*)obj)->type();
|
||||
|
||||
if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
|
||||
if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
|
||||
return CV_MAT_TYPE(flags);
|
||||
|
||||
if( k == NONE )
|
||||
@ -831,7 +834,7 @@ bool _InputArray::empty() const
|
||||
if( k == UMAT )
|
||||
return ((const UMat*)obj)->empty();
|
||||
|
||||
if( k == MATX || k == STD_ARRAY )
|
||||
if (k == MATX)
|
||||
return false;
|
||||
|
||||
if( k == STD_VECTOR )
|
||||
@ -900,7 +903,7 @@ bool _InputArray::isContinuous(int i) const
|
||||
if( k == UMAT )
|
||||
return i < 0 ? ((const UMat*)obj)->isContinuous() : true;
|
||||
|
||||
if( k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
|
||||
if( k == MATX || k == STD_VECTOR ||
|
||||
k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
|
||||
return true;
|
||||
|
||||
@ -941,7 +944,7 @@ bool _InputArray::isSubmatrix(int i) const
|
||||
if( k == UMAT )
|
||||
return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false;
|
||||
|
||||
if( k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
|
||||
if( k == MATX || k == STD_VECTOR ||
|
||||
k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
|
||||
return false;
|
||||
|
||||
@ -986,7 +989,7 @@ size_t _InputArray::offset(int i) const
|
||||
return ((const UMat*)obj)->offset;
|
||||
}
|
||||
|
||||
if( k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
|
||||
if( k == MATX || k == STD_VECTOR ||
|
||||
k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
|
||||
return 0;
|
||||
|
||||
@ -1045,7 +1048,7 @@ size_t _InputArray::step(int i) const
|
||||
return ((const UMat*)obj)->step;
|
||||
}
|
||||
|
||||
if( k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
|
||||
if( k == MATX || k == STD_VECTOR ||
|
||||
k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
|
||||
return 0;
|
||||
|
||||
@ -1091,7 +1094,7 @@ void _InputArray::copyTo(const _OutputArray& arr) const
|
||||
|
||||
if( k == NONE )
|
||||
arr.release();
|
||||
else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_BOOL_VECTOR )
|
||||
else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR )
|
||||
{
|
||||
Mat m = getMat();
|
||||
m.copyTo(arr);
|
||||
@ -1112,7 +1115,7 @@ void _InputArray::copyTo(const _OutputArray& arr, const _InputArray & mask) cons
|
||||
|
||||
if( k == NONE )
|
||||
arr.release();
|
||||
else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_BOOL_VECTOR )
|
||||
else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR )
|
||||
{
|
||||
Mat m = getMat();
|
||||
m.copyTo(arr, mask);
|
||||
@ -1300,16 +1303,27 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
|
||||
CV_Assert( i < 0 );
|
||||
int type0 = CV_MAT_TYPE(flags);
|
||||
CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
|
||||
CV_Assert( d == 2 && ((sizes[0] == sz.height && sizes[1] == sz.width) ||
|
||||
(allowTransposed && sizes[0] == sz.width && sizes[1] == sz.height)));
|
||||
return;
|
||||
}
|
||||
|
||||
if( k == STD_ARRAY )
|
||||
{
|
||||
int type0 = CV_MAT_TYPE(flags);
|
||||
CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
|
||||
CV_Assert( d == 2 && sz.area() == sizes[0]*sizes[1]);
|
||||
CV_CheckLE(d, 2, "");
|
||||
Size requested_size(d == 2 ? sizes[1] : 1, d >= 1 ? sizes[0] : 1);
|
||||
if (sz.width == 1 || sz.height == 1)
|
||||
{
|
||||
// NB: 1D arrays assume allowTransposed=true (see #4159)
|
||||
int total_1d = std::max(sz.width, sz.height);
|
||||
CV_Check(requested_size, std::max(requested_size.width, requested_size.height) == total_1d, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!allowTransposed)
|
||||
{
|
||||
CV_CheckEQ(requested_size, sz, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Check(requested_size,
|
||||
(requested_size == sz || (requested_size.height == sz.width && requested_size.width == sz.height)),
|
||||
"");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1771,7 +1785,7 @@ void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
|
||||
|
||||
if( k == NONE )
|
||||
;
|
||||
else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_ARRAY )
|
||||
else if (k == MAT || k == MATX || k == STD_VECTOR)
|
||||
{
|
||||
Mat m = getMat();
|
||||
m.setTo(arr, mask);
|
||||
|
@ -1988,7 +1988,6 @@ class TestInputArrayRangeChecking {
|
||||
C(EXPR);
|
||||
C(MATX);
|
||||
C(STD_VECTOR);
|
||||
C(STD_ARRAY);
|
||||
C(NONE);
|
||||
C(STD_VECTOR_VECTOR);
|
||||
C(STD_BOOL_VECTOR);
|
||||
|
@ -617,8 +617,13 @@ public:
|
||||
}
|
||||
}
|
||||
// Keep outputs k results per image.
|
||||
std::sort(scoreIndexPairs.begin(), scoreIndexPairs.end(),
|
||||
util::SortScorePairDescend<std::pair<int, int> >);
|
||||
if ((_keepTopK * 8) > scoreIndexPairs.size()) {
|
||||
std::sort(scoreIndexPairs.begin(), scoreIndexPairs.end(),
|
||||
util::SortScorePairDescend<std::pair<int, int> >);
|
||||
} else {
|
||||
std::partial_sort(scoreIndexPairs.begin(), scoreIndexPairs.begin() + _keepTopK, scoreIndexPairs.end(),
|
||||
util::SortScorePairDescend<std::pair<int, int> >);
|
||||
}
|
||||
scoreIndexPairs.resize(_keepTopK);
|
||||
|
||||
std::map<int, std::vector<int> > newIndices;
|
||||
@ -853,16 +858,16 @@ public:
|
||||
for (int i = 0; i < num; ++i, locData += numPredsPerClass * numLocClasses * 4)
|
||||
{
|
||||
LabelBBox& labelBBox = locPreds[i];
|
||||
int start = shareLocation ? -1 : 0;
|
||||
for (int c = 0; c < numLocClasses; ++c) {
|
||||
labelBBox[start++].resize(numPredsPerClass);
|
||||
}
|
||||
for (int p = 0; p < numPredsPerClass; ++p)
|
||||
{
|
||||
int startIdx = p * numLocClasses * 4;
|
||||
for (int c = 0; c < numLocClasses; ++c)
|
||||
{
|
||||
int label = shareLocation ? -1 : c;
|
||||
if (labelBBox.find(label) == labelBBox.end())
|
||||
{
|
||||
labelBBox[label].resize(numPredsPerClass);
|
||||
}
|
||||
util::NormalizedBBox& bbox = labelBBox[label][p];
|
||||
if (locPredTransposed)
|
||||
{
|
||||
|
@ -292,7 +292,8 @@ public:
|
||||
|
||||
CV_Assert(imInfo.total() >= 2);
|
||||
// We've chosen the smallest data type because we need just a shape from it.
|
||||
fakeImageBlob.create(shape(1, 1, imInfo.at<float>(0), imInfo.at<float>(1)), CV_8UC1);
|
||||
// We don't allocate memory but just need the shape is correct.
|
||||
Mat fakeImageBlob(shape(1, 1, imInfo.at<float>(0), imInfo.at<float>(1)), CV_8UC1, NULL);
|
||||
|
||||
// Generate prior boxes.
|
||||
std::vector<Mat> layerInputs(2), layerOutputs(1, priorBoxes);
|
||||
@ -433,7 +434,6 @@ private:
|
||||
Ptr<PermuteLayer> deltasPermute;
|
||||
Ptr<PermuteLayer> scoresPermute;
|
||||
uint32_t keepTopBeforeNMS, keepTopAfterNMS, featStride, baseSize;
|
||||
Mat fakeImageBlob;
|
||||
float nmsThreshold;
|
||||
DictValue ratios, scales;
|
||||
#ifdef HAVE_OPENCL
|
||||
|
@ -405,9 +405,13 @@ enum ConnectedComponentsTypes {
|
||||
|
||||
//! connected components algorithm
|
||||
enum ConnectedComponentsAlgorithmsTypes {
|
||||
CCL_WU = 0, //!< SAUF @cite Wu2009 algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity
|
||||
CCL_DEFAULT = -1, //!< BBDT algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity
|
||||
CCL_GRANA = 1 //!< BBDT algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity
|
||||
CCL_DEFAULT = -1, //!< BBDT @cite Grana2010 algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity. The parallel implementation described in @cite Bolelli2017 is available for both BBDT and SAUF.
|
||||
CCL_WU = 0, //!< SAUF @cite Wu2009 algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity. The parallel implementation described in @cite Bolelli2017 is available for SAUF.
|
||||
CCL_GRANA = 1, //!< BBDT @cite Grana2010 algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity. The parallel implementation described in @cite Bolelli2017 is available for both BBDT and SAUF.
|
||||
CCL_BOLELLI = 2, //!< Spaghetti @cite Bolelli2019 algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity.
|
||||
CCL_SAUF = 3, //!< Same as CCL_WU. It is preferable to use the flag with the name of the algorithm (CCL_SAUF) rather than the one with the name of the first author (CCL_WU).
|
||||
CCL_BBDT = 4, //!< Same as CCL_GRANA. It is preferable to use the flag with the name of the algorithm (CCL_BBDT) rather than the one with the name of the first author (CCL_GRANA).
|
||||
CCL_SPAGHETTI = 5, //!< Same as CCL_BOLELLI. It is preferable to use the flag with the name of the algorithm (CCL_SPAGHETTI) rather than the one with the name of the first author (CCL_BOLELLI).
|
||||
};
|
||||
|
||||
//! mode of the contour retrieval algorithm
|
||||
@ -3546,7 +3550,7 @@ CV_EXPORTS_W int floodFill( InputOutputArray image, InputOutputArray mask,
|
||||
//! @param weights1 It has a type of CV_32FC1 and the same size with src1.
|
||||
//! @param weights2 It has a type of CV_32FC1 and the same size with src1.
|
||||
//! @param dst It is created if it does not have the same size and type with src1.
|
||||
CV_EXPORTS void blendLinear(InputArray src1, InputArray src2, InputArray weights1, InputArray weights2, OutputArray dst);
|
||||
CV_EXPORTS_W void blendLinear(InputArray src1, InputArray src2, InputArray weights1, InputArray weights2, OutputArray dst);
|
||||
|
||||
//! @} imgproc_misc
|
||||
|
||||
|
1746
modules/imgproc/src/ccl_bolelli_forest.inc.hpp
Normal file
1746
modules/imgproc/src/ccl_bolelli_forest.inc.hpp
Normal file
File diff suppressed because it is too large
Load Diff
218
modules/imgproc/src/ccl_bolelli_forest_firstline.inc.hpp
Normal file
218
modules/imgproc/src/ccl_bolelli_forest_firstline.inc.hpp
Normal file
@ -0,0 +1,218 @@
|
||||
// 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.
|
||||
//
|
||||
// 2021 Federico Bolelli <federico.bolelli@unimore.it>
|
||||
// 2021 Stefano Allegretti <stefano.allegretti@unimore.it>
|
||||
// 2021 Costantino Grana <costantino.grana@unimore.it>
|
||||
//
|
||||
// This file has been automatically generated using GRAPHGEN (https://github.com/prittt/GRAPHGEN)
|
||||
// and taken from the YACCLAB repository (https://github.com/prittt/YACCLAB).
|
||||
fl_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto fl_break_0_0; } else { goto fl_break_1_0; } }
|
||||
if (CONDITION_O) {
|
||||
NODE_253:
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
goto fl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto fl_tree_2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S){
|
||||
goto NODE_253;
|
||||
}
|
||||
else {
|
||||
NODE_255:
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
goto fl_tree_1;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_T) {
|
||||
ACTION_2
|
||||
goto fl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
goto fl_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fl_tree_1: if ((c+=2) >= w - 2) { if (c > w - 2) { goto fl_break_0_1; } else { goto fl_break_1_1; } }
|
||||
if (CONDITION_O) {
|
||||
NODE_257:
|
||||
if (CONDITION_P) {
|
||||
ACTION_6
|
||||
goto fl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto fl_tree_2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S){
|
||||
goto NODE_257;
|
||||
}
|
||||
else{
|
||||
goto NODE_255;
|
||||
}
|
||||
}
|
||||
fl_tree_2: if ((c+=2) >= w - 2) { if (c > w - 2) { goto fl_break_0_2; } else { goto fl_break_1_2; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_R){
|
||||
goto NODE_257;
|
||||
}
|
||||
else{
|
||||
goto NODE_253;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S) {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_R) {
|
||||
ACTION_6
|
||||
goto fl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto fl_tree_1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_R) {
|
||||
ACTION_6
|
||||
goto fl_tree_2;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto fl_tree_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_255;
|
||||
}
|
||||
}
|
||||
fl_break_0_0:
|
||||
if (CONDITION_O) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto end_fl;
|
||||
fl_break_0_1:
|
||||
if (CONDITION_O) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto end_fl;
|
||||
fl_break_0_2:
|
||||
if (CONDITION_O) {
|
||||
NODE_266:
|
||||
if (CONDITION_R) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S){
|
||||
goto NODE_266;
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto end_fl;
|
||||
fl_break_1_0:
|
||||
if (CONDITION_O) {
|
||||
NODE_268:
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S){
|
||||
goto NODE_268;
|
||||
}
|
||||
else {
|
||||
NODE_270:
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
if (CONDITION_T) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
goto end_fl;
|
||||
fl_break_1_1:
|
||||
if (CONDITION_O) {
|
||||
NODE_272:
|
||||
if (CONDITION_P) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S){
|
||||
goto NODE_272;
|
||||
}
|
||||
else{
|
||||
goto NODE_270;
|
||||
}
|
||||
}
|
||||
goto end_fl;
|
||||
fl_break_1_2:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_R){
|
||||
goto NODE_272;
|
||||
}
|
||||
else{
|
||||
goto NODE_268;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_S) {
|
||||
if (CONDITION_P){
|
||||
goto NODE_266;
|
||||
}
|
||||
else{
|
||||
goto NODE_266;
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_270;
|
||||
}
|
||||
}
|
||||
goto end_fl;
|
||||
end_fl:;
|
731
modules/imgproc/src/ccl_bolelli_forest_lastline.inc.hpp
Normal file
731
modules/imgproc/src/ccl_bolelli_forest_lastline.inc.hpp
Normal file
@ -0,0 +1,731 @@
|
||||
// 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.
|
||||
//
|
||||
// 2021 Federico Bolelli <federico.bolelli@unimore.it>
|
||||
// 2021 Stefano Allegretti <stefano.allegretti@unimore.it>
|
||||
// 2021 Costantino Grana <costantino.grana@unimore.it>
|
||||
//
|
||||
// This file has been automatically generated using GRAPHGEN (https://github.com/prittt/GRAPHGEN)
|
||||
// and taken from the YACCLAB repository (https://github.com/prittt/YACCLAB).
|
||||
ll_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_0; } else { goto ll_break_1_0; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
NODE_277:
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_I) {
|
||||
NODE_279:
|
||||
if (CONDITION_D) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_10
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_3;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto ll_tree_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_0;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE_282:
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
goto ll_tree_5;
|
||||
}
|
||||
else{
|
||||
goto NODE_277;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
goto ll_tree_1;
|
||||
}
|
||||
}
|
||||
ll_tree_1: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_1; } else { goto ll_break_1_1; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_H) {
|
||||
NODE_287:
|
||||
if (CONDITION_C) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
ACTION_7
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_I){
|
||||
goto NODE_279;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_H) {
|
||||
NODE_292:
|
||||
if (CONDITION_D) {
|
||||
if (CONDITION_C) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_8
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_8
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_3;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_H) {
|
||||
ACTION_3
|
||||
goto ll_tree_2;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto ll_tree_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_0;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_H) {
|
||||
ACTION_3
|
||||
goto ll_tree_0;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_282;
|
||||
}
|
||||
ll_tree_2: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_2; } else { goto ll_break_1_2; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_11
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_7;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE_301:
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
goto ll_tree_5;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_K) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto ll_tree_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
goto ll_tree_1;
|
||||
}
|
||||
}
|
||||
ll_tree_3: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_2; } else { goto ll_break_1_3; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_C) {
|
||||
NODE_306:
|
||||
if (CONDITION_B) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
ACTION_7
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_D) {
|
||||
if (CONDITION_C) {
|
||||
NODE_311:
|
||||
if (CONDITION_B) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_7;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_301;
|
||||
}
|
||||
ll_tree_4: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_2; } else { goto ll_break_1_4; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_D) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_7;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
goto ll_tree_5;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_K){
|
||||
goto NODE_279;
|
||||
}
|
||||
else {
|
||||
ACTION_4
|
||||
goto ll_tree_3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
goto ll_tree_1;
|
||||
}
|
||||
}
|
||||
ll_tree_5: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_2; } else { goto ll_break_1_5; } }
|
||||
if (CONDITION_O) {
|
||||
NODE_319:
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_C) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_D) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_C) {
|
||||
ACTION_5
|
||||
goto ll_tree_4;
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_7;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_282;
|
||||
}
|
||||
ll_tree_6: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_3; } else { goto ll_break_1_6; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_N){
|
||||
goto NODE_319;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_6;
|
||||
}
|
||||
else{
|
||||
goto NODE_287;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_I){
|
||||
goto NODE_279;
|
||||
}
|
||||
else{
|
||||
goto NODE_292;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_3;
|
||||
}
|
||||
else {
|
||||
ACTION_3
|
||||
goto ll_tree_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
goto ll_tree_0;
|
||||
}
|
||||
else {
|
||||
ACTION_3
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_282;
|
||||
}
|
||||
ll_tree_7: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_2; } else { goto ll_break_1_7; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_C) {
|
||||
if (CONDITION_G){
|
||||
goto NODE_306;
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
goto ll_tree_6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_K) {
|
||||
if (CONDITION_D) {
|
||||
if (CONDITION_C) {
|
||||
if (CONDITION_G){
|
||||
goto NODE_311;
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_12
|
||||
goto ll_tree_4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_7;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto ll_tree_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_301;
|
||||
}
|
||||
ll_break_0_0:
|
||||
if (CONDITION_O) {
|
||||
NODE_343:
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_0_1:
|
||||
if (CONDITION_O) {
|
||||
NODE_344:
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
if (CONDITION_H) {
|
||||
ACTION_3
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_0_2:
|
||||
if (CONDITION_O) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_0_3:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_N) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
NODE_347:
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_3
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_0:
|
||||
if (CONDITION_O) {
|
||||
NODE_348:
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
}
|
||||
else{
|
||||
goto NODE_343;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE_349:
|
||||
if (CONDITION_P){
|
||||
goto NODE_348;
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_1:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
if (CONDITION_H) {
|
||||
NODE_353:
|
||||
if (CONDITION_C) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_7
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_4
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_344;
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_349;
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_2:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_11
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE_355:
|
||||
if (CONDITION_P) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_3:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_C) {
|
||||
NODE_359:
|
||||
if (CONDITION_B) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_7
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_355;
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_4:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (CONDITION_P) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_5:
|
||||
if (CONDITION_O) {
|
||||
NODE_362:
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
if (CONDITION_C) {
|
||||
ACTION_4
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_349;
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_6:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_N){
|
||||
goto NODE_362;
|
||||
}
|
||||
else {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_I) {
|
||||
ACTION_4
|
||||
}
|
||||
else{
|
||||
goto NODE_353;
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_347;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_349;
|
||||
}
|
||||
goto ll_end;
|
||||
ll_break_1_7:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_J) {
|
||||
if (CONDITION_C) {
|
||||
if (CONDITION_G){
|
||||
goto NODE_359;
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_11
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_355;
|
||||
}
|
||||
goto ll_end;
|
||||
ll_end:;
|
95
modules/imgproc/src/ccl_bolelli_forest_singleline.inc.hpp
Normal file
95
modules/imgproc/src/ccl_bolelli_forest_singleline.inc.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
// 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.
|
||||
//
|
||||
// 2021 Federico Bolelli <federico.bolelli@unimore.it>
|
||||
// 2021 Stefano Allegretti <stefano.allegretti@unimore.it>
|
||||
// 2021 Costantino Grana <costantino.grana@unimore.it>
|
||||
//
|
||||
// This file has been automatically generated using GRAPHGEN (https://github.com/prittt/GRAPHGEN)
|
||||
// and taken from the YACCLAB repository (https://github.com/prittt/YACCLAB).
|
||||
sl_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto sl_break_0_0; } else { goto sl_break_1_0; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
goto sl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
goto sl_tree_0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE_372:
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
goto sl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
goto sl_tree_0;
|
||||
}
|
||||
}
|
||||
sl_tree_1: if ((c+=2) >= w - 2) { if (c > w - 2) { goto sl_break_0_1; } else { goto sl_break_1_1; } }
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_P) {
|
||||
ACTION_6
|
||||
goto sl_tree_1;
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
goto sl_tree_0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_372;
|
||||
}
|
||||
sl_break_0_0:
|
||||
if (CONDITION_O) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
goto end_sl;
|
||||
sl_break_0_1:
|
||||
if (CONDITION_O) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
goto end_sl;
|
||||
sl_break_1_0:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
ACTION_2
|
||||
}
|
||||
}
|
||||
else {
|
||||
NODE_375:
|
||||
if (CONDITION_P) {
|
||||
ACTION_2
|
||||
}
|
||||
else {
|
||||
ACTION_1
|
||||
}
|
||||
}
|
||||
goto end_sl;
|
||||
sl_break_1_1:
|
||||
if (CONDITION_O) {
|
||||
if (CONDITION_P) {
|
||||
ACTION_6
|
||||
}
|
||||
else {
|
||||
ACTION_6
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto NODE_375;
|
||||
}
|
||||
goto end_sl;
|
||||
end_sl:;
|
@ -38,11 +38,12 @@
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// 2011 Jason Newton <nevion@gmail.com>
|
||||
// 2016 Costantino Grama <costantino.grana@unimore.it>
|
||||
// 2016 Federico Bolelli <federico.bolelli@hotmail.com>
|
||||
// 2016, 2021 Costantino Grana <costantino.grana@unimore.it>
|
||||
// 2016, 2021 Federico Bolelli <federico.bolelli@unimore.it>
|
||||
// 2016 Lorenzo Baraldi <lorenzo.baraldi@unimore.it>
|
||||
// 2016 Roberto Vezzani <roberto.vezzani@unimore.it>
|
||||
// 2016 Michele Cancilla <cancilla.michele@gmail.com>
|
||||
// 2021 Stefano Allegretti <stefano.allegretti@unimore.it>
|
||||
//M*/
|
||||
//
|
||||
#include "precomp.hpp"
|
||||
@ -286,10 +287,366 @@ namespace cv{
|
||||
return LT((y /*+ 1*/) / 2) * LT((w + 1) / 2) + 1;
|
||||
}
|
||||
|
||||
//Implementation of Spaghetti algorithm, as described in "Spaghetti Labeling: Directed Acyclic Graphs for Block-Based
|
||||
//Connected Components Labeling" (only for 8-connectivity)
|
||||
//Federico Bolelli et. al.
|
||||
template<typename LabelT, typename PixelT, typename StatsOp = NoOp >
|
||||
struct LabelingBolelli
|
||||
{
|
||||
LabelT operator()(const cv::Mat& img, cv::Mat& imgLabels, int connectivity, StatsOp& sop)
|
||||
{
|
||||
CV_Assert(img.rows == imgLabels.rows);
|
||||
CV_Assert(img.cols == imgLabels.cols);
|
||||
CV_Assert(connectivity == 8);
|
||||
|
||||
//Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan array union find) variant
|
||||
//using decision trees
|
||||
//Kesheng Wu, et al
|
||||
const int h = img.rows;
|
||||
const int w = img.cols;
|
||||
|
||||
const int e_rows = h & -2;
|
||||
const bool o_rows = h % 2 == 1;
|
||||
const int e_cols = w & -2;
|
||||
const bool o_cols = w % 2 == 1;
|
||||
|
||||
// A quick and dirty upper bound for the maximum number of labels.
|
||||
// Following formula comes from the fact that a 2x2 block in 8-connectivity case
|
||||
// can never have more than 1 new label and 1 label for background.
|
||||
// Worst case image example pattern:
|
||||
// 1 0 1 0 1...
|
||||
// 0 0 0 0 0...
|
||||
// 1 0 1 0 1...
|
||||
// ............
|
||||
const size_t Plength = size_t(((h + 1) / 2) * size_t((w + 1) / 2)) + 1;
|
||||
|
||||
std::vector<LabelT> P_(Plength, 0);
|
||||
LabelT *P = P_.data();
|
||||
//P[0] = 0;
|
||||
LabelT lunique = 1;
|
||||
|
||||
// First scan
|
||||
|
||||
// We work with 2x2 blocks
|
||||
// +-+-+-+
|
||||
// |P|Q|R|
|
||||
// +-+-+-+
|
||||
// |S|X|
|
||||
// +-+-+
|
||||
|
||||
// The pixels are named as follows
|
||||
// +---+---+---+
|
||||
// |a b|c d|e f|
|
||||
// |g h|i j|k l|
|
||||
// +---+---+---+
|
||||
// |m n|o p|
|
||||
// |q r|s t|
|
||||
// +---+---+
|
||||
|
||||
// Pixels a, f, l, q are not needed, since we need to understand the
|
||||
// the connectivity between these blocks and those pixels only matter
|
||||
// when considering the outer connectivities
|
||||
|
||||
// A bunch of defines is used to check if the pixels are foreground
|
||||
// and to define actions to be performed on blocks
|
||||
{
|
||||
#define CONDITION_B img_row_prev_prev[c-1]>0
|
||||
#define CONDITION_C img_row_prev_prev[c]>0
|
||||
#define CONDITION_D img_row_prev_prev[c+1]>0
|
||||
#define CONDITION_E img_row_prev_prev[c+2]>0
|
||||
|
||||
#define CONDITION_G img_row_prev[c-2]>0
|
||||
#define CONDITION_H img_row_prev[c-1]>0
|
||||
#define CONDITION_I img_row_prev[c]>0
|
||||
#define CONDITION_J img_row_prev[c+1]>0
|
||||
#define CONDITION_K img_row_prev[c+2]>0
|
||||
|
||||
#define CONDITION_M img_row[c-2]>0
|
||||
#define CONDITION_N img_row[c-1]>0
|
||||
#define CONDITION_O img_row[c]>0
|
||||
#define CONDITION_P img_row[c+1]>0
|
||||
|
||||
#define CONDITION_R img_row_fol[c-1]>0
|
||||
#define CONDITION_S img_row_fol[c]>0
|
||||
#define CONDITION_T img_row_fol[c+1]>0
|
||||
|
||||
// Action 1: No action
|
||||
#define ACTION_1 img_labels_row[c] = 0;
|
||||
// Action 2: New label (the block has foreground pixels and is not connected to anything else)
|
||||
#define ACTION_2 img_labels_row[c] = lunique; \
|
||||
P[lunique] = lunique; \
|
||||
lunique = lunique + 1;
|
||||
//Action 3: Assign label of block P
|
||||
#define ACTION_3 img_labels_row[c] = img_labels_row_prev_prev[c - 2];
|
||||
// Action 4: Assign label of block Q
|
||||
#define ACTION_4 img_labels_row[c] = img_labels_row_prev_prev[c];
|
||||
// Action 5: Assign label of block R
|
||||
#define ACTION_5 img_labels_row[c] = img_labels_row_prev_prev[c + 2];
|
||||
// Action 6: Assign label of block S
|
||||
#define ACTION_6 img_labels_row[c] = img_labels_row[c - 2];
|
||||
// Action 7: Merge labels of block P and Q
|
||||
#define ACTION_7 img_labels_row[c] = set_union(P, img_labels_row_prev_prev[c - 2], img_labels_row_prev_prev[c]);
|
||||
//Action 8: Merge labels of block P and R
|
||||
#define ACTION_8 img_labels_row[c] = set_union(P, img_labels_row_prev_prev[c - 2], img_labels_row_prev_prev[c + 2]);
|
||||
// Action 9 Merge labels of block P and S
|
||||
#define ACTION_9 img_labels_row[c] = set_union(P, img_labels_row_prev_prev[c - 2], img_labels_row[c - 2]);
|
||||
// Action 10 Merge labels of block Q and R
|
||||
#define ACTION_10 img_labels_row[c] = set_union(P, img_labels_row_prev_prev[c], img_labels_row_prev_prev[c + 2]);
|
||||
// Action 11: Merge labels of block Q and S
|
||||
#define ACTION_11 img_labels_row[c] = set_union(P, img_labels_row_prev_prev[c], img_labels_row[c - 2]);
|
||||
// Action 12: Merge labels of block R and S
|
||||
#define ACTION_12 img_labels_row[c] = set_union(P, img_labels_row_prev_prev[c + 2], img_labels_row[c - 2]);
|
||||
// Action 13: Merge labels of block P, Q and R
|
||||
#define ACTION_13 img_labels_row[c] = set_union(P, set_union(P, img_labels_row_prev_prev[c - 2], img_labels_row_prev_prev[c]), img_labels_row_prev_prev[c + 2]);
|
||||
// Action 14: Merge labels of block P, Q and S
|
||||
#define ACTION_14 img_labels_row[c] = set_union(P, set_union(P, img_labels_row_prev_prev[c - 2], img_labels_row_prev_prev[c]), img_labels_row[c - 2]);
|
||||
//Action 15: Merge labels of block P, R and S
|
||||
#define ACTION_15 img_labels_row[c] = set_union(P, set_union(P, img_labels_row_prev_prev[c - 2], img_labels_row_prev_prev[c + 2]), img_labels_row[c - 2]);
|
||||
//Action 16: labels of block Q, R and S
|
||||
#define ACTION_16 img_labels_row[c] = set_union(P, set_union(P, img_labels_row_prev_prev[c], img_labels_row_prev_prev[c + 2]), img_labels_row[c - 2]);
|
||||
}
|
||||
// The following Directed Rooted Acyclic Graphs (DAGs) allow to choose which action to
|
||||
// perform, checking as few conditions as possible. Special DAGs are used for the first/last
|
||||
// line of the image and for single line images. Actions: the blocks label are provisionally
|
||||
// stored in the top left pixel of the block in the labels image.
|
||||
if (h == 1) {
|
||||
// Single line
|
||||
const PixelT * const img_row = img.ptr<PixelT>(0);
|
||||
LabelT * const img_labels_row = imgLabels.ptr<LabelT>(0);
|
||||
int c = -2;
|
||||
#include "ccl_bolelli_forest_singleline.inc.hpp"
|
||||
}
|
||||
else {
|
||||
// More than one line
|
||||
|
||||
// First couple of lines
|
||||
{
|
||||
const PixelT * const img_row = img.ptr<PixelT>(0);
|
||||
const PixelT * const img_row_fol = (PixelT *)(((char*)img_row) + img.step.p[0]);
|
||||
LabelT * const img_labels_row = imgLabels.ptr<LabelT>(0);
|
||||
int c = -2;
|
||||
#include "ccl_bolelli_forest_firstline.inc.hpp"
|
||||
}
|
||||
|
||||
// Every other line but the last one if image has an odd number of rows
|
||||
for (int r = 2; r < e_rows; r += 2) {
|
||||
// Get rows pointer
|
||||
const PixelT * const img_row = img.ptr<PixelT>(r);
|
||||
const PixelT * const img_row_prev = (PixelT *)(((char*)img_row) - img.step.p[0]);
|
||||
const PixelT * const img_row_prev_prev = (PixelT *)(((char*)img_row_prev) - img.step.p[0]);
|
||||
const PixelT * const img_row_fol = (PixelT *)(((char*)img_row) + img.step.p[0]);
|
||||
LabelT * const img_labels_row = imgLabels.ptr<LabelT>(r);
|
||||
LabelT * const img_labels_row_prev_prev = (LabelT *)(((char*)img_labels_row) - imgLabels.step.p[0] - imgLabels.step.p[0]);
|
||||
|
||||
int c = -2;
|
||||
goto tree_0;
|
||||
|
||||
#include "ccl_bolelli_forest.inc.hpp"
|
||||
}
|
||||
|
||||
// Last line (in case the rows are odd)
|
||||
if (o_rows) {
|
||||
int r = h - 1;
|
||||
const PixelT * const img_row = img.ptr<PixelT>(r);
|
||||
const PixelT * const img_row_prev = (PixelT *)(((char*)img_row) - img.step.p[0]);
|
||||
const PixelT * const img_row_prev_prev = (PixelT *)(((char*)img_row_prev) - img.step.p[0]);
|
||||
LabelT * const img_labels_row = imgLabels.ptr<LabelT>(r);
|
||||
LabelT * const img_labels_row_prev_prev = (LabelT *)(((char*)img_labels_row) - imgLabels.step.p[0] - imgLabels.step.p[0]);
|
||||
int c = -2;
|
||||
#include "ccl_bolelli_forest_lastline.inc.hpp"
|
||||
}
|
||||
}
|
||||
|
||||
// undef conditions and actions
|
||||
{
|
||||
#undef ACTION_1
|
||||
#undef ACTION_2
|
||||
#undef ACTION_3
|
||||
#undef ACTION_4
|
||||
#undef ACTION_5
|
||||
#undef ACTION_6
|
||||
#undef ACTION_7
|
||||
#undef ACTION_8
|
||||
#undef ACTION_9
|
||||
#undef ACTION_10
|
||||
#undef ACTION_11
|
||||
#undef ACTION_12
|
||||
#undef ACTION_13
|
||||
#undef ACTION_14
|
||||
#undef ACTION_15
|
||||
#undef ACTION_16
|
||||
|
||||
#undef CONDITION_B
|
||||
#undef CONDITION_C
|
||||
#undef CONDITION_D
|
||||
#undef CONDITION_E
|
||||
|
||||
#undef CONDITION_G
|
||||
#undef CONDITION_H
|
||||
#undef CONDITION_I
|
||||
#undef CONDITION_J
|
||||
#undef CONDITION_K
|
||||
|
||||
#undef CONDITION_M
|
||||
#undef CONDITION_N
|
||||
#undef CONDITION_O
|
||||
#undef CONDITION_P
|
||||
|
||||
#undef CONDITION_R
|
||||
#undef CONDITION_S
|
||||
#undef CONDITION_T
|
||||
}
|
||||
|
||||
// Second scan + analysis
|
||||
LabelT nLabels = flattenL(P, lunique);
|
||||
sop.init(nLabels);
|
||||
|
||||
int r = 0;
|
||||
for (; r < e_rows; r += 2) {
|
||||
// Get rows pointer
|
||||
const PixelT * const img_row = img.ptr<PixelT>(r);
|
||||
const PixelT * const img_row_fol = (PixelT *)(((char*)img_row) + img.step.p[0]);
|
||||
LabelT * const img_labels_row = imgLabels.ptr<LabelT>(r);
|
||||
LabelT * const img_labels_row_fol = (LabelT *)(((char*)img_labels_row) + imgLabels.step.p[0]);
|
||||
int c = 0;
|
||||
for (; c < e_cols; c += 2) {
|
||||
LabelT iLabel = img_labels_row[c];
|
||||
if (iLabel > 0) {
|
||||
iLabel = P[iLabel];
|
||||
if (img_row[c] > 0) {
|
||||
img_labels_row[c] = iLabel;
|
||||
sop(r, c, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
}
|
||||
if (img_row[c + 1] > 0) {
|
||||
img_labels_row[c + 1] = iLabel;
|
||||
sop(r, c + 1, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row[c + 1] = 0;
|
||||
sop(r, c + 1, 0);
|
||||
}
|
||||
if (img_row_fol[c] > 0) {
|
||||
img_labels_row_fol[c] = iLabel;
|
||||
sop(r + 1, c, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row_fol[c] = 0;
|
||||
sop(r + 1, c, 0);
|
||||
}
|
||||
if (img_row_fol[c + 1] > 0) {
|
||||
img_labels_row_fol[c + 1] = iLabel;
|
||||
sop(r + 1, c + 1, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row_fol[c + 1] = 0;
|
||||
sop(r + 1, c + 1, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
img_labels_row[c + 1] = 0;
|
||||
sop(r, c + 1, 0);
|
||||
img_labels_row_fol[c] = 0;
|
||||
sop(r + 1, c, 0);
|
||||
img_labels_row_fol[c + 1] = 0;
|
||||
sop(r + 1, c + 1, 0);
|
||||
}
|
||||
}
|
||||
// Last column if the number of columns is odd
|
||||
if (o_cols) {
|
||||
LabelT iLabel = img_labels_row[c];
|
||||
if (iLabel > 0) {
|
||||
iLabel = P[iLabel];
|
||||
if (img_row[c] > 0) {
|
||||
img_labels_row[c] = iLabel;
|
||||
sop(r, c, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
}
|
||||
if (img_row_fol[c] > 0) {
|
||||
img_labels_row_fol[c] = iLabel;
|
||||
sop(r + 1, c, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row_fol[c] = 0;
|
||||
sop(r + 1, c, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
img_labels_row_fol[c] = 0;
|
||||
sop(r + 1, c, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Last row if the number of rows is odd
|
||||
if (o_rows) {
|
||||
// Get rows pointer
|
||||
const PixelT * const img_row = img.ptr<PixelT>(r);
|
||||
LabelT * const img_labels_row = imgLabels.ptr<LabelT>(r);
|
||||
int c = 0;
|
||||
for (; c < e_cols; c += 2) {
|
||||
LabelT iLabel = img_labels_row[c];
|
||||
if (iLabel > 0) {
|
||||
iLabel = P[iLabel];
|
||||
if (img_row[c] > 0) {
|
||||
img_labels_row[c] = iLabel;
|
||||
sop(r, c, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
}
|
||||
if (img_row[c + 1] > 0) {
|
||||
img_labels_row[c + 1] = iLabel;
|
||||
sop(r, c + 1, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row[c + 1] = 0;
|
||||
sop(r, c + 1, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
img_labels_row[c + 1] = 0;
|
||||
sop(r, c + 1, 0);
|
||||
}
|
||||
}
|
||||
// Last column if the number of columns is odd
|
||||
if (o_cols) {
|
||||
LabelT iLabel = img_labels_row[c];
|
||||
if (iLabel > 0) {
|
||||
iLabel = P[iLabel];
|
||||
if (img_row[c] > 0) {
|
||||
img_labels_row[c] = iLabel;
|
||||
sop(r, c, iLabel);
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
img_labels_row[c] = 0;
|
||||
sop(r, c, iLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sop.finish();
|
||||
return nLabels;
|
||||
}//End function LabelingBolelli operator()
|
||||
};//End struct LabelingBolelli
|
||||
|
||||
//Parallel implementation of Scan Array-based Union Find (SAUF) algorithm, as described in "Two More Strategies to Speed
|
||||
//Up Connected Components Labeling Algorithms"
|
||||
//Federico Bolelli et. al.
|
||||
template<typename LabelT, typename PixelT, typename StatsOp = NoOp >
|
||||
struct LabelingWuParallel{
|
||||
|
||||
@ -332,11 +689,11 @@ namespace cv{
|
||||
LabelT * const imgLabels_row_prev = (LabelT *)(((char *)imgLabels_row) - imgLabels_.step.p[0]);
|
||||
for (int c = 0; c < w; ++c) {
|
||||
|
||||
#define condition_p c > 0 && r > limitLine && img_row_prev[c - 1] > 0
|
||||
#define condition_q r > limitLine && img_row_prev[c] > 0
|
||||
#define condition_r c < w - 1 && r > limitLine && img_row_prev[c + 1] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
#define condition_p c > 0 && r > limitLine && img_row_prev[c - 1] > 0
|
||||
#define condition_q r > limitLine && img_row_prev[c] > 0
|
||||
#define condition_r c < w - 1 && r > limitLine && img_row_prev[c + 1] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_q){
|
||||
@ -390,11 +747,11 @@ namespace cv{
|
||||
//write in the follower memory location
|
||||
chunksSizeAndLabels_[startR + 1] = label - firstLabel;
|
||||
}
|
||||
#undef condition_p
|
||||
#undef condition_q
|
||||
#undef condition_r
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
#undef condition_p
|
||||
#undef condition_q
|
||||
#undef condition_r
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
};
|
||||
|
||||
class FirstScan4Connectivity : public cv::ParallelLoopBody{
|
||||
@ -435,9 +792,9 @@ namespace cv{
|
||||
LabelT * const imgLabels_row_prev = (LabelT *)(((char *)imgLabels_row) - imgLabels_.step.p[0]);
|
||||
for (int c = 0; c < w; ++c) {
|
||||
|
||||
#define condition_q r > limitLine && img_row_prev[c] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
#define condition_q r > limitLine && img_row_prev[c] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_q){
|
||||
@ -471,9 +828,9 @@ namespace cv{
|
||||
//write in the following memory location
|
||||
chunksSizeAndLabels_[startR + 1] = label - firstLabel;
|
||||
}
|
||||
#undef condition_q
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
#undef condition_q
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
};
|
||||
|
||||
class SecondScan : public cv::ParallelLoopBody{
|
||||
@ -541,10 +898,10 @@ namespace cv{
|
||||
|
||||
for (int c = 0; c < w; ++c){
|
||||
|
||||
#define condition_p c > 0 && imgLabels_row_prev[c - 1] > 0
|
||||
#define condition_q imgLabels_row_prev[c] > 0
|
||||
#define condition_r c < w - 1 && imgLabels_row_prev[c + 1] > 0
|
||||
#define condition_x imgLabels_row[c] > 0
|
||||
#define condition_p c > 0 && imgLabels_row_prev[c - 1] > 0
|
||||
#define condition_q imgLabels_row_prev[c] > 0
|
||||
#define condition_r c < w - 1 && imgLabels_row_prev[c + 1] > 0
|
||||
#define condition_x imgLabels_row[c] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_p){
|
||||
@ -562,10 +919,10 @@ namespace cv{
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef condition_p
|
||||
#undef condition_q
|
||||
#undef condition_r
|
||||
#undef condition_x
|
||||
#undef condition_p
|
||||
#undef condition_q
|
||||
#undef condition_r
|
||||
#undef condition_x
|
||||
}
|
||||
|
||||
inline static
|
||||
@ -586,8 +943,8 @@ namespace cv{
|
||||
|
||||
for (int c = 0; c < w; ++c){
|
||||
|
||||
#define condition_q imgLabels_row_prev[c] > 0
|
||||
#define condition_x imgLabels_row[c] > 0
|
||||
#define condition_q imgLabels_row_prev[c] > 0
|
||||
#define condition_x imgLabels_row[c] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_q){
|
||||
@ -597,8 +954,8 @@ namespace cv{
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef condition_q
|
||||
#undef condition_x
|
||||
#undef condition_q
|
||||
#undef condition_x
|
||||
}
|
||||
|
||||
LabelT operator()(const cv::Mat& img, cv::Mat& imgLabels, int connectivity, StatsOp& sop){
|
||||
@ -671,10 +1028,9 @@ namespace cv{
|
||||
}
|
||||
};//End struct LabelingWuParallel
|
||||
|
||||
|
||||
//Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan array union find) variant
|
||||
//Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan Array-based Union Find) variant
|
||||
//using decision trees
|
||||
//Kesheng Wu, et al
|
||||
//Kesheng Wu et. al.
|
||||
template<typename LabelT, typename PixelT, typename StatsOp = NoOp >
|
||||
struct LabelingWu{
|
||||
LabelT operator()(const cv::Mat& img, cv::Mat& imgLabels, int connectivity, StatsOp& sop){
|
||||
@ -712,11 +1068,11 @@ namespace cv{
|
||||
|
||||
for (int c = 0; c < w; ++c){
|
||||
|
||||
#define condition_p c>0 && r>0 && img_row_prev[c - 1]>0
|
||||
#define condition_q r>0 && img_row_prev[c]>0
|
||||
#define condition_r c < w - 1 && r > 0 && img_row_prev[c + 1] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
#define condition_p c>0 && r>0 && img_row_prev[c - 1]>0
|
||||
#define condition_q r>0 && img_row_prev[c]>0
|
||||
#define condition_r c < w - 1 && r > 0 && img_row_prev[c + 1] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_q){
|
||||
@ -770,11 +1126,11 @@ namespace cv{
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef condition_p
|
||||
#undef condition_q
|
||||
#undef condition_r
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
#undef condition_p
|
||||
#undef condition_q
|
||||
#undef condition_r
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
}
|
||||
else{
|
||||
for (int r = 0; r < h; ++r){
|
||||
@ -784,9 +1140,9 @@ namespace cv{
|
||||
LabelT * const imgLabels_row_prev = (LabelT *)(((char *)imgLabels_row) - imgLabels.step.p[0]);
|
||||
for (int c = 0; c < w; ++c) {
|
||||
|
||||
#define condition_q r > 0 && img_row_prev[c] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
#define condition_q r > 0 && img_row_prev[c] > 0
|
||||
#define condition_s c > 0 && img_row[c - 1] > 0
|
||||
#define condition_x img_row[c] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_q){
|
||||
@ -818,9 +1174,9 @@ namespace cv{
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef condition_q
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
#undef condition_q
|
||||
#undef condition_s
|
||||
#undef condition_x
|
||||
}
|
||||
|
||||
//analysis
|
||||
@ -842,9 +1198,9 @@ namespace cv{
|
||||
}//End function LabelingWu operator()
|
||||
};//End struct LabelingWu
|
||||
|
||||
|
||||
// Based on "Optimized Block-based Connected Components Labeling with Decision Trees", Costantino Grana et al
|
||||
// Only for 8-connectivity
|
||||
//Parallel implementation of BBDT (Block-Based with Decision Tree) algorithm, as described in "Two More Strategies to Speed
|
||||
//Up Connected Components Labeling Algorithms"
|
||||
//Federico Bolelli et. al.
|
||||
template<typename LabelT, typename PixelT, typename StatsOp = NoOp >
|
||||
struct LabelingGranaParallel{
|
||||
|
||||
@ -901,31 +1257,31 @@ namespace cv{
|
||||
// +---+---+
|
||||
|
||||
// Pixels a, f, l, q are not needed, since we need to understand the
|
||||
// the connectivity between these blocks and those pixels only metter
|
||||
// the connectivity between these blocks and those pixels only matter
|
||||
// when considering the outer connectivities
|
||||
|
||||
// A bunch of defines used to check if the pixels are foreground,
|
||||
// without going outside the image limits.
|
||||
|
||||
#define condition_b c-1>=0 && r > limitLine && img_row_prev_prev[c-1]>0
|
||||
#define condition_c r > limitLine && img_row_prev_prev[c]>0
|
||||
#define condition_d c+1<w && r > limitLine && img_row_prev_prev[c+1]>0
|
||||
#define condition_e c+2<w && r > limitLine && img_row_prev_prev[c+2]>0
|
||||
#define condition_b c-1>=0 && r > limitLine && img_row_prev_prev[c-1]>0
|
||||
#define condition_c r > limitLine && img_row_prev_prev[c]>0
|
||||
#define condition_d c+1<w && r > limitLine && img_row_prev_prev[c+1]>0
|
||||
#define condition_e c+2<w && r > limitLine && img_row_prev_prev[c+2]>0
|
||||
|
||||
#define condition_g c-2>=0 && r > limitLine - 1 && img_row_prev[c-2]>0
|
||||
#define condition_h c-1>=0 && r > limitLine - 1 && img_row_prev[c-1]>0
|
||||
#define condition_i r > limitLine - 1 && img_row_prev[c]>0
|
||||
#define condition_j c+1<w && r > limitLine - 1 && img_row_prev[c+1]>0
|
||||
#define condition_k c+2<w && r > limitLine - 1 && img_row_prev[c+2]>0
|
||||
#define condition_g c-2>=0 && r > limitLine - 1 && img_row_prev[c-2]>0
|
||||
#define condition_h c-1>=0 && r > limitLine - 1 && img_row_prev[c-1]>0
|
||||
#define condition_i r > limitLine - 1 && img_row_prev[c]>0
|
||||
#define condition_j c+1<w && r > limitLine - 1 && img_row_prev[c+1]>0
|
||||
#define condition_k c+2<w && r > limitLine - 1 && img_row_prev[c+2]>0
|
||||
|
||||
#define condition_m c-2>=0 && img_row[c-2]>0
|
||||
#define condition_n c-1>=0 && img_row[c-1]>0
|
||||
#define condition_o img_row[c]>0
|
||||
#define condition_p c+1<w && img_row[c+1]>0
|
||||
#define condition_m c-2>=0 && img_row[c-2]>0
|
||||
#define condition_n c-1>=0 && img_row[c-1]>0
|
||||
#define condition_o img_row[c]>0
|
||||
#define condition_p c+1<w && img_row[c+1]>0
|
||||
|
||||
#define condition_r c-1>=0 && r+1<h && img_row_fol[c-1]>0
|
||||
#define condition_s r+1<h && img_row_fol[c]>0
|
||||
#define condition_t c+1<w && r+1<h && img_row_fol[c+1]>0
|
||||
#define condition_r c-1>=0 && r+1<h && img_row_fol[c-1]>0
|
||||
#define condition_s r+1<h && img_row_fol[c]>0
|
||||
#define condition_t c+1<w && r+1<h && img_row_fol[c+1]>0
|
||||
|
||||
// This is a decision tree which allows to choose which action to
|
||||
// perform, checking as few conditions as possible.
|
||||
@ -1903,15 +2259,15 @@ namespace cv{
|
||||
//write in the follower memory location
|
||||
chunksSizeAndLabels_[startR + 1] = label - firstLabel;
|
||||
}
|
||||
#undef condition_k
|
||||
#undef condition_j
|
||||
#undef condition_i
|
||||
#undef condition_h
|
||||
#undef condition_g
|
||||
#undef condition_e
|
||||
#undef condition_d
|
||||
#undef condition_c
|
||||
#undef condition_b
|
||||
#undef condition_k
|
||||
#undef condition_j
|
||||
#undef condition_i
|
||||
#undef condition_h
|
||||
#undef condition_g
|
||||
#undef condition_e
|
||||
#undef condition_d
|
||||
#undef condition_c
|
||||
#undef condition_b
|
||||
};
|
||||
|
||||
class SecondScan : public cv::ParallelLoopBody{
|
||||
@ -2511,12 +2867,12 @@ namespace cv{
|
||||
|
||||
for (int c = 0; c < w; c += 2){
|
||||
|
||||
#define condition_x imgLabels_row[c] > 0
|
||||
#define condition_pppr c > 1 && imgLabels_row_prev_prev[c - 2] > 0
|
||||
#define condition_qppr imgLabels_row_prev_prev[c] > 0
|
||||
#define condition_qppr1 c < w - 1
|
||||
#define condition_qppr2 c < w
|
||||
#define condition_rppr c < w - 2 && imgLabels_row_prev_prev[c + 2] > 0
|
||||
#define condition_x imgLabels_row[c] > 0
|
||||
#define condition_pppr c > 1 && imgLabels_row_prev_prev[c - 2] > 0
|
||||
#define condition_qppr imgLabels_row_prev_prev[c] > 0
|
||||
#define condition_qppr1 c < w - 1
|
||||
#define condition_qppr2 c < w
|
||||
#define condition_rppr c < w - 2 && imgLabels_row_prev_prev[c + 2] > 0
|
||||
|
||||
if (condition_x){
|
||||
if (condition_pppr){
|
||||
@ -2603,8 +2959,9 @@ namespace cv{
|
||||
}
|
||||
};//End struct LabelingGranaParallel
|
||||
|
||||
// Based on "Optimized Block-based Connected Components Labeling with Decision Trees", Costantino Grana et al
|
||||
// Only for 8-connectivity
|
||||
//Implementation of BBDT (Block-Based with Decision Tree) algorithm, as described in "Optimized Block-based Connected
|
||||
//Components Labeling with Decision Trees" (only for 8-connectivity)
|
||||
//Costantino Grana et. al.
|
||||
template<typename LabelT, typename PixelT, typename StatsOp = NoOp >
|
||||
struct LabelingGrana{
|
||||
LabelT operator()(const cv::Mat& img, cv::Mat& imgLabels, int connectivity, StatsOp& sop){
|
||||
@ -2658,30 +3015,30 @@ namespace cv{
|
||||
// +---+---+
|
||||
|
||||
// Pixels a, f, l, q are not needed, since we need to understand the
|
||||
// the connectivity between these blocks and those pixels only metter
|
||||
// the connectivity between these blocks and those pixels only matter
|
||||
// when considering the outer connectivities
|
||||
|
||||
// A bunch of defines used to check if the pixels are foreground,
|
||||
// without going outside the image limits.
|
||||
#define condition_b c-1>=0 && r-2>=0 && img_row_prev_prev[c-1]>0
|
||||
#define condition_c r-2>=0 && img_row_prev_prev[c]>0
|
||||
#define condition_d c+1<w&& r-2>=0 && img_row_prev_prev[c+1]>0
|
||||
#define condition_e c+2<w && r-1>=0 && img_row_prev[c-1]>0
|
||||
#define condition_b c-1>=0 && r-2>=0 && img_row_prev_prev[c-1]>0
|
||||
#define condition_c r-2>=0 && img_row_prev_prev[c]>0
|
||||
#define condition_d c+1<w&& r-2>=0 && img_row_prev_prev[c+1]>0
|
||||
#define condition_e c+2<w && r-1>=0 && img_row_prev[c-1]>0
|
||||
|
||||
#define condition_g c-2>=0 && r-1>=0 && img_row_prev[c-2]>0
|
||||
#define condition_h c-1>=0 && r-1>=0 && img_row_prev[c-1]>0
|
||||
#define condition_i r-1>=0 && img_row_prev[c]>0
|
||||
#define condition_j c+1<w && r-1>=0 && img_row_prev[c+1]>0
|
||||
#define condition_k c+2<w && r-1>=0 && img_row_prev[c+2]>0
|
||||
#define condition_g c-2>=0 && r-1>=0 && img_row_prev[c-2]>0
|
||||
#define condition_h c-1>=0 && r-1>=0 && img_row_prev[c-1]>0
|
||||
#define condition_i r-1>=0 && img_row_prev[c]>0
|
||||
#define condition_j c+1<w && r-1>=0 && img_row_prev[c+1]>0
|
||||
#define condition_k c+2<w && r-1>=0 && img_row_prev[c+2]>0
|
||||
|
||||
#define condition_m c-2>=0 && img_row[c-2]>0
|
||||
#define condition_n c-1>=0 && img_row[c-1]>0
|
||||
#define condition_o img_row[c]>0
|
||||
#define condition_p c+1<w && img_row[c+1]>0
|
||||
#define condition_m c-2>=0 && img_row[c-2]>0
|
||||
#define condition_n c-1>=0 && img_row[c-1]>0
|
||||
#define condition_o img_row[c]>0
|
||||
#define condition_p c+1<w && img_row[c+1]>0
|
||||
|
||||
#define condition_r c-1>=0 && r+1<h && img_row_fol[c-1]>0
|
||||
#define condition_s r+1<h && img_row_fol[c]>0
|
||||
#define condition_t c+1<w && r+1<h && img_row_fol[c+1]>0
|
||||
#define condition_r c-1>=0 && r+1<h && img_row_fol[c-1]>0
|
||||
#define condition_s r+1<h && img_row_fol[c]>0
|
||||
#define condition_t c+1<w && r+1<h && img_row_fol[c+1]>0
|
||||
|
||||
// This is a decision tree which allows to choose which action to
|
||||
// perform, checking as few conditions as possible.
|
||||
@ -3948,7 +4305,7 @@ namespace cv{
|
||||
int connectedComponents_sub1(const cv::Mat& I, cv::Mat& L, int connectivity, int ccltype, StatsOp& sop){
|
||||
CV_Assert(L.channels() == 1 && I.channels() == 1);
|
||||
CV_Assert(connectivity == 8 || connectivity == 4);
|
||||
CV_Assert(ccltype == CCL_GRANA || ccltype == CCL_WU || ccltype == CCL_DEFAULT);
|
||||
CV_Assert(ccltype == CCL_SPAGHETTI || ccltype == CCL_BBDT || ccltype == CCL_SAUF || ccltype == CCL_BOLELLI || ccltype == CCL_GRANA || ccltype == CCL_WU || ccltype == CCL_DEFAULT);
|
||||
|
||||
int lDepth = L.depth();
|
||||
int iDepth = I.depth();
|
||||
@ -3960,8 +4317,8 @@ namespace cv{
|
||||
//Run parallel labeling only if the rows of the image are at least twice the number of available threads
|
||||
const bool is_parallel = currentParallelFramework != NULL && nThreads > 1 && L.rows / nThreads >= 2;
|
||||
|
||||
if (ccltype == CCL_WU || connectivity == 4){
|
||||
// Wu algorithm is used
|
||||
if (ccltype == CCL_SAUF || ccltype == CCL_WU || connectivity == 4){
|
||||
// SAUF algorithm is used
|
||||
using connectedcomponents::LabelingWu;
|
||||
using connectedcomponents::LabelingWuParallel;
|
||||
//warn if L's depth is not sufficient?
|
||||
@ -3980,8 +4337,8 @@ namespace cv{
|
||||
return (int)LabelingWuParallel<int, uchar, StatsOp>()(I, L, connectivity, sop);
|
||||
}
|
||||
}
|
||||
else if ((ccltype == CCL_GRANA || ccltype == CCL_DEFAULT) && connectivity == 8){
|
||||
// Grana algorithm is used
|
||||
else if ((ccltype == CCL_BBDT || ccltype == CCL_GRANA || ccltype == CCL_DEFAULT) && connectivity == 8){
|
||||
// BBDT algorithm is used
|
||||
using connectedcomponents::LabelingGrana;
|
||||
using connectedcomponents::LabelingGranaParallel;
|
||||
//warn if L's depth is not sufficient?
|
||||
@ -4000,6 +4357,23 @@ namespace cv{
|
||||
return (int)LabelingGranaParallel<int, uchar, StatsOp>()(I, L, connectivity, sop);
|
||||
}
|
||||
}
|
||||
else if ((ccltype == CCL_SPAGHETTI || ccltype == CCL_BOLELLI) && connectivity == 8) {
|
||||
// Spaghetti algorithm is used
|
||||
using connectedcomponents::LabelingBolelli;
|
||||
//using connectedcomponents::LabelingBolelliParallel; // Not implemented
|
||||
//warn if L's depth is not sufficient?
|
||||
if (lDepth == CV_8U) {
|
||||
//Not supported yet
|
||||
}
|
||||
else if (lDepth == CV_16U) {
|
||||
return (int)LabelingBolelli<ushort, uchar, StatsOp>()(I, L, connectivity, sop);
|
||||
}
|
||||
else if (lDepth == CV_32S) {
|
||||
//note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects
|
||||
//OpenCV: how should we proceed? .at<T> typechecks in debug mode
|
||||
return (int)LabelingBolelli<int, uchar, StatsOp>()(I, L, connectivity, sop);
|
||||
}
|
||||
}
|
||||
|
||||
CV_Error(CV_StsUnsupportedFormat, "unsupported label/image type");
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ struct RemapVec_8u
|
||||
{
|
||||
int cn = _src.channels(), x = 0, sstep = (int)_src.step;
|
||||
|
||||
if( (cn != 1 && cn != 3 && cn != 4) || sstep > 0x8000 )
|
||||
if( (cn != 1 && cn != 3 && cn != 4) || sstep >= 0x8000 )
|
||||
return 0;
|
||||
|
||||
const uchar *S0 = _src.ptr(), *S1 = _src.ptr(1);
|
||||
|
@ -74,11 +74,10 @@ void normalizeLabels(Mat1i& imgLabels, int iNumLabels) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_ConnectedComponentsTest::run( int /* start_from */)
|
||||
{
|
||||
|
||||
int ccltype[] = { cv::CCL_WU, cv::CCL_DEFAULT, cv::CCL_GRANA };
|
||||
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, 0);
|
||||
@ -150,7 +149,6 @@ TEST(Imgproc_ConnectedComponents, grana_buffer_overflow)
|
||||
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));
|
||||
@ -239,5 +237,124 @@ TEST(Imgproc_ConnectedComponents, missing_background_pixels)
|
||||
EXPECT_TRUE(std::isnan(centroids.at<double>(0, 1)));
|
||||
}
|
||||
|
||||
TEST(Imgproc_ConnectedComponents, spaghetti_bbdt_sauf_stats)
|
||||
{
|
||||
cv::Mat1b img(16, 16);
|
||||
img << 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);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
@ -1473,6 +1473,26 @@ TEST(Imgproc_Warp, multichannel)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_Warp, regression_19566) // valgrind should detect problem if any
|
||||
{
|
||||
const Size imgSize(8192, 8);
|
||||
|
||||
Mat inMat = Mat::zeros(imgSize, CV_8UC4);
|
||||
Mat outMat = Mat::zeros(imgSize, CV_8UC4);
|
||||
|
||||
warpAffine(
|
||||
inMat,
|
||||
outMat,
|
||||
getRotationMatrix2D(Point2f(imgSize.width / 2.0f, imgSize.height / 2.0f), 45.0, 1.0),
|
||||
imgSize,
|
||||
INTER_LINEAR,
|
||||
cv::BORDER_CONSTANT,
|
||||
cv::Scalar(0.0, 0.0, 0.0, 255.0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_GetAffineTransform, singularity)
|
||||
{
|
||||
Point2f A_sample[3];
|
||||
|
@ -2129,80 +2129,83 @@ namespace {
|
||||
#undef JOCvT
|
||||
}
|
||||
|
||||
template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
|
||||
{
|
||||
if(! m) return 0;
|
||||
if(! buff) return 0;
|
||||
|
||||
count *= sizeof(T);
|
||||
int rest = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
|
||||
if(count>rest) count = rest;
|
||||
int res = count;
|
||||
|
||||
if( m->isContinuous() )
|
||||
{
|
||||
memcpy(m->ptr(row, col), buff + offset, count);
|
||||
} else {
|
||||
// row by row
|
||||
int num = (m->cols - col) * (int)m->elemSize(); // 1st partial row
|
||||
if(count<num) num = count;
|
||||
uchar* data = m->ptr(row++, col);
|
||||
while(count>0){
|
||||
memcpy(data, buff + offset, num);
|
||||
count -= num;
|
||||
buff += num;
|
||||
num = m->cols * (int)m->elemSize();
|
||||
if(count<num) num = count;
|
||||
data = m->ptr(row++, 0);
|
||||
}
|
||||
static size_t idx2Offset(cv::Mat* mat, std::vector<int>& indices) {
|
||||
size_t offset = indices[0];
|
||||
for (int dim=1; dim < mat->dims; dim++) {
|
||||
offset = offset*mat->size[dim] + indices[dim];
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void offset2Idx(cv::Mat* mat, size_t offset, std::vector<int>& indices) {
|
||||
for (int dim=mat->dims-1; dim>=0; dim--) {
|
||||
indices[dim] = offset % mat->size[dim];
|
||||
offset = (offset - indices[dim]) / mat->size[dim];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// returns true if final index was reached
|
||||
static bool updateIdx(cv::Mat* m, std::vector<int>& idx, int inc) {
|
||||
for (int i=m->dims-1; i>=0; i--) {
|
||||
if (inc == 0) return false;
|
||||
idx[i] = (idx[i] + 1) % m->size[i];
|
||||
inc--;
|
||||
}
|
||||
return true;
|
||||
static bool updateIdx(cv::Mat* mat, std::vector<int>& indices, size_t inc) {
|
||||
size_t currentOffset = idx2Offset(mat, indices);
|
||||
size_t newOffset = currentOffset + inc;
|
||||
bool reachedEnd = newOffset>=(size_t)mat->total();
|
||||
offset2Idx(mat, reachedEnd?0:newOffset, indices);
|
||||
return reachedEnd;
|
||||
}
|
||||
|
||||
template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
|
||||
{
|
||||
template<typename T> static int mat_copy_data(cv::Mat* m, std::vector<int>& idx, int count, char* buff, bool isPut) {
|
||||
if(! m) return 0;
|
||||
if(! buff) return 0;
|
||||
|
||||
count *= sizeof(T);
|
||||
int rest = (int)m->elemSize();
|
||||
for (int i = 0; i < m->dims; i++) {
|
||||
rest *= (m->size[i] - idx[i]);
|
||||
}
|
||||
if(count>rest) count = rest;
|
||||
int res = count;
|
||||
size_t countBytes = count * sizeof(T);
|
||||
size_t remainingBytes = (size_t)(m->total() - idx2Offset(m, idx))*m->elemSize();
|
||||
countBytes = (countBytes>remainingBytes)?remainingBytes:countBytes;
|
||||
int res = (int)countBytes;
|
||||
|
||||
if( m->isContinuous() )
|
||||
{
|
||||
memcpy(m->ptr(idx.data()), buff + offset, count);
|
||||
if (isPut) {
|
||||
memcpy(m->ptr(idx.data()), buff, countBytes);
|
||||
} else {
|
||||
memcpy(buff, m->ptr(idx.data()), countBytes);
|
||||
}
|
||||
} else {
|
||||
// dim by dim
|
||||
int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
|
||||
if(count<num) num = count;
|
||||
size_t blockSize = m->size[m->dims-1] * m->elemSize();
|
||||
size_t firstPartialBlockSize = (m->size[m->dims-1] - idx[m->dims-1]) * m->step[m->dims-1];;
|
||||
for (int dim=m->dims-2; dim>=0 && blockSize == m->step[dim]; dim--) {
|
||||
blockSize *= m->size[dim];
|
||||
firstPartialBlockSize += (m->size[dim] - (idx[dim]+1)) * m->step[dim];
|
||||
}
|
||||
size_t copyCount = (countBytes<firstPartialBlockSize)?countBytes:firstPartialBlockSize;
|
||||
uchar* data = m->ptr(idx.data());
|
||||
while(count>0){
|
||||
memcpy(data, buff + offset, num);
|
||||
updateIdx(m, idx, num / (int)m->elemSize());
|
||||
count -= num;
|
||||
buff += num;
|
||||
num = m->size[m->dims-1] * (int)m->elemSize();
|
||||
if(count<num) num = count;
|
||||
while(countBytes>0){
|
||||
if (isPut) {
|
||||
memcpy(data, buff, copyCount);
|
||||
} else {
|
||||
memcpy(buff, data, copyCount);
|
||||
}
|
||||
updateIdx(m, idx, copyCount / m->elemSize());
|
||||
countBytes -= copyCount;
|
||||
buff += copyCount;
|
||||
copyCount = countBytes<blockSize?countBytes:blockSize;
|
||||
data = m->ptr(idx.data());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
|
||||
{
|
||||
return mat_copy_data<T>(m, idx, count, buff + offset, true);
|
||||
}
|
||||
|
||||
template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
|
||||
{
|
||||
int indicesArray[] = { row, col };
|
||||
std::vector<int> indices(indicesArray, indicesArray+2);
|
||||
return mat_put_idx<T>(m, indices, count, offset, buff);
|
||||
}
|
||||
|
||||
template<class ARRAY> static jint java_mat_put(JNIEnv* env, jlong self, jint row, jint col, jint count, jint offset, ARRAY vals)
|
||||
{
|
||||
static const char *method_name = JavaOpenCVTrait<ARRAY>::put;
|
||||
@ -2455,68 +2458,16 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
|
||||
|
||||
} // extern "C"
|
||||
|
||||
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
|
||||
{
|
||||
if(! m) return 0;
|
||||
if(! buff) return 0;
|
||||
|
||||
int bytesToCopy = count * sizeof(T);
|
||||
int bytesRestInMat = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
|
||||
if(bytesToCopy > bytesRestInMat) bytesToCopy = bytesRestInMat;
|
||||
int res = bytesToCopy;
|
||||
|
||||
if( m->isContinuous() )
|
||||
{
|
||||
memcpy(buff, m->ptr(row, col), bytesToCopy);
|
||||
} else {
|
||||
// row by row
|
||||
int bytesInRow = (m->cols - col) * (int)m->elemSize(); // 1st partial row
|
||||
while(bytesToCopy > 0)
|
||||
{
|
||||
int len = std::min(bytesToCopy, bytesInRow);
|
||||
memcpy(buff, m->ptr(row, col), len);
|
||||
bytesToCopy -= len;
|
||||
buff += len;
|
||||
row++;
|
||||
col = 0;
|
||||
bytesInRow = m->cols * (int)m->elemSize();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
|
||||
{
|
||||
if(! m) return 0;
|
||||
if(! buff) return 0;
|
||||
return mat_copy_data<T>(m, idx, count, buff, false);
|
||||
}
|
||||
|
||||
count *= sizeof(T);
|
||||
int rest = (int)m->elemSize();
|
||||
for (int i = 0; i < m->dims; i++) {
|
||||
rest *= (m->size[i] - idx[i]);
|
||||
}
|
||||
if(count>rest) count = rest;
|
||||
int res = count;
|
||||
|
||||
if( m->isContinuous() )
|
||||
{
|
||||
memcpy(buff, m->ptr(idx.data()), count);
|
||||
} else {
|
||||
// dim by dim
|
||||
int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
|
||||
if(count<num) num = count;
|
||||
uchar* data = m->ptr(idx.data());
|
||||
while(count>0){
|
||||
memcpy(buff, data, num);
|
||||
updateIdx(m, idx, num / (int)m->elemSize());
|
||||
count -= num;
|
||||
buff += num;
|
||||
num = m->size[m->dims-1] * (int)m->elemSize();
|
||||
if(count<num) num = count;
|
||||
data = m->ptr(idx.data());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
|
||||
{
|
||||
int indicesArray[] = { row, col };
|
||||
std::vector<int> indices(indicesArray, indicesArray+2);
|
||||
return mat_get_idx<T>(m, indices, count, buff);
|
||||
}
|
||||
|
||||
template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) {
|
||||
|
@ -279,19 +279,23 @@ public class OpenCVTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
|
||||
if (ar1.length != ar2.length) {
|
||||
fail("Arrays have different sizes.");
|
||||
}
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
|
||||
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
|
||||
}
|
||||
|
||||
public static void assertArrayEquals(short[] ar1, short[] ar2) {
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i], ar2[i]);
|
||||
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
|
||||
}
|
||||
|
||||
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
|
||||
if (ar1.length != ar2.length) {
|
||||
fail("Arrays have different sizes.");
|
||||
}
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i], ar2[i], epsilon);
|
||||
|
@ -305,19 +305,22 @@ public class OpenCVTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
|
||||
if (ar1.length != ar2.length) {
|
||||
fail("Arrays have different sizes.");
|
||||
}
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
|
||||
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
|
||||
}
|
||||
|
||||
public static void assertArrayEquals(short[] ar1, short[] ar2) {
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i], ar2[i]);
|
||||
}
|
||||
|
||||
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
|
||||
if (ar1.length != ar2.length) {
|
||||
fail("Arrays have different sizes.");
|
||||
}
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i], ar2[i], epsilon);
|
||||
|
@ -30,6 +30,7 @@ def main():
|
||||
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 10, np.array([]), 100, 30, 1, 30)
|
||||
|
||||
if circles is not None: # Check if circles have been found and only then iterate over these and add them to the image
|
||||
circles = np.uint16(np.around(circles))
|
||||
_a, b, _c = circles.shape
|
||||
for i in range(b):
|
||||
cv.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv.LINE_AA)
|
||||
|
@ -38,10 +38,10 @@ def Hist_and_Backproj(val):
|
||||
|
||||
## [Read the image]
|
||||
parser = argparse.ArgumentParser(description='Code for Back Projection tutorial.')
|
||||
parser.add_argument('--input', help='Path to input image.')
|
||||
parser.add_argument('--input', help='Path to input image.', default='home.jpg')
|
||||
args = parser.parse_args()
|
||||
|
||||
src = cv.imread(args.input)
|
||||
src = cv.imread(cv.samples.findFile(args.input))
|
||||
if src is None:
|
||||
print('Could not open or find the image:', args.input)
|
||||
exit(0)
|
||||
|
@ -54,10 +54,10 @@ def Hist_and_Backproj(mask):
|
||||
|
||||
# Read the image
|
||||
parser = argparse.ArgumentParser(description='Code for Back Projection tutorial.')
|
||||
parser.add_argument('--input', help='Path to input image.')
|
||||
parser.add_argument('--input', help='Path to input image.', default='home.jpg')
|
||||
args = parser.parse_args()
|
||||
|
||||
src = cv.imread(args.input)
|
||||
src = cv.imread(cv.samples.findFile(args.input))
|
||||
if src is None:
|
||||
print('Could not open or find the image:', args.input)
|
||||
exit(0)
|
||||
|
@ -53,14 +53,14 @@ cv.normalize(r_hist, r_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX)
|
||||
|
||||
## [Draw for each channel]
|
||||
for i in range(1, histSize):
|
||||
cv.line(histImage, ( bin_w*(i-1), hist_h - int(round(b_hist[i-1])) ),
|
||||
( bin_w*(i), hist_h - int(round(b_hist[i])) ),
|
||||
cv.line(histImage, ( bin_w*(i-1), hist_h - int(b_hist[i-1]) ),
|
||||
( bin_w*(i), hist_h - int(b_hist[i]) ),
|
||||
( 255, 0, 0), thickness=2)
|
||||
cv.line(histImage, ( bin_w*(i-1), hist_h - int(round(g_hist[i-1])) ),
|
||||
( bin_w*(i), hist_h - int(round(g_hist[i])) ),
|
||||
cv.line(histImage, ( bin_w*(i-1), hist_h - int(g_hist[i-1]) ),
|
||||
( bin_w*(i), hist_h - int(g_hist[i]) ),
|
||||
( 0, 255, 0), thickness=2)
|
||||
cv.line(histImage, ( bin_w*(i-1), hist_h - int(round(r_hist[i-1])) ),
|
||||
( bin_w*(i), hist_h - int(round(r_hist[i])) ),
|
||||
cv.line(histImage, ( bin_w*(i-1), hist_h - int(r_hist[i-1]) ),
|
||||
( bin_w*(i), hist_h - int(r_hist[i]) ),
|
||||
( 0, 0, 255), thickness=2)
|
||||
## [Draw for each channel]
|
||||
|
||||
|
@ -30,7 +30,7 @@ def goodFeaturesToTrack_Demo(val):
|
||||
print('** Number of corners detected:', corners.shape[0])
|
||||
radius = 4
|
||||
for i in range(corners.shape[0]):
|
||||
cv.circle(copy, (corners[i,0,0], corners[i,0,1]), radius, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
|
||||
cv.circle(copy, (int(corners[i,0,0]), int(corners[i,0,1])), radius, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
|
||||
|
||||
# Show what you got
|
||||
cv.namedWindow(source_window)
|
||||
|
@ -30,7 +30,7 @@ def goodFeaturesToTrack_Demo(val):
|
||||
print('** Number of corners detected:', corners.shape[0])
|
||||
radius = 4
|
||||
for i in range(corners.shape[0]):
|
||||
cv.circle(copy, (corners[i,0,0], corners[i,0,1]), radius, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
|
||||
cv.circle(copy, (int(corners[i,0,0]), int(corners[i,0,1])), radius, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
|
||||
|
||||
# Show what you got
|
||||
cv.namedWindow(source_window)
|
||||
|
@ -53,7 +53,7 @@ thickness = 2
|
||||
sv = svm.getUncompressedSupportVectors()
|
||||
|
||||
for i in range(sv.shape[0]):
|
||||
cv.circle(image, (sv[i,0], sv[i,1]), 6, (128, 128, 128), thickness)
|
||||
cv.circle(image, (int(sv[i,0]), int(sv[i,1])), 6, (128, 128, 128), thickness)
|
||||
## [show_vectors]
|
||||
|
||||
cv.imwrite('result.png', image) # save the image
|
||||
|
@ -94,13 +94,13 @@ thick = -1
|
||||
for i in range(NTRAINING_SAMPLES):
|
||||
px = trainData[i,0]
|
||||
py = trainData[i,1]
|
||||
cv.circle(I, (px, py), 3, (0, 255, 0), thick)
|
||||
cv.circle(I, (int(px), int(py)), 3, (0, 255, 0), thick)
|
||||
|
||||
# Class 2
|
||||
for i in range(NTRAINING_SAMPLES, 2*NTRAINING_SAMPLES):
|
||||
px = trainData[i,0]
|
||||
py = trainData[i,1]
|
||||
cv.circle(I, (px, py), 3, (255, 0, 0), thick)
|
||||
cv.circle(I, (int(px), int(py)), 3, (255, 0, 0), thick)
|
||||
## [show_data]
|
||||
|
||||
#------------------------- 6. Show support vectors --------------------------------------------
|
||||
@ -109,7 +109,7 @@ thick = 2
|
||||
sv = svm.getUncompressedSupportVectors()
|
||||
|
||||
for i in range(sv.shape[0]):
|
||||
cv.circle(I, (sv[i,0], sv[i,1]), 6, (128, 128, 128), thick)
|
||||
cv.circle(I, (int(sv[i,0]), int(sv[i,1])), 6, (128, 128, 128), thick)
|
||||
## [show_vectors]
|
||||
|
||||
cv.imwrite('result.png', I) # save the Image
|
||||
|
@ -33,7 +33,7 @@ def hog(img):
|
||||
return hist
|
||||
## [hog]
|
||||
|
||||
img = cv.imread('digits.png',0)
|
||||
img = cv.imread(cv.samples.findFile('digits.png'),0)
|
||||
if img is None:
|
||||
raise Exception("we need the digits.png image from samples/data here !")
|
||||
|
||||
|
@ -40,15 +40,16 @@ while(1):
|
||||
p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
|
||||
|
||||
# Select good points
|
||||
good_new = p1[st==1]
|
||||
good_old = p0[st==1]
|
||||
if p1 is not None:
|
||||
good_new = p1[st==1]
|
||||
good_old = p0[st==1]
|
||||
|
||||
# draw the tracks
|
||||
for i,(new,old) in enumerate(zip(good_new, good_old)):
|
||||
a,b = new.ravel()
|
||||
c,d = old.ravel()
|
||||
mask = cv.line(mask, (a,b),(c,d), color[i].tolist(), 2)
|
||||
frame = cv.circle(frame,(a,b),5,color[i].tolist(),-1)
|
||||
mask = cv.line(mask, (int(a),int(b)),(int(c),int(d)), color[i].tolist(), 2)
|
||||
frame = cv.circle(frame,(int(a),int(b)),5,color[i].tolist(),-1)
|
||||
img = cv.add(frame,mask)
|
||||
|
||||
cv.imshow('frame',img)
|
||||
|
@ -86,8 +86,8 @@ def main():
|
||||
|
||||
framenum = -1 # Frame counter
|
||||
|
||||
captRefrnc = cv.VideoCapture(sourceReference)
|
||||
captUndTst = cv.VideoCapture(sourceCompareWith)
|
||||
captRefrnc = cv.VideoCapture(cv.samples.findFileOrKeep(sourceReference))
|
||||
captUndTst = cv.VideoCapture(cv.samples.findFileOrKeep(sourceCompareWith))
|
||||
|
||||
if not captRefrnc.isOpened():
|
||||
print("Could not open the reference " + sourceReference)
|
||||
|
Loading…
Reference in New Issue
Block a user