1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2023-09-28 16:42:08 +03:00
202 changed files with 14784 additions and 7242 deletions
+15
View File
@@ -349,6 +349,9 @@ be set to the default -1. In this case, the output array will have the same dept
array, be it src1, src2 or both.
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@note (Python) Be careful to difference behaviour between src1/src2 are single number and they are tuple/array.
`add(src,X)` means `add(src,(X,X,X,X))`.
`add(src,(X,))` means `add(src,(X,0,0,0))`.
@param src1 first input array or a scalar.
@param src2 second input array or a scalar.
@param dst output array that has the same size and number of channels as the input array(s); the
@@ -390,6 +393,9 @@ in the first case, when src1.depth() == src2.depth(), dtype can be set to the de
case the output array will have the same depth as the input array, be it src1, src2 or both.
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@note (Python) Be careful to difference behaviour between src1/src2 are single number and they are tuple/array.
`subtract(src,X)` means `subtract(src,(X,X,X,X))`.
`subtract(src,(X,))` means `subtract(src,(X,0,0,0))`.
@param src1 first input array or a scalar.
@param src2 second input array or a scalar.
@param dst output array of the same size and the same number of channels as the input array.
@@ -415,6 +421,9 @@ For a not-per-element matrix product, see gemm .
@note Saturation is not applied when the output array has the depth
CV_32S. You may even get result of an incorrect sign in the case of
overflow.
@note (Python) Be careful to difference behaviour between src1/src2 are single number and they are tuple/array.
`multiply(src,X)` means `multiply(src,(X,X,X,X))`.
`multiply(src,(X,))` means `multiply(src,(X,0,0,0))`.
@param src1 first input array.
@param src2 second input array of the same size and the same type as src1.
@param dst output array of the same size and type as src1.
@@ -443,6 +452,9 @@ Expect correct IEEE-754 behaviour for floating-point data (with NaN, Inf result
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@note (Python) Be careful to difference behaviour between src1/src2 are single number and they are tuple/array.
`divide(src,X)` means `divide(src,(X,X,X,X))`.
`divide(src,(X,))` means `divide(src,(X,0,0,0))`.
@param src1 first input array.
@param src2 second input array of the same size and type as src1.
@param scale scalar factor.
@@ -1412,6 +1424,9 @@ The function cv::absdiff calculates:
multi-channel arrays, each channel is processed independently.
@note Saturation is not applied when the arrays have the depth CV_32S.
You may even get a negative value in the case of overflow.
@note (Python) Be careful to difference behaviour between src1/src2 are single number and they are tuple/array.
`absdiff(src,X)` means `absdiff(src,(X,X,X,X))`.
`absdiff(src,(X,))` means `absdiff(src,(X,0,0,0))`.
@param src1 first input array or a scalar.
@param src2 second input array or a scalar.
@param dst output array that has the same size and type as input arrays.
@@ -760,7 +760,22 @@ namespace CV__SIMD_NAMESPACE {
inline _Tpvec v_add(const _Tpvec& f1, const _Tpvec& f2, const Args&... vf) { \
return v_add(f1 + f2, vf...); \
}
#define OPENCV_HAL_WRAP_SHIFT_OP(_Tpvec) \
inline _Tpvec v_shr(const _Tpvec& a, int n) \
{ \
return a >> n; \
} \
inline _Tpvec v_shl(const _Tpvec& a, int n) \
{ \
return a << n; \
}
OPENCV_HAL_WRAP_SHIFT_OP(v_uint16)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint32)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint64)
OPENCV_HAL_WRAP_SHIFT_OP(v_int16)
OPENCV_HAL_WRAP_SHIFT_OP(v_int32)
OPENCV_HAL_WRAP_SHIFT_OP(v_int64)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_uint8)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_uint16)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_uint32)
@@ -784,6 +799,12 @@ namespace CV__SIMD_NAMESPACE {
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_int32x4)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_int64x2)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_float32x4)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint16x8)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint32x4)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint64x2)
OPENCV_HAL_WRAP_SHIFT_OP(v_int16x8)
OPENCV_HAL_WRAP_SHIFT_OP(v_int32x4)
OPENCV_HAL_WRAP_SHIFT_OP(v_int64x2)
#if CV_SIMD_64F
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_float64x2)
#endif
@@ -799,6 +820,12 @@ namespace CV__SIMD_NAMESPACE {
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_int32x8)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_int64x4)
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_float32x8)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint16x16)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint32x8)
OPENCV_HAL_WRAP_SHIFT_OP(v_uint64x4)
OPENCV_HAL_WRAP_SHIFT_OP(v_int16x16)
OPENCV_HAL_WRAP_SHIFT_OP(v_int32x8)
OPENCV_HAL_WRAP_SHIFT_OP(v_int64x4)
#if CV_SIMD_64F
OPENCV_HAL_WRAP_BIN_OP_ADDSUB(v_float64x4)
#endif
@@ -816,7 +843,9 @@ namespace CV__SIMD_NAMESPACE {
inline _Tpvec v_xor(const _Tpvec& a, const _Tpvec& b) \
{ \
return a ^ b; \
} \
}
#define OPENCV_HAL_WRAP_NOT_OP(_Tpvec) \
inline _Tpvec v_not(const _Tpvec& a) \
{ \
return ~a; \
@@ -830,6 +859,18 @@ namespace CV__SIMD_NAMESPACE {
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int16)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int32)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int64)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_float32)
OPENCV_HAL_WRAP_NOT_OP(v_uint8)
OPENCV_HAL_WRAP_NOT_OP(v_uint16)
OPENCV_HAL_WRAP_NOT_OP(v_uint32)
OPENCV_HAL_WRAP_NOT_OP(v_uint64)
OPENCV_HAL_WRAP_NOT_OP(v_int8)
OPENCV_HAL_WRAP_NOT_OP(v_int16)
OPENCV_HAL_WRAP_NOT_OP(v_int32)
OPENCV_HAL_WRAP_NOT_OP(v_int64)
#if CV_SIMD_64F
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_float64)
#endif
#if CV_SIMD_WIDTH != 16/*128*/ && CV_SIMD128
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_uint8x16)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_uint16x8)
@@ -839,6 +880,18 @@ namespace CV__SIMD_NAMESPACE {
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int16x8)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int32x4)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int64x2)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_float32x4)
OPENCV_HAL_WRAP_NOT_OP(v_uint8x16)
OPENCV_HAL_WRAP_NOT_OP(v_uint16x8)
OPENCV_HAL_WRAP_NOT_OP(v_uint32x4)
OPENCV_HAL_WRAP_NOT_OP(v_uint64x2)
OPENCV_HAL_WRAP_NOT_OP(v_int8x16)
OPENCV_HAL_WRAP_NOT_OP(v_int16x8)
OPENCV_HAL_WRAP_NOT_OP(v_int32x4)
OPENCV_HAL_WRAP_NOT_OP(v_int64x2)
#if CV_SIMD_64F
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_float64x2)
#endif
#endif
#if CV_SIMD_WIDTH != 32/*256*/ && CV_SIMD256
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_uint8x32)
@@ -849,6 +902,18 @@ namespace CV__SIMD_NAMESPACE {
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int16x16)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int32x8)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_int64x4)
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_float32x8)
OPENCV_HAL_WRAP_NOT_OP(v_uint8x32)
OPENCV_HAL_WRAP_NOT_OP(v_uint16x16)
OPENCV_HAL_WRAP_NOT_OP(v_uint32x8)
OPENCV_HAL_WRAP_NOT_OP(v_uint64x4)
OPENCV_HAL_WRAP_NOT_OP(v_int8x32)
OPENCV_HAL_WRAP_NOT_OP(v_int16x16)
OPENCV_HAL_WRAP_NOT_OP(v_int32x8)
OPENCV_HAL_WRAP_NOT_OP(v_int64x4)
#if CV_SIMD_64F
OPENCV_HAL_WRAP_BIN_OP_LOGIC(v_float64x4)
#endif
#endif
#define OPENCV_HAL_WRAP_BIN_OP_MUL(_Tpvec) \
@@ -45,6 +45,7 @@ OPENCV_HAL_IMPL_RVV_FUN_LOXEI(vuint8m2_t, u8m2, vuint8m2_t, i8)
OPENCV_HAL_IMPL_RVV_FUN_LOXEI(vuint8m4_t, u8m4, vuint8m4_t, i8)
OPENCV_HAL_IMPL_RVV_FUN_LOXEI(vuint8m8_t, u8m8, vuint8m8_t, i8)
OPENCV_HAL_IMPL_RVV_FUN_LOXEI(vfloat32m1_t, f32m1, vuint32m1_t, i32)
OPENCV_HAL_IMPL_RVV_FUN_LOXEI(vuint32m1_t, u32m1, vuint32m1_t, i32)
#if CV_SIMD_SCALABLE_64F
OPENCV_HAL_IMPL_RVV_FUN_LOXEI(vfloat64m1_t, f64m1, vuint32mf2_t, i32)
#endif
@@ -475,6 +475,25 @@ OPENCV_HAL_IMPL_RVV_LUT(v_float32, float, m1)
OPENCV_HAL_IMPL_RVV_LUT(v_float64, double, mf2)
#endif
#define OPENCV_HAL_IMPL_RVV_LUT_VEC(_Tpvec, _Tp) \
inline _Tpvec v_lut(const _Tp* tab, const v_int32& vidx) \
{ \
v_uint32 vidx_ = vmul(vreinterpret_u32m1(vidx), sizeof(_Tp), VTraits<v_int32>::vlanes()); \
return vloxei32(tab, vidx_, VTraits<_Tpvec>::vlanes()); \
}
OPENCV_HAL_IMPL_RVV_LUT_VEC(v_float32, float)
OPENCV_HAL_IMPL_RVV_LUT_VEC(v_int32, int)
OPENCV_HAL_IMPL_RVV_LUT_VEC(v_uint32, unsigned)
#if CV_SIMD_SCALABLE_64F
inline v_float64 v_lut(const double* tab, const v_int32& vidx) \
{ \
vuint32mf2_t vidx_ = vmul(vlmul_trunc_u32mf2(vreinterpret_u32m1(vidx)), sizeof(double), VTraits<v_float64>::vlanes()); \
return vloxei32(tab, vidx_, VTraits<v_float64>::vlanes()); \
}
#endif
inline v_uint8 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); }
inline v_uint8 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
inline v_uint8 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
@@ -690,23 +709,27 @@ inline v_float64 v_not (const v_float64& a) \
////////////// Bitwise shifts //////////////
/* Usage
1. v_shl<N>(vec);
2. v_shl(vec, N); // instead of vec << N, when N is non-constant.
*/
#define OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(_Tpvec, vl) \
template<int n> inline _Tpvec v_shl(const _Tpvec& a) \
template<int s = 0> inline _Tpvec v_shl(const _Tpvec& a, int n = s) \
{ \
return _Tpvec(vsll(a, uint8_t(n), vl)); \
} \
template<int n> inline _Tpvec v_shr(const _Tpvec& a) \
template<int s = 0> inline _Tpvec v_shr(const _Tpvec& a, int n = s) \
{ \
return _Tpvec(vsrl(a, uint8_t(n), vl)); \
}
#define OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(_Tpvec, vl) \
template<int n> inline _Tpvec v_shl(const _Tpvec& a) \
template<int s = 0> inline _Tpvec v_shl(const _Tpvec& a, int n = s) \
{ \
return _Tpvec(vsll(a, uint8_t(n), vl)); \
} \
template<int n> inline _Tpvec v_shr(const _Tpvec& a) \
template<int s = 0> inline _Tpvec v_shr(const _Tpvec& a, int n = s) \
{ \
return _Tpvec(vsra(a, uint8_t(n), vl)); \
}
@@ -8,6 +8,7 @@
#include <limits>
#include <cstring>
#include <algorithm>
#include <emscripten/version.h>
#include "opencv2/core/saturate.hpp"
#define CV_SIMD128 1
+2 -2
View File
@@ -898,14 +898,14 @@ void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
}
dstroi.width *= elemSize;
dst += dststep*top;
for( i = 0; i < top; i++ )
{
j = cv::borderInterpolate(i - top, srcroi.height, borderType);
memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
memcpy(dst + i*dststep, dst + (top+j)*dststep, dstroi.width);
}
dst += dststep*top;
for( i = 0; i < bottom; i++ )
{
j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType);
+1
View File
@@ -66,6 +66,7 @@
#if defined(__clang__) && defined(__has_feature)
#if __has_feature(memory_sanitizer)
#include <sanitizer/msan_interface.h>
#define CV_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
__msan_unpoison(address, size)
#endif
+2 -2
View File
@@ -1158,11 +1158,11 @@ Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
std::swap(col1, col2);
if (dims == 1) {
data += (col1 - ofs.x)*esz;
data += (col1 - ofs.x)*(std::ptrdiff_t)esz;
cols = col2 - col1;
size.p[0] = cols;
} else {
data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
data += (row1 - ofs.y)*(std::ptrdiff_t)step + (col1 - ofs.x)*(std::ptrdiff_t)esz;
rows = row2 - row1; cols = col2 - col1;
size.p[0] = rows; size.p[1] = cols;
updateContinuityFlag();
+4 -1
View File
@@ -580,8 +580,11 @@ void ThreadPool::run(const Range& range, const ParallelLoopBody& body, double ns
pthread_mutex_unlock(&mutex);
CV_LOG_VERBOSE(NULL, 5, "MainThread: wake worker threads...");
for (size_t i = 0; i < threads.size(); ++i)
size_t num_threads_to_wake = std::min(static_cast<size_t>(range.size()), threads.size());
for (size_t i = 0; i < num_threads_to_wake; ++i)
{
if (job->current_task >= job->range.size())
break;
WorkerThread& thread = *(threads[i].get());
if (
#if defined(__clang__) && defined(__has_feature)
+12
View File
@@ -1369,6 +1369,18 @@ TEST(Core_Mat, copyNx1ToVector)
ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_<ushort>(dst16).reshape(1, 5));
}
TEST(Core_Mat, copyMakeBoderUndefinedBehavior)
{
Mat1b src(4, 4), dst;
randu(src, Scalar(10), Scalar(100));
// This could trigger a (signed int)*size_t operation which is undefined behavior.
cv::copyMakeBorder(src, dst, 1, 1, 1, 1, cv::BORDER_REFLECT_101);
EXPECT_EQ(0, cv::norm(src.row(1), dst(Rect(1,0,4,1))));
EXPECT_EQ(0, cv::norm(src.row(2), dst(Rect(1,5,4,1))));
EXPECT_EQ(0, cv::norm(src.col(1), dst(Rect(0,1,1,4))));
EXPECT_EQ(0, cv::norm(src.col(2), dst(Rect(5,1,1,4))));
}
TEST(Core_Matx, fromMat_)
{
Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
+23
View File
@@ -917,5 +917,28 @@ REGISTER_TYPED_TEST_CASE_P(Rect_Test, Overflows);
typedef ::testing::Types<int, float, double> RectTypes;
INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Rect_Test, RectTypes);
// Expected that SkipTestException thrown in the constructor should skip test but not fail
struct TestFixtureSkip: public ::testing::Test {
TestFixtureSkip(bool throwEx = true) {
if (throwEx) {
throw SkipTestException("Skip test at constructor");
}
}
};
TEST_F(TestFixtureSkip, NoBodyRun) {
FAIL() << "Unreachable code called";
}
// Expected that SkipTestException thrown in SetUp method should skip test but not fail
struct TestSetUpSkip: public ::testing::Test {
virtual void SetUp() CV_OVERRIDE {
throw SkipTestException("Skip test at SetUp");
}
};
TEST_F(TestSetUpSkip, NoBodyRun) {
FAIL() << "Unreachable code called";
}
}} // namespace
+9
View File
@@ -1380,6 +1380,15 @@ TEST(MatTestRoi, adjustRoiOverflow)
ASSERT_EQ(roi.rows, m.rows);
}
TEST(MatTestRoi, adjustRoiUndefinedBehavior)
{
Mat m(6, 6, CV_8U);
Mat roi(m, cv::Range(2, 4), cv::Range(2, 4));
// This could trigger a (negative int)*size_t when updating data,
// which is undefined behavior.
roi.adjustROI(2, 2, 2, 2);
EXPECT_EQ(m.data, roi.data);
}
CV_ENUM(SortRowCol, SORT_EVERY_COLUMN, SORT_EVERY_ROW)
CV_ENUM(SortOrder, SORT_ASCENDING, SORT_DESCENDING)