Merge pull request #25351 from Kumataro:fix25073_format_g

core: persistence: output reals as human-friendly expression. #25351

Close #25073
Related https://github.com/opencv/opencv/pull/25087

This patch is need to merge same time with https://github.com/opencv/opencv_contrib/pull/3714

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
pull/25391/head
Kumataro 1 year ago committed by GitHub
parent cf3a130be6
commit b14ea19466
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 22
      modules/core/src/persistence.cpp
  2. 96
      modules/core/test/test_io.cpp
  3. 2
      modules/features2d/misc/java/test/AKAZEDescriptorExtractorTest.java
  4. 2
      modules/features2d/misc/java/test/GFTTFeatureDetectorTest.java
  5. 2
      modules/features2d/misc/java/test/KAZEDescriptorExtractorTest.java
  6. 2
      modules/features2d/misc/java/test/MSERFeatureDetectorTest.java
  7. 2
      modules/features2d/misc/java/test/ORBDescriptorExtractorTest.java
  8. 2
      modules/features2d/misc/java/test/SIFTDescriptorExtractorTest.java
  9. 3
      modules/features2d/misc/java/test/SIMPLEBLOBFeatureDetectorTest.java

@ -76,9 +76,11 @@ char* doubleToString( char* buf, size_t bufSize, double value, bool explicitZero
}
else
{
static const char* fmt = "%.16e";
// binary64 has 52 bit fraction with hidden bit.
// 53 * log_10(2) is 15.955. So "%.16f" should be fine, but its test fails.
snprintf( buf, bufSize, "%.17g", value );
char* ptr = buf;
snprintf( buf, bufSize, fmt, value );
if( *ptr == '+' || *ptr == '-' )
ptr++;
for( ; cv_isdigit(*ptr); ptr++ )
@ -118,11 +120,21 @@ char* floatToString( char* buf, size_t bufSize, float value, bool halfprecision,
}
else
{
char* ptr = buf;
if (halfprecision)
snprintf(buf, bufSize, "%.4e", value);
{
// bfloat16 has 7 bit fraction with hidden bit.
// binary16 has 10 bit fraction with hidden bit.
// 11 * log_10(2) is 3.311. So "%.4f" should be fine, but its test fails.
snprintf(buf, bufSize, "%.5g", value);
}
else
snprintf(buf, bufSize, "%.8e", value);
{
// binray32 has 23 bit fraction with hidden bit.
// 24 * log_10(2) is 7.225. So "%.8f" should be fine, but its test fails.
snprintf(buf, bufSize, "%.9g", value);
}
char* ptr = buf;
if( *ptr == '+' || *ptr == '-' )
ptr++;
for( ; cv_isdigit(*ptr); ptr++ )

@ -1189,11 +1189,7 @@ TEST(Core_InputOutput, FileStorage_DMatch)
EXPECT_NO_THROW(fs << "d" << d);
cv::String fs_result = fs.releaseAndGetString();
#if defined _MSC_VER && _MSC_VER <= 1800 /* MSVC 2013 and older */
EXPECT_STREQ(fs_result.c_str(), "%YAML:1.0\n---\nd: [ 1, 2, 3, -1.5000000000000000e+000 ]\n");
#else
EXPECT_STREQ(fs_result.c_str(), "%YAML:1.0\n---\nd: [ 1, 2, 3, -1.5000000000000000e+00 ]\n");
#endif
EXPECT_STREQ(fs_result.c_str(), "%YAML:1.0\n---\nd: [ 1, 2, 3, -1.5 ]\n");
cv::FileStorage fs_read(fs_result, cv::FileStorage::READ | cv::FileStorage::MEMORY);
@ -1220,25 +1216,14 @@ TEST(Core_InputOutput, FileStorage_DMatch_vector)
EXPECT_NO_THROW(fs << "dv" << dv);
cv::String fs_result = fs.releaseAndGetString();
#if defined _MSC_VER && _MSC_VER <= 1800 /* MSVC 2013 and older */
EXPECT_STREQ(fs_result.c_str(),
"%YAML:1.0\n"
"---\n"
"dv:\n"
" - [ 1, 2, 3, -1.5000000000000000e+000 ]\n"
" - [ 2, 3, 4, 1.5000000000000000e+000 ]\n"
" - [ 3, 2, 1, 5.0000000000000000e-001 ]\n"
);
#else
EXPECT_STREQ(fs_result.c_str(),
"%YAML:1.0\n"
"---\n"
"dv:\n"
" - [ 1, 2, 3, -1.5000000000000000e+00 ]\n"
" - [ 2, 3, 4, 1.5000000000000000e+00 ]\n"
" - [ 3, 2, 1, 5.0000000000000000e-01 ]\n"
" - [ 1, 2, 3, -1.5 ]\n"
" - [ 2, 3, 4, 1.5 ]\n"
" - [ 3, 2, 1, 0.5 ]\n"
);
#endif
cv::FileStorage fs_read(fs_result, cv::FileStorage::READ | cv::FileStorage::MEMORY);
@ -1278,33 +1263,18 @@ TEST(Core_InputOutput, FileStorage_DMatch_vector_vector)
EXPECT_NO_THROW(fs << "dvv" << dvv);
cv::String fs_result = fs.releaseAndGetString();
#ifndef OPENCV_TRAITS_ENABLE_DEPRECATED
#if defined _MSC_VER && _MSC_VER <= 1800 /* MSVC 2013 and older */
EXPECT_STREQ(fs_result.c_str(),
"%YAML:1.0\n"
"---\n"
"dvv:\n"
" -\n"
" - [ 1, 2, 3, -1.5000000000000000e+000 ]\n"
" - [ 2, 3, 4, 1.5000000000000000e+000 ]\n"
" - [ 3, 2, 1, 5.0000000000000000e-001 ]\n"
" -\n"
" - [ 3, 2, 1, 5.0000000000000000e-001 ]\n"
" - [ 1, 2, 3, -1.5000000000000000e+000 ]\n"
);
#else
EXPECT_STREQ(fs_result.c_str(),
"%YAML:1.0\n"
"---\n"
"dvv:\n"
" -\n"
" - [ 1, 2, 3, -1.5000000000000000e+00 ]\n"
" - [ 2, 3, 4, 1.5000000000000000e+00 ]\n"
" - [ 3, 2, 1, 5.0000000000000000e-01 ]\n"
" - [ 1, 2, 3, -1.5 ]\n"
" - [ 2, 3, 4, 1.5 ]\n"
" - [ 3, 2, 1, 0.5 ]\n"
" -\n"
" - [ 3, 2, 1, 5.0000000000000000e-01 ]\n"
" - [ 1, 2, 3, -1.5000000000000000e+00 ]\n"
" - [ 3, 2, 1, 0.5 ]\n"
" - [ 1, 2, 3, -1.5 ]\n"
);
#endif
#endif // OPENCV_TRAITS_ENABLE_DEPRECATED
cv::FileStorage fs_read(fs_result, cv::FileStorage::READ | cv::FileStorage::MEMORY);
@ -1966,5 +1936,53 @@ TEST(Core_InputOutput, FileStorage_invalid_path_regression_21448_JSON)
fs.release();
}
// see https://github.com/opencv/opencv/issues/25073
typedef testing::TestWithParam< std::string > Core_InputOutput_regression_25073;
TEST_P(Core_InputOutput_regression_25073, my_double)
{
cv::String res = "";
double my_double = 0.5;
FileStorage fs( GetParam(), cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
EXPECT_NO_THROW( fs << "my_double" << my_double );
EXPECT_NO_THROW( fs << "my_int" << 5 );
EXPECT_NO_THROW( res = fs.releaseAndGetString() );
EXPECT_NE( res.find("0.5"), String::npos ) << res; // Found "0.5"
EXPECT_EQ( res.find("5.0"), String::npos ) << res; // Not Found "5.000000000000000000e-01"
fs.release();
}
TEST_P(Core_InputOutput_regression_25073, my_float)
{
cv::String res = "";
float my_float = 0.5;
FileStorage fs( GetParam(), cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
EXPECT_NO_THROW( fs << "my_float" << my_float );
EXPECT_NO_THROW( fs << "my_int" << 5 );
EXPECT_NO_THROW( res = fs.releaseAndGetString() );
EXPECT_NE( res.find("0.5"), String::npos ) << res; // Found "0.5"
EXPECT_EQ( res.find("5.0"), String::npos ) << res; // Not Found "5.00000000e-01",
fs.release();
}
TEST_P(Core_InputOutput_regression_25073, my_float16)
{
cv::String res = "";
cv::float16_t my_float16(0.5);
FileStorage fs( GetParam(), cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
EXPECT_NO_THROW( fs << "my_float16" << my_float16 );
EXPECT_NO_THROW( fs << "my_int" << 5 );
EXPECT_NO_THROW( res = fs.releaseAndGetString() );
EXPECT_NE( res.find("0.5"), String::npos ) << res; // Found "0.5".
EXPECT_EQ( res.find("5.0"), String::npos ) << res; // Not Found "5.0000e-01".
fs.release();
}
INSTANTIATE_TEST_CASE_P( /*nothing*/,
Core_InputOutput_regression_25073,
Values("test.json", "test.xml", "test.yml") );
}} // namespace

@ -58,7 +58,7 @@ public class AKAZEDescriptorExtractorTest extends OpenCVTestCase {
extractor.write(filename);
String truth = "%YAML:1.0\n---\nformat: 3\nname: \"Feature2D.AKAZE\"\ndescriptor: 5\ndescriptor_channels: 3\ndescriptor_size: 0\nthreshold: 1.0000000474974513e-03\noctaves: 4\nsublevels: 4\ndiffusivity: 1\nmax_points: -1\n";
String truth = "%YAML:1.0\n---\nformat: 3\nname: \"Feature2D.AKAZE\"\ndescriptor: 5\ndescriptor_channels: 3\ndescriptor_size: 0\nthreshold: 0.0010000000474974513\noctaves: 4\nsublevels: 4\ndiffusivity: 1\nmax_points: -1\n";
String actual = readFile(filename);
actual = actual.replaceAll("e([+-])0(\\d\\d)", "e$1$2"); // NOTE: workaround for different platforms double representation
assertEquals(truth, actual);

@ -58,7 +58,7 @@ public class GFTTFeatureDetectorTest extends OpenCVTestCase {
detector.write(filename);
String truth = "%YAML:1.0\n---\nname: \"Feature2D.GFTTDetector\"\nnfeatures: 1000\nqualityLevel: 1.0000000000000000e-02\nminDistance: 1.\nblockSize: 3\ngradSize: 3\nuseHarrisDetector: 0\nk: 4.0000000000000001e-02\n";
String truth = "%YAML:1.0\n---\nname: \"Feature2D.GFTTDetector\"\nnfeatures: 1000\nqualityLevel: 0.01\nminDistance: 1.\nblockSize: 3\ngradSize: 3\nuseHarrisDetector: 0\nk: 0.040000000000000001\n";
String actual = readFile(filename);
actual = actual.replaceAll("e([+-])0(\\d\\d)", "e$1$2"); // NOTE: workaround for different platforms double representation
assertEquals(truth, actual);

@ -57,7 +57,7 @@ public class KAZEDescriptorExtractorTest extends OpenCVTestCase {
extractor.write(filename);
String truth = "%YAML:1.0\n---\nformat: 3\nname: \"Feature2D.KAZE\"\nextended: 0\nupright: 0\nthreshold: 1.0000000474974513e-03\noctaves: 4\nsublevels: 4\ndiffusivity: 1\n";
String truth = "%YAML:1.0\n---\nformat: 3\nname: \"Feature2D.KAZE\"\nextended: 0\nupright: 0\nthreshold: 0.0010000000474974513\noctaves: 4\nsublevels: 4\ndiffusivity: 1\n";
String actual = readFile(filename);
actual = actual.replaceAll("e([+-])0(\\d\\d)", "e$1$2"); // NOTE: workaround for different platforms double representation
assertEquals(truth, actual);

@ -61,7 +61,7 @@ public class MSERFeatureDetectorTest extends OpenCVTestCase {
detector.write(filename);
String truth = "%YAML:1.0\n---\nname: \"Feature2D.MSER\"\ndelta: 5\nminArea: 60\nmaxArea: 14400\nmaxVariation: 2.5000000000000000e-01\nminDiversity: 2.0000000000000001e-01\nmaxEvolution: 200\nareaThreshold: 1.0100000000000000e+00\nminMargin: 3.0000000000000001e-03\nedgeBlurSize: 5\npass2Only: 0\n";
String truth = "%YAML:1.0\n---\nname: \"Feature2D.MSER\"\ndelta: 5\nminArea: 60\nmaxArea: 14400\nmaxVariation: 0.25\nminDiversity: 0.20000000000000001\nmaxEvolution: 200\nareaThreshold: 1.01\nminMargin: 0.0030000000000000001\nedgeBlurSize: 5\npass2Only: 0\n";
String actual = readFile(filename);
actual = actual.replaceAll("e([+-])0(\\d\\d)", "e$1$2"); // NOTE: workaround for different platforms double representation
assertEquals(truth, actual);

@ -111,7 +111,7 @@ public class ORBDescriptorExtractorTest extends OpenCVTestCase {
extractor.write(filename);
String truth = "%YAML:1.0\n---\nname: \"Feature2D.ORB\"\nnfeatures: 500\nscaleFactor: 1.2000000476837158e+00\nnlevels: 8\nedgeThreshold: 31\nfirstLevel: 0\nwta_k: 2\nscoreType: 0\npatchSize: 31\nfastThreshold: 20\n";
String truth = "%YAML:1.0\n---\nname: \"Feature2D.ORB\"\nnfeatures: 500\nscaleFactor: 1.2000000476837158\nnlevels: 8\nedgeThreshold: 31\nfirstLevel: 0\nwta_k: 2\nscoreType: 0\npatchSize: 31\nfastThreshold: 20\n";
// String truth = "%YAML:1.0\n---\n";
String actual = readFile(filename);
actual = actual.replaceAll("e\\+000", "e+00"); // NOTE: workaround for different platforms double representation

@ -100,7 +100,7 @@ public class SIFTDescriptorExtractorTest extends OpenCVTestCase {
extractor.write(filename);
String truth = "%YAML:1.0\n---\nname: \"Feature2D.SIFT\"\nnfeatures: 0\nnOctaveLayers: 3\ncontrastThreshold: 4.0000000000000001e-02\nedgeThreshold: 10.\nsigma: 1.6000000000000001e+00\ndescriptorType: 5\n";
String truth = "%YAML:1.0\n---\nname: \"Feature2D.SIFT\"\nnfeatures: 0\nnOctaveLayers: 3\ncontrastThreshold: 0.040000000000000001\nedgeThreshold: 10.\nsigma: 1.6000000000000001\ndescriptorType: 5\n";
String actual = readFile(filename);
actual = actual.replaceAll("e([+-])0(\\d\\d)", "e$1$2"); // NOTE: workaround for different platforms double representation
assertEquals(truth, actual);

@ -133,8 +133,7 @@ public class SIMPLEBLOBFeatureDetectorTest extends OpenCVTestCase {
String filename = OpenCVTestRunner.getTempFileName("xml");
detector.write(filename);
String truth = "<?xml version=\"1.0\"?>\n<opencv_storage>\n<format>3</format>\n<thresholdStep>10.</thresholdStep>\n<minThreshold>50.</minThreshold>\n<maxThreshold>220.</maxThreshold>\n<minRepeatability>2</minRepeatability>\n<minDistBetweenBlobs>10.</minDistBetweenBlobs>\n<filterByColor>1</filterByColor>\n<blobColor>0</blobColor>\n<filterByArea>1</filterByArea>\n<minArea>25.</minArea>\n<maxArea>5000.</maxArea>\n<filterByCircularity>0</filterByCircularity>\n<minCircularity>8.0000001192092896e-01</minCircularity>\n<maxCircularity>3.4028234663852886e+38</maxCircularity>\n<filterByInertia>1</filterByInertia>\n<minInertiaRatio>1.0000000149011612e-01</minInertiaRatio>\n<maxInertiaRatio>3.4028234663852886e+38</maxInertiaRatio>\n<filterByConvexity>1</filterByConvexity>\n<minConvexity>9.4999998807907104e-01</minConvexity>\n<maxConvexity>3.4028234663852886e+38</maxConvexity>\n<collectContours>0</collectContours>\n</opencv_storage>\n";
String truth = "<?xml version=\"1.0\"?>\n<opencv_storage>\n<format>3</format>\n<thresholdStep>10.</thresholdStep>\n<minThreshold>50.</minThreshold>\n<maxThreshold>220.</maxThreshold>\n<minRepeatability>2</minRepeatability>\n<minDistBetweenBlobs>10.</minDistBetweenBlobs>\n<filterByColor>1</filterByColor>\n<blobColor>0</blobColor>\n<filterByArea>1</filterByArea>\n<minArea>25.</minArea>\n<maxArea>5000.</maxArea>\n<filterByCircularity>0</filterByCircularity>\n<minCircularity>0.80000001192092896</minCircularity>\n<maxCircularity>3.4028234663852886e+38</maxCircularity>\n<filterByInertia>1</filterByInertia>\n<minInertiaRatio>0.10000000149011612</minInertiaRatio>\n<maxInertiaRatio>3.4028234663852886e+38</maxInertiaRatio>\n<filterByConvexity>1</filterByConvexity>\n<minConvexity>0.94999998807907104</minConvexity>\n<maxConvexity>3.4028234663852886e+38</maxConvexity>\n<collectContours>0</collectContours>\n</opencv_storage>\n";
assertEquals(truth, readFile(filename));
}
}

Loading…
Cancel
Save