1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 08:13:04 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2026-05-19 16:23:55 +03:00
160 changed files with 9385 additions and 2093 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ static bool ocl_math_op(InputArray _src1, InputArray _src2, OutputArray _dst, in
Fast cube root by Ken Turkowski
(http://www.worldserver.com/turk/computergraphics/papers.html)
\* ************************************************************************** */
float cubeRoot( float value )
CV_DISABLE_UBSAN float cubeRoot( float value )
{
CV_INSTRUMENT_REGION();
+537 -27
View File
@@ -1160,6 +1160,535 @@ struct NormDiffL2_SIMD<double, double> {
#endif
template <typename T, typename ST>
struct MaskedNormInf_SIMD {
inline ST operator() (const T* src, const uchar* mask, int len, int cn) const {
ST s = 0;
if (cn == 1) {
for (int i = 0; i < len; i++) {
if (mask[i]) {
s = std::max(s, (ST)cv_abs(src[i]));
}
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const T* elem = src + i * cn;
int k = 0;
#if CV_ENABLE_UNROLLED
for (; k <= cn - 4; k += 4) {
s = std::max(s, (ST)cv_abs(elem[k]));
s = std::max(s, (ST)cv_abs(elem[k + 1]));
s = std::max(s, (ST)cv_abs(elem[k + 2]));
s = std::max(s, (ST)cv_abs(elem[k + 3]));
}
#endif
for (; k < cn; k++) {
s = std::max(s, (ST)cv_abs(elem[k]));
}
}
}
}
return s;
}
};
template <typename T, typename ST>
struct MaskedNormL1_SIMD {
inline ST operator() (const T* src, const uchar* mask, int len, int cn) const {
ST s = 0;
if (cn == 1) {
for (int i = 0; i < len; i++) {
if (mask[i]) {
s += (ST)cv_abs(src[i]);
}
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const T* elem = src + i * cn;
int k = 0;
#if CV_ENABLE_UNROLLED
for (; k <= cn - 4; k += 4) {
s += (ST)cv_abs(elem[k]);
s += (ST)cv_abs(elem[k + 1]);
s += (ST)cv_abs(elem[k + 2]);
s += (ST)cv_abs(elem[k + 3]);
}
#endif
for (; k < cn; k++) {
s += (ST)cv_abs(elem[k]);
}
}
}
}
return s;
}
};
template <typename T, typename ST>
struct MaskedNormL2_SIMD {
inline ST operator() (const T* src, const uchar* mask, int len, int cn) const {
ST s = 0;
if (cn == 1) {
int i = 0;
#if CV_ENABLE_UNROLLED
for (; i <= len - 4; i += 4) {
if (mask[i]) { T v0 = src[i]; s += (ST)v0 * v0; }
if (mask[i + 1]) { T v1 = src[i + 1]; s += (ST)v1 * v1; }
if (mask[i + 2]) { T v2 = src[i + 2]; s += (ST)v2 * v2; }
if (mask[i + 3]) { T v3 = src[i + 3]; s += (ST)v3 * v3; }
}
#endif
for (; i < len; i++) {
if (mask[i]) {
T v = src[i];
s += (ST)v * v;
}
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const T* elem = src + i * cn;
int k = 0;
#if CV_ENABLE_UNROLLED
for (; k <= cn - 4; k += 4) {
T v0 = elem[k]; s += (ST)v0 * v0;
T v1 = elem[k + 1]; s += (ST)v1 * v1;
T v2 = elem[k + 2]; s += (ST)v2 * v2;
T v3 = elem[k + 3]; s += (ST)v3 * v3;
}
#endif
for (; k < cn; k++) {
T v = elem[k];
s += (ST)v * v;
}
}
}
}
return s;
}
};
template <>
struct MaskedNormInf_SIMD<float, float> {
inline float operator()(const float* src, const uchar* mask, int len, int cn) const {
float result = 0.0f;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_float32>::vlanes();
v_float32 acc = vx_setzero_f32();
for (; i <= len - vstep; i += vstep) {
v_uint32 m = v_reinterpret_as_u32(vx_load_expand(mask + i));
v_uint32 cmp = v_gt(m, vx_setzero_u32());
v_float32 s = vx_load(src + i);
s = v_abs(s);
s = v_reinterpret_as_f32(v_and(v_reinterpret_as_u32(s), cmp));
acc = v_max(acc, s);
}
result = v_reduce_max(acc);
for (; i < len; i++) {
if (mask[i])
result = std::max(result, std::abs(src[i]));
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const float* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_float32>::vlanes();
v_float32 acc = vx_setzero_f32();
for (; k <= cn - vstep; k += vstep) {
v_float32 s = vx_load(elem + k);
acc = v_max(acc, v_abs(s));
}
result = std::max(result, v_reduce_max(acc));
for (; k < cn; k++)
result = std::max(result, std::abs(elem[k]));
}
}
}
return result;
}
};
#if CV_SIMD_64F
template <>
struct MaskedNormL1_SIMD<float, double> {
inline double operator()(const float* src, const uchar* mask, int len, int cn) const {
double result = 0.0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_float32>::vlanes();
v_float64 acc = vx_setzero_f64();
for (; i <= len - vstep; i += vstep) {
v_uint32 cmp = v_gt(vx_load_expand_q(mask + i), vx_setzero_u32());
v_float32 s = v_reinterpret_as_f32(v_and(v_reinterpret_as_u32(v_abs(vx_load(src + i))), cmp));
acc = v_add(acc, v_cvt_f64(s));
acc = v_add(acc, v_cvt_f64_high(s));
}
result = v_reduce_sum(acc);
for (; i < len; i++) {
if (mask[i])
result += std::abs(src[i]);
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const float* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_float32>::vlanes();
v_float64 acc = vx_setzero_f64();
for (; k <= cn - vstep; k += vstep) {
v_float32 s = v_abs(vx_load(elem + k));
acc = v_add(acc, v_cvt_f64(s));
acc = v_add(acc, v_cvt_f64_high(s));
}
result += v_reduce_sum(acc);
for (; k < cn; k++)
result += std::abs(elem[k]);
}
}
}
return result;
}
};
template <>
struct MaskedNormL2_SIMD<float, double> {
inline double operator()(const float* src, const uchar* mask, int len, int cn) const {
double result = 0.0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_float32>::vlanes();
v_float32 facc = vx_setzero_f32();
v_float64 dacc = vx_setzero_f64();
int flush = 0;
for (; i <= len - vstep; i += vstep, flush += vstep) {
if (flush >= 64) {
dacc = v_add(dacc, v_cvt_f64(facc));
dacc = v_add(dacc, v_cvt_f64_high(facc));
facc = vx_setzero_f32();
flush = 0;
}
v_uint32 cmp = v_gt(vx_load_expand_q(mask + i), vx_setzero_u32());
v_float32 s = v_reinterpret_as_f32(v_and(v_reinterpret_as_u32(vx_load(src + i)), cmp));
facc = v_add(facc, v_mul(s, s));
}
dacc = v_add(dacc, v_cvt_f64(facc));
dacc = v_add(dacc, v_cvt_f64_high(facc));
result = v_reduce_sum(dacc);
for (; i < len; i++) {
if (mask[i]) {
double v = src[i];
result += v * v;
}
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const float* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_float32>::vlanes();
v_float32 facc = vx_setzero_f32();
for (; k <= cn - vstep; k += vstep) {
v_float32 s = vx_load(elem + k);
facc = v_add(facc, v_mul(s, s));
}
v_float64 dacc = v_add(v_cvt_f64(facc), v_cvt_f64_high(facc));
result += v_reduce_sum(dacc);
for (; k < cn; k++) {
double v = elem[k];
result += v * v;
}
}
}
}
return result;
}
};
#endif
template <>
struct MaskedNormInf_SIMD<uchar, int> {
inline int operator()(const uchar* src, const uchar* mask, int len, int cn) const {
int result = 0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_uint8>::vlanes();
v_uint8 acc = vx_setzero_u8();
for (; i <= len - vstep; i += vstep) {
v_uint8 m = vx_load(mask + i);
v_uint8 s = vx_load(src + i);
v_uint8 sel = v_and(s, v_gt(m, vx_setzero_u8()));
acc = v_max(acc, sel);
}
result = (int)v_reduce_max(acc);
for (; i < len; i++) {
if (mask[i])
result = std::max(result, (int)src[i]);
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const uchar* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_uint8>::vlanes();
v_uint8 acc = vx_setzero_u8();
for (; k <= cn - vstep; k += vstep) {
acc = v_max(acc, vx_load(elem + k));
}
result = std::max(result, (int)v_reduce_max(acc));
for (; k < cn; k++)
result = std::max(result, (int)elem[k]);
}
}
}
return result;
}
};
template <>
struct MaskedNormL1_SIMD<uchar, int> {
inline int operator()(const uchar* src, const uchar* mask, int len, int cn) const {
int result = 0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_uint8>::vlanes() / 4;
v_uint32 acc = vx_setzero_u32();
for (; i <= len - vstep; i += vstep) {
v_uint32 m = vx_load_expand_q(mask + i);
v_uint32 s = vx_load_expand_q(src + i);
v_uint32 sel = v_and(s, v_gt(m, vx_setzero_u32()));
acc = v_add(acc, sel);
}
result = (int)v_reduce_sum(acc);
for (; i < len; i++) {
if (mask[i])
result += src[i];
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const uchar* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_uint8>::vlanes() / 4;
v_uint32 acc = vx_setzero_u32();
for (; k <= cn - vstep; k += vstep) {
v_uint32 s = vx_load_expand_q(elem + k);
acc = v_add(acc, s);
}
result += (int)v_reduce_sum(acc);
for (; k < cn; k++)
result += elem[k];
}
}
}
return result;
}
};
template <>
struct MaskedNormInf_SIMD<ushort, int> {
inline int operator()(const ushort* src, const uchar* mask, int len, int cn) const {
int result = 0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_uint16>::vlanes();
v_uint16 acc = vx_setzero_u16();
for (; i <= len - vstep; i += vstep) {
v_uint16 m = vx_load_expand(mask + i);
v_uint16 cmp = v_gt(m, vx_setzero_u16());
v_uint16 s = vx_load(src + i);
v_uint16 sel = v_and(s, cmp);
acc = v_max(acc, sel);
}
result = (int)v_reduce_max(acc);
for (; i < len; i++) {
if (mask[i])
result = std::max(result, (int)src[i]);
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const ushort* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_uint16>::vlanes();
v_uint16 acc = vx_setzero_u16();
for (; k <= cn - vstep; k += vstep) {
acc = v_max(acc, vx_load(elem + k));
}
result = std::max(result, (int)v_reduce_max(acc));
for (; k < cn; k++)
result = std::max(result, (int)elem[k]);
}
}
}
return result;
}
};
template <>
struct MaskedNormL1_SIMD<ushort, int> {
inline int operator()(const ushort* src, const uchar* mask, int len, int cn) const {
int result = 0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_uint16>::vlanes();
v_uint32 acc32 = vx_setzero_u32();
v_uint64 acc64 = vx_setzero_u64();
int acc32_elems = 0;
for (; i <= len - vstep; i += vstep, acc32_elems += vstep) {
if (acc32_elems >= 512) {
v_uint64 lo64, hi64;
v_expand(acc32, lo64, hi64);
acc64 = v_add(acc64, v_add(lo64, hi64));
acc32 = vx_setzero_u32();
acc32_elems = 0;
}
v_uint16 m = vx_load_expand(mask + i);
v_uint16 cmp = v_gt(m, vx_setzero_u16());
v_uint16 s = v_and(vx_load(src + i), cmp);
v_uint32 lo32, hi32;
v_expand(s, lo32, hi32);
acc32 = v_add(acc32, v_add(lo32, hi32));
}
v_uint64 lo64, hi64;
v_expand(acc32, lo64, hi64);
acc64 = v_add(acc64, v_add(lo64, hi64));
result = (int)v_reduce_sum(acc64);
for (; i < len; i++) {
if (mask[i])
result += src[i];
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const ushort* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_uint16>::vlanes();
v_uint32 acc = vx_setzero_u32();
for (; k <= cn - vstep; k += vstep) {
v_uint32 lo32, hi32;
v_expand(vx_load(elem + k), lo32, hi32);
acc = v_add(acc, v_add(lo32, hi32));
}
result += (int)v_reduce_sum(acc);
for (; k < cn; k++)
result += elem[k];
}
}
}
return result;
}
};
template <>
struct MaskedNormL2_SIMD<ushort, double> {
inline double operator()(const ushort* src, const uchar* mask, int len, int cn) const {
double result = 0.0;
if (cn == 1) {
int i = 0;
const int vstep = VTraits<v_uint16>::vlanes();
v_uint64 acc = vx_setzero_u64();
for (; i <= len - vstep; i += vstep) {
v_uint16 m = vx_load_expand(mask + i);
v_uint16 cmp = v_gt(m, vx_setzero_u16());
v_uint16 s = v_and(vx_load(src + i), cmp);
v_uint32 lo32, hi32;
v_expand(s, lo32, hi32);
v_uint64 lo64a, lo64b, hi64a, hi64b;
v_expand(v_mul(lo32, lo32), lo64a, lo64b);
v_expand(v_mul(hi32, hi32), hi64a, hi64b);
acc = v_add(acc, v_add(v_add(lo64a, lo64b), v_add(hi64a, hi64b)));
}
result = (double)v_reduce_sum(acc);
for (; i < len; i++) {
if (mask[i]) {
double v = src[i];
result += v * v;
}
}
}
else {
for (int i = 0; i < len; i++) {
if (mask[i]) {
const ushort* elem = src + i * cn;
int k = 0;
const int vstep = VTraits<v_uint16>::vlanes();
v_uint64 acc = vx_setzero_u64();
for (; k <= cn - vstep; k += vstep) {
v_uint32 lo32, hi32;
v_expand(vx_load(elem + k), lo32, hi32);
v_uint64 lo64a, lo64b, hi64a, hi64b;
v_expand(v_mul(lo32, lo32), lo64a, lo64b);
v_expand(v_mul(hi32, hi32), hi64a, hi64b);
acc = v_add(acc, v_add(v_add(lo64a, lo64b), v_add(hi64a, hi64b)));
}
result += (double)v_reduce_sum(acc);
for (; k < cn; k++) {
double v = elem[k];
result += v * v;
}
}
}
}
return result;
}
};
template<typename T, typename ST> int
normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
{
@@ -1168,15 +1697,9 @@ normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
{
NormInf_SIMD<T, ST> op;
result = std::max(result, op(src, len*cn));
}
else
{
for( int i = 0; i < len; i++, src += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
result = std::max(result, (ST)cv_abs(src[k]));
}
} else {
MaskedNormInf_SIMD<T, ST> op;
result = std::max(result, op(src, mask, len, cn));
}
*_result = result;
return 0;
@@ -1190,15 +1713,9 @@ normL1_(const T* src, const uchar* mask, ST* _result, int len, int cn)
{
NormL1_SIMD<T, ST> op;
result += op(src, len*cn);
}
else
{
for( int i = 0; i < len; i++, src += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
result += cv_abs(src[k]);
}
} else {
MaskedNormL1_SIMD<T, ST> op;
result += op(src, mask, len, cn);
}
*_result = result;
return 0;
@@ -1215,15 +1732,8 @@ normL2_(const T* src, const uchar* mask, ST* _result, int len, int cn)
}
else
{
for( int i = 0; i < len; i++, src += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
{
ST v = (ST)src[k];
result += v*v;
}
}
MaskedNormL2_SIMD<T, ST> op;
result += op(src, mask, len, cn);
}
*_result = result;
return 0;
+44
View File
@@ -98,6 +98,50 @@ __kernel void copyToMask(__global const uchar * srcptr, int src_step, int src_of
}
}
#elif defined(SET_DIAG)
#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#endif
__kernel void setDiag(__global uchar* dst, int dst_step, int dst_offset,
int dst_rows, int dst_cols,
__global const uchar* src, int src_step, int src_offset,
int len)
{
int x = get_global_id(0);
int y = get_global_id(1);
if (x < dst_cols && y < dst_rows)
{
int elem_size = (int)sizeof(T1) * cn;
int dst_idx = mad24(y, dst_step, mad24(x, elem_size, dst_offset));
if (x == y && x < len)
{
#if IS_ROW_VECTOR
int src_idx = src_offset + x * elem_size;
#else
int src_idx = mad24(x, src_step, src_offset);
#endif
__global T1* dst_ptr = (__global T1*)(dst + dst_idx);
__global const T1* src_ptr = (__global const T1*)(src + src_idx);
#pragma unroll
for (int c = 0; c < cn; ++c)
dst_ptr[c] = src_ptr[c];
}
else
{
__global T1* dst_ptr = (__global T1*)(dst + dst_idx);
#pragma unroll
for (int c = 0; c < cn; ++c)
dst_ptr[c] = (T1)0;
}
}
}
#else
#ifndef dstST
+24 -10
View File
@@ -529,7 +529,6 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
bool write_base64 = (write_mode || append) && (_flags & FileStorage::BASE64) != 0;
bool isGZ = false;
size_t fnamelen = 0;
std::vector<std::string> params;
//if ( !mem_mode )
@@ -552,18 +551,30 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
flags = _flags;
if (!mem_mode) {
char *dot_pos = strrchr((char *) filename.c_str(), '.');
size_t dot_idx = filename.find_last_of('.');
char compression = '\0';
if (dot_pos && dot_pos[1] == 'g' && dot_pos[2] == 'z' &&
(dot_pos[3] == '\0' || (cv_isdigit(dot_pos[3]) && dot_pos[4] == '\0'))) {
if (append) {
CV_Error(cv::Error::StsNotImplemented, "Appending data to compressed file is not implemented");
if (dot_idx != std::string::npos)
{
std::string ext = filename.substr(dot_idx);
// Instead of `ext.starts_with(".gz")
if (ext.size() >= 3 && (ext[1] == 'g') && (ext[2] == 'z') )
{
if (ext.size() == 3)
{
// ".gz"
isGZ = true;
}
else if(ext.size() == 4 && cv_isdigit(ext[3]))
{
// ".gz[0-9]"
isGZ = true;
compression = ext[3];
filename.pop_back(); // Replace `gz[0-9]' to 'gz'.
}
}
isGZ = true;
compression = dot_pos[3];
if (compression)
dot_pos[3] = '\0', fnamelen--;
}
if (!isGZ) {
@@ -575,6 +586,9 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
}
} else {
#if USE_ZLIB
if (append) {
CV_Error(cv::Error::StsNotImplemented, "Appending data to compressed file is not implemented");
}
char mode[] = {write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0'};
gzfile = gzopen(filename.c_str(), mode);
if (!gzfile)
+45 -1
View File
@@ -1029,10 +1029,54 @@ UMat UMat::reshape(int new_cn, int new_rows) const
return hdr;
}
#ifdef HAVE_OPENCL
namespace {
static bool ocl_setDiag(const UMat& d, UMat& m, int len)
{
int cn = d.channels();
int depth = d.depth();
if (depth == CV_64F && !ocl::Device::getDefault().doubleFPConfig())
return false;
String opts = format("-D SET_DIAG -D T1=%s -D cn=%d -D IS_ROW_VECTOR=%d",
ocl::memopTypeToStr(depth),
cn,
(d.rows == 1) ? 1 : 0);
ocl::Kernel k("setDiag", ocl::core::copyset_oclsrc, opts);
if (k.empty())
return false;
k.args(ocl::KernelArg::WriteOnly(m),
ocl::KernelArg::ReadOnlyNoSize(d),
len);
size_t globalsize[2] = { (size_t)len, (size_t)len };
return k.run(2, globalsize, NULL, false);
}
}
#endif
UMat UMat::diag(const UMat& d, UMatUsageFlags usageFlags)
{
CV_Assert( d.cols == 1 || d.rows == 1 );
CV_INSTRUMENT_REGION();
CV_Assert(d.cols == 1 || d.rows == 1);
int len = d.rows + d.cols - 1;
#ifdef HAVE_OPENCL
if (ocl::useOpenCL())
{
UMat m(len, len, d.type(), usageFlags);
if (ocl_setDiag(d, m, len))
{
CV_IMPL_ADD(CV_IMPL_OCL);
return m;
}
}
#endif
UMat m(len, len, d.type(), Scalar(0), usageFlags);
UMat md = m.diag();
if( d.cols == 1 )