From 1623576a885d5e75d8731757c8a7f83ffd7ba609 Mon Sep 17 00:00:00 2001 From: MaximSmolskiy Date: Thu, 6 Feb 2025 21:13:34 +0300 Subject: [PATCH] Support 32-bit unsigned type for FileStorage Base64 --- modules/core/src/persistence.cpp | 3 ++ .../core/src/persistence_base64_encoding.cpp | 2 ++ modules/core/test/test_io.cpp | 33 ++++++++++++++++++- modules/python/src2/cv2_convert.cpp | 1 + modules/python/test/test_filestorage_io.py | 7 ++-- 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index a1eeec41ea..8279ab4d26 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -1882,6 +1882,9 @@ char *FileStorage::Impl::parseBase64(char *ptr, int indent, FileNode &collection case CV_16S: ival = (short) base64decoder.getUInt16(); break; + case CV_32U: + ival = base64decoder.getInt32(); + break; case CV_32S: ival = base64decoder.getInt32(); break; diff --git a/modules/core/src/persistence_base64_encoding.cpp b/modules/core/src/persistence_base64_encoding.cpp index a7225c0ded..efb173f80b 100644 --- a/modules/core/src/persistence_base64_encoding.cpp +++ b/modules/core/src/persistence_base64_encoding.cpp @@ -206,6 +206,7 @@ int base64::icvCalcStructSize(const char *dt, int initial_size) { case 'w': { elem_max_size = std::max( elem_max_size, sizeof(ushort) ); break; } case 's': { elem_max_size = std::max( elem_max_size, sizeof(short ) ); break; } case 'i': { elem_max_size = std::max( elem_max_size, sizeof(int ) ); break; } + case 'n': { elem_max_size = std::max( elem_max_size, sizeof(unsigned) ); break; } case 'f': { elem_max_size = std::max( elem_max_size, sizeof(float ) ); break; } case 'd': { elem_max_size = std::max( elem_max_size, sizeof(double) ); break; } case 'I': { elem_max_size = std::max( elem_max_size, sizeof(int64_t)); break; } @@ -337,6 +338,7 @@ size_t base64::RawDataToBinaryConvertor::make_to_binary_funcs(const std::string size = sizeof(ushort); pack.func = to_binary; break; + case 'n': case 'i': size = sizeof(uint); pack.func = to_binary; diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index d6a611dfd1..454b627197 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -602,6 +602,7 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo cv::Mat _em_out, _em_in; cv::Mat _2d_out_u8, _2d_in_u8; + cv::Mat _2d_out_u32, _2d_in_u32; cv::Mat _2d_out_i64, _2d_in_i64; cv::Mat _2d_out_u64, _2d_in_u64; cv::Mat _nd_out, _nd_in; @@ -615,6 +616,12 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo for (int j = 0; j < _2d_out_u8.cols; ++j) _2d_out_u8.at(i, j)[1] = (i + j) % 256; + /* a normal mat u32 */ + _2d_out_u32 = cv::Mat(10, 20, CV_32UC3, cv::Scalar(1U, 2U, 2147483647U)); + for (int i = 0; i < _2d_out_u32.rows; ++i) + for (int j = 0; j < _2d_out_u32.cols; ++j) + _2d_out_u32.at>(i, j)[1] = i + j; + /* a normal mat i64 */ _2d_out_i64 = cv::Mat(10, 20, CV_64SC3, cv::Scalar(1LL, 2LL, 2251799813685247LL)); for (int i = 0; i < _2d_out_i64.rows; ++i) @@ -658,6 +665,7 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo { cv::FileStorage fs(name, write_flags + (useMemory ? cv::FileStorage::MEMORY : 0)); fs << "normal_2d_mat_u8" << _2d_out_u8; + fs << "normal_2d_mat_u32" << _2d_out_u32; fs << "normal_2d_mat_i64" << _2d_out_i64; fs << "normal_2d_mat_u64" << _2d_out_u64; fs << "normal_nd_mat" << _nd_out; @@ -702,7 +710,7 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo } } std::cout << "Storage size: " << sz << std::endl; - EXPECT_LE(sz, (size_t)21000); + EXPECT_LE(sz, (size_t)24000); } { /* read */ cv::FileStorage fs(name, cv::FileStorage::READ + (useMemory ? cv::FileStorage::MEMORY : 0)); @@ -710,6 +718,7 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo /* mat */ fs["empty_2d_mat"] >> _em_in; fs["normal_2d_mat_u8"] >> _2d_in_u8; + fs["normal_2d_mat_u32"] >> _2d_in_u32; fs["normal_2d_mat_i64"] >> _2d_in_i64; fs["normal_2d_mat_u64"] >> _2d_in_u64; fs["normal_nd_mat"] >> _nd_in; @@ -752,6 +761,11 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo ASSERT_EQ(_2d_in_u8.dims , _2d_out_u8.dims); ASSERT_EQ(_2d_in_u8.depth(), _2d_out_u8.depth()); + ASSERT_EQ(_2d_in_u32.rows , _2d_out_u32.rows); + ASSERT_EQ(_2d_in_u32.cols , _2d_out_u32.cols); + ASSERT_EQ(_2d_in_u32.dims , _2d_out_u32.dims); + ASSERT_EQ(_2d_in_u32.depth(), _2d_out_u32.depth()); + ASSERT_EQ(_2d_in_i64.rows , _2d_out_i64.rows); ASSERT_EQ(_2d_in_i64.cols , _2d_out_i64.cols); ASSERT_EQ(_2d_in_i64.dims , _2d_out_i64.dims); @@ -779,6 +793,23 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo } } + errors = 0; + for(int i = 0; i < _2d_out_u32.rows; ++i) + { + for (int j = 0; j < _2d_out_u32.cols; ++j) + { + if (_2d_in_u32.at>(i, j) != _2d_out_u32.at>(i, j)) { + EXPECT_EQ((_2d_in_u32.at>(i, j)), (_2d_out_u32.at>(i, j))); + printf("i = %d, j = %d\n", i, j); + if (++errors >= 3) + { + i = _2d_out_u32.rows; + break; + } + } + } + } + errors = 0; for(int i = 0; i < _2d_out_i64.rows; ++i) { diff --git a/modules/python/src2/cv2_convert.cpp b/modules/python/src2/cv2_convert.cpp index cd1e4a05e9..8ce800d785 100644 --- a/modules/python/src2/cv2_convert.cpp +++ b/modules/python/src2/cv2_convert.cpp @@ -134,6 +134,7 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S : typenum == NPY_INT ? CV_32S : + typenum == NPY_UINT32 ? CV_32U : typenum == NPY_INT32 ? CV_32S : typenum == NPY_HALF ? CV_16F : typenum == NPY_FLOAT ? CV_32F : diff --git a/modules/python/test/test_filestorage_io.py b/modules/python/test/test_filestorage_io.py index 01e0a72300..08e4d4e215 100644 --- a/modules/python/test/test_filestorage_io.py +++ b/modules/python/test/test_filestorage_io.py @@ -119,12 +119,12 @@ class filestorage_io_test(NewOpenCVTests): os.remove(fname) @staticmethod - def get_normal_2d_mat(): + def get_normal_2d_mat(dtype): rows = 10 cols = 20 cn = 3 - image = np.zeros((rows, cols, cn), np.uint8) + image = np.zeros((rows, cols, cn), dtype) image[:] = (1, 2, 127) for i in range(rows): @@ -176,7 +176,8 @@ class filestorage_io_test(NewOpenCVTests): def write_base64_json(self, fname): fs = cv.FileStorage(fname, cv.FileStorage_WRITE_BASE64) - mats = {'normal_2d_mat': self.get_normal_2d_mat(), + mats = {'normal_2d_mat_u8': self.get_normal_2d_mat(np.uint8), + 'normal_2d_mat_u32': self.get_normal_2d_mat(np.uint32), 'normal_nd_mat': self.get_normal_nd_mat(), 'empty_2d_mat': self.get_empty_2d_mat(), 'random_mat': self.get_random_mat()}