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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user