diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index 3f18d54a39..61d1d27fa0 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -944,6 +944,27 @@ void write(FileStorage& fs, const Scalar_<_Tp>& s ) write(fs, s.val[3]); } +static inline +void write(FileStorage& fs, const KeyPoint& kpt ) +{ + write(fs, kpt.pt.x); + write(fs, kpt.pt.y); + write(fs, kpt.size); + write(fs, kpt.angle); + write(fs, kpt.response); + write(fs, kpt.octave); + write(fs, kpt.class_id); +} + +static inline +void write(FileStorage& fs, const DMatch& m ) +{ + write(fs, m.queryIdx); + write(fs, m.trainIdx); + write(fs, m.imgIdx); + write(fs, m.distance); +} + static inline void write(FileStorage& fs, const Range& r ) { @@ -951,6 +972,26 @@ void write(FileStorage& fs, const Range& r ) write(fs, r.end); } +static inline +void write( FileStorage& fs, const std::vector& vec ) +{ + size_t npoints = vec.size(); + for(size_t i = 0; i < npoints; i++ ) + { + write(fs, vec[i]); + } +} + +static inline +void write( FileStorage& fs, const std::vector& vec ) +{ + size_t npoints = vec.size(); + for(size_t i = 0; i < npoints; i++ ) + { + write(fs, vec[i]); + } +} + template static inline void write( FileStorage& fs, const std::vector<_Tp>& vec ) { @@ -1096,6 +1137,24 @@ void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& } } +static inline +void read( const FileNode& node, std::vector& vec, const std::vector& default_value ) +{ + if(!node.node) + vec = default_value; + else + read(node, vec); +} + +static inline +void read( const FileNode& node, std::vector& vec, const std::vector& default_value ) +{ + if(!node.node) + vec = default_value; + else + read(node, vec); +} + //! @} FileNode //! @relates cv::FileStorage diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 946875f5b1..cfe44e8201 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -7283,14 +7283,7 @@ void write(FileStorage& fs, const String& objname, const std::vector& int i, npoints = (int)keypoints.size(); for( i = 0; i < npoints; i++ ) { - const KeyPoint& kpt = keypoints[i]; - cv::write(fs, kpt.pt.x); - cv::write(fs, kpt.pt.y); - cv::write(fs, kpt.size); - cv::write(fs, kpt.angle); - cv::write(fs, kpt.response); - cv::write(fs, kpt.octave); - cv::write(fs, kpt.class_id); + write(fs, keypoints[i]); } } @@ -7315,11 +7308,7 @@ void write(FileStorage& fs, const String& objname, const std::vector& ma int i, n = (int)matches.size(); for( i = 0; i < n; i++ ) { - const DMatch& m = matches[i]; - cv::write(fs, m.queryIdx); - cv::write(fs, m.trainIdx); - cv::write(fs, m.imgIdx); - cv::write(fs, m.distance); + write(fs, matches[i]); } } diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 880d5cb1d8..910d6d43a3 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -1013,3 +1013,74 @@ TEST(Core_InputOutput, filestorage_yaml_advanvced_type_heading) ASSERT_EQ(cv::norm(inputMatrix, actualMatrix, NORM_INF), 0.); } + +TEST(Core_InputOutput, filestorage_keypoints_io) +{ + vector > kptsVec; + vector kpts; + kpts.push_back(KeyPoint(0, 0, 1.1f)); + kpts.push_back(KeyPoint(1, 1, 1.1f)); + kptsVec.push_back(kpts); + kpts.clear(); + kpts.push_back(KeyPoint(0, 0, 1.1f, 10.1f, 34.5f, 10, 11)); + kptsVec.push_back(kpts); + + FileStorage writer("", FileStorage::WRITE + FileStorage::MEMORY + FileStorage::FORMAT_XML); + writer << "keypoints" << kptsVec; + String content = writer.releaseAndGetString(); + + FileStorage reader(content, FileStorage::READ + FileStorage::MEMORY); + vector > readKptsVec; + reader["keypoints"] >> readKptsVec; + + ASSERT_EQ(kptsVec.size(), readKptsVec.size()); + + for(size_t i = 0; i < kptsVec.size(); i++) + { + ASSERT_EQ(kptsVec[i].size(), readKptsVec[i].size()); + for(size_t j = 0; j < kptsVec[i].size(); j++) + { + ASSERT_FLOAT_EQ(kptsVec[i][j].pt.x, readKptsVec[i][j].pt.x); + ASSERT_FLOAT_EQ(kptsVec[i][j].pt.y, readKptsVec[i][j].pt.y); + ASSERT_FLOAT_EQ(kptsVec[i][j].angle, readKptsVec[i][j].angle); + ASSERT_FLOAT_EQ(kptsVec[i][j].size, readKptsVec[i][j].size); + ASSERT_FLOAT_EQ(kptsVec[i][j].response, readKptsVec[i][j].response); + ASSERT_EQ(kptsVec[i][j].octave, readKptsVec[i][j].octave); + ASSERT_EQ(kptsVec[i][j].class_id, readKptsVec[i][j].class_id); + } + } +} + +TEST(Core_InputOutput, filestorage_dmatch_io) +{ + vector > matchesVec; + vector matches; + matches.push_back(DMatch(1, 0, 10, 11.5f)); + matches.push_back(DMatch(2, 1, 11, 21.5f)); + matchesVec.push_back(matches); + matches.clear(); + matches.push_back(DMatch(22, 10, 1, 1.5f)); + matchesVec.push_back(matches); + + FileStorage writer("", FileStorage::WRITE + FileStorage::MEMORY + FileStorage::FORMAT_XML); + writer << "dmatches" << matchesVec; + String content = writer.releaseAndGetString(); + + FileStorage reader(content, FileStorage::READ + FileStorage::MEMORY); + vector > readKptsVec; + reader["dmatches"] >> readKptsVec; + + ASSERT_EQ(matchesVec.size(), readKptsVec.size()); + + for(size_t i = 0; i < matchesVec.size(); i++) + { + ASSERT_EQ(matchesVec[i].size(), readKptsVec[i].size()); + for(size_t j = 0; j < matchesVec[i].size(); j++) + { + ASSERT_FLOAT_EQ(matchesVec[i][j].distance, readKptsVec[i][j].distance); + ASSERT_EQ(matchesVec[i][j].imgIdx, readKptsVec[i][j].imgIdx); + ASSERT_EQ(matchesVec[i][j].queryIdx, readKptsVec[i][j].queryIdx); + ASSERT_EQ(matchesVec[i][j].trainIdx, readKptsVec[i][j].trainIdx); + } + } +}