mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge pull request #28482 from satyam102006:core/yaml-1-2-support
core: add YAML 1.2 support for FileStorage #28482 Fixes: #26363 CI Update: https://github.com/opencv/ci-gha-workflow/pull/306 Summary: - Bool true/false literals support - Header-less YAMLs support for Python YAML module compatibility. Header-less files are parsed as YAMLs by default - Added FORMAT_YAML_1_0 flag to FileStorage for fallback. - New YAML1.2 header Testing: - Added Core_InputOutput.YAML_1_2_Compatibility test case in test_io.cpp. - Added YAML interop test in Python
This commit is contained in:
@@ -273,6 +273,7 @@ public:
|
||||
FORMAT_XML = (1<<3), //!< flag, XML format
|
||||
FORMAT_YAML = (2<<3), //!< flag, YAML format
|
||||
FORMAT_JSON = (3<<3), //!< flag, JSON format
|
||||
FORMAT_YAML_1_0 = (4<<3), //!< flag, Legacy YAML 1.0 format (strict headers, booleans as ints)
|
||||
|
||||
BASE64 = 64, //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64)
|
||||
WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64
|
||||
@@ -365,6 +366,8 @@ public:
|
||||
*/
|
||||
CV_WRAP void write(const String& name, int val);
|
||||
/// @overload
|
||||
CV_WRAP void write(const String& name, bool val);
|
||||
|
||||
CV_WRAP void write(const String& name, int64_t val);
|
||||
/// @overload
|
||||
CV_WRAP void write(const String& name, double val);
|
||||
@@ -658,6 +661,7 @@ protected:
|
||||
/////////////////// XML & YAML I/O implementation //////////////////
|
||||
|
||||
CV_EXPORTS void write( FileStorage& fs, const String& name, int value );
|
||||
CV_EXPORTS void write( FileStorage& fs, const String& name, bool value );
|
||||
CV_EXPORTS void write( FileStorage& fs, const String& name, int64_t value );
|
||||
CV_EXPORTS void write( FileStorage& fs, const String& name, float value );
|
||||
CV_EXPORTS void write( FileStorage& fs, const String& name, double value );
|
||||
|
||||
@@ -695,9 +695,13 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
||||
}
|
||||
|
||||
emitter_do_not_use_direct_dereference = createXMLEmitter(this);
|
||||
} else if (fmt == FileStorage::FORMAT_YAML) {
|
||||
if (!append)
|
||||
puts("%YAML:1.0\n---\n");
|
||||
} else if (fmt == FileStorage::FORMAT_YAML || fmt == FileStorage::FORMAT_YAML_1_0) {
|
||||
if (!append) {
|
||||
if (fmt == FileStorage::FORMAT_YAML_1_0)
|
||||
puts("%YAML:1.0\n---\n"); // Legacy Flag -> Legacy Header
|
||||
else
|
||||
puts("%YAML 1.2\n---\n"); // Default -> Modern Header
|
||||
}
|
||||
else
|
||||
puts("...\n---\n");
|
||||
|
||||
@@ -750,16 +754,15 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
||||
char *bufPtr = cv_skip_BOM(buf);
|
||||
size_t bufOffset = bufPtr - buf;
|
||||
|
||||
// NOTE: Yaml 1.2 allows to skip header. Data without type signature is read as YAML
|
||||
if (strncmp(bufPtr, yaml_signature, strlen(yaml_signature)) == 0)
|
||||
fmt = FileStorage::FORMAT_YAML;
|
||||
else if (strncmp(bufPtr, json_signature, strlen(json_signature)) == 0)
|
||||
fmt = FileStorage::FORMAT_JSON;
|
||||
else if (strncmp(bufPtr, xml_signature, strlen(xml_signature)) == 0)
|
||||
fmt = FileStorage::FORMAT_XML;
|
||||
else if (strbufsize == bufOffset)
|
||||
CV_Error(cv::Error::StsBadArg, "Input file is invalid");
|
||||
else
|
||||
CV_Error(cv::Error::StsBadArg, "Unsupported file storage format");
|
||||
fmt = FileStorage::FORMAT_YAML;
|
||||
|
||||
rewind();
|
||||
strbufpos = bufOffset;
|
||||
@@ -782,6 +785,7 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
||||
parser_do_not_use_direct_dereference = createXMLParser(this);
|
||||
break;
|
||||
case FileStorage::FORMAT_YAML:
|
||||
case FileStorage::FORMAT_YAML_1_0:
|
||||
parser_do_not_use_direct_dereference = createYAMLParser(this);
|
||||
break;
|
||||
case FileStorage::FORMAT_JSON:
|
||||
@@ -2156,7 +2160,13 @@ void write( FileStorage& fs, const String& name, const String& value )
|
||||
fs.p->write(name, value);
|
||||
}
|
||||
|
||||
void write( FileStorage& fs, const String& name, bool value )
|
||||
{
|
||||
fs.p->write(name, value);
|
||||
}
|
||||
|
||||
void FileStorage::write(const String& name, int val) { p->write(name, val); }
|
||||
void FileStorage::write(const String& name, bool val) { p->write(name, val); }
|
||||
void FileStorage::write(const String& name, int64_t val) { p->write(name, val); }
|
||||
void FileStorage::write(const String& name, double val) { p->write(name, val); }
|
||||
void FileStorage::write(const String& name, const String& val) { p->write(name, val); }
|
||||
@@ -2894,6 +2904,21 @@ void read(const FileNode& node, std::string& val, const std::string& default_val
|
||||
val = (std::string)node;
|
||||
}
|
||||
}
|
||||
void FileStorage::Impl::write(const String &key, bool value)
|
||||
{
|
||||
CV_Assert(write_mode);
|
||||
// [SWAP LOGIC]
|
||||
if (fmt == FileStorage::FORMAT_YAML_1_0)
|
||||
{
|
||||
// Legacy behavior: Write as integer 1 or 0
|
||||
getEmitter().write(key.c_str(), (int)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default/Modern behavior: Write as "true" or "false"
|
||||
getEmitter().write(key.c_str(), value ? "true" : "false", false);
|
||||
}
|
||||
}
|
||||
|
||||
FileStorage_API::~FileStorage_API() {}
|
||||
|
||||
|
||||
@@ -137,6 +137,8 @@ public:
|
||||
virtual ~FileStorage_API();
|
||||
virtual FileStorage* getFS() = 0;
|
||||
|
||||
virtual int getFormat() const = 0;
|
||||
|
||||
virtual void puts( const char* str ) = 0;
|
||||
virtual char* gets() = 0;
|
||||
virtual bool eof() = 0;
|
||||
|
||||
@@ -69,6 +69,8 @@ public:
|
||||
|
||||
void write( const String& key, int value );
|
||||
|
||||
void write( const String& key, bool value );
|
||||
|
||||
void write( const String& key, int64_t value );
|
||||
|
||||
void write( const String& key, double value );
|
||||
@@ -97,7 +99,7 @@ public:
|
||||
|
||||
FileNode operator[](const char* /*nodename*/) const;
|
||||
|
||||
int getFormat() const;
|
||||
virtual int getFormat() const CV_OVERRIDE;
|
||||
|
||||
char* bufferPtr() const;
|
||||
char* bufferStart() const;
|
||||
|
||||
@@ -728,10 +728,30 @@ public:
|
||||
if( is_parent_flow || c != ':' )
|
||||
{
|
||||
char* str_end = endptr;
|
||||
// strip spaces in the end of string
|
||||
do c = *--str_end;
|
||||
while( str_end > ptr && c == ' ' );
|
||||
str_end++;
|
||||
if ((fs->getFormat() & FileStorage::FORMAT_MASK) != FileStorage::FORMAT_YAML_1_0)
|
||||
{
|
||||
size_t llen = str_end - ptr;
|
||||
if (llen == 4 && memcmp(ptr, "true", 4) == 0) {
|
||||
int64_t ival = 1;
|
||||
node.setValue(FileNode::INT, &ival);
|
||||
ptr = endptr;
|
||||
return ptr;
|
||||
}
|
||||
else if (llen == 5 && memcmp(ptr, "false", 5) == 0) {
|
||||
int64_t ival = 0;
|
||||
node.setValue(FileNode::INT, &ival);
|
||||
ptr = endptr;
|
||||
return ptr;
|
||||
}
|
||||
else if (llen == 4 && memcmp(ptr, "null", 4) == 0) {
|
||||
ptr = endptr;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
node.setValue(FileNode::STRING, ptr, (int)(str_end - ptr));
|
||||
ptr = endptr;
|
||||
return ptr;
|
||||
@@ -806,7 +826,10 @@ public:
|
||||
if( memcmp( ptr, "%YAML", 5 ) == 0 &&
|
||||
memcmp( ptr, "%YAML:1.", 8 ) != 0 &&
|
||||
memcmp( ptr, "%YAML 1.", 8 ) != 0)
|
||||
CV_PARSE_ERROR_CPP( "Unsupported YAML version (it must be 1.x)" );
|
||||
{
|
||||
if ((fs->getFormat() & FileStorage::FORMAT_MASK) == FileStorage::FORMAT_YAML_1_0)
|
||||
CV_PARSE_ERROR_CPP( "Unsupported YAML version (it must be 1.x)" );
|
||||
}
|
||||
*ptr = '\0';
|
||||
}
|
||||
else if( *ptr == '-' )
|
||||
|
||||
@@ -499,7 +499,7 @@ TEST(Core_InputOutput, FileStorageKey)
|
||||
EXPECT_NO_THROW(f << "key1" << "value1");
|
||||
EXPECT_NO_THROW(f << "_key2" << "value2");
|
||||
EXPECT_NO_THROW(f << "key_3" << "value3");
|
||||
const std::string expected = "%YAML:1.0\n---\nkey1: value1\n_key2: value2\nkey_3: value3\n";
|
||||
const std::string expected = "%YAML 1.2\n---\nkey1: value1\n_key2: value2\nkey_3: value3\n";
|
||||
ASSERT_STREQ(f.releaseAndGetString().c_str(), expected.c_str());
|
||||
}
|
||||
|
||||
@@ -1199,7 +1199,7 @@ TEST(Core_InputOutput, FileStorage_DMatch)
|
||||
|
||||
EXPECT_NO_THROW(fs << "d" << d);
|
||||
cv::String fs_result = fs.releaseAndGetString();
|
||||
EXPECT_STREQ(fs_result.c_str(), "%YAML:1.0\n---\nd: [ 1, 2, 3, -1.5 ]\n");
|
||||
EXPECT_STREQ(fs_result.c_str(), "%YAML 1.2\n---\nd: [ 1, 2, 3, -1.5 ]\n");
|
||||
|
||||
cv::FileStorage fs_read(fs_result, cv::FileStorage::READ | cv::FileStorage::MEMORY);
|
||||
|
||||
@@ -1227,7 +1227,7 @@ TEST(Core_InputOutput, FileStorage_DMatch_vector)
|
||||
EXPECT_NO_THROW(fs << "dv" << dv);
|
||||
cv::String fs_result = fs.releaseAndGetString();
|
||||
EXPECT_STREQ(fs_result.c_str(),
|
||||
"%YAML:1.0\n"
|
||||
"%YAML 1.2\n"
|
||||
"---\n"
|
||||
"dv:\n"
|
||||
" - [ 1, 2, 3, -1.5 ]\n"
|
||||
@@ -1274,7 +1274,7 @@ TEST(Core_InputOutput, FileStorage_DMatch_vector_vector)
|
||||
cv::String fs_result = fs.releaseAndGetString();
|
||||
#ifndef OPENCV_TRAITS_ENABLE_DEPRECATED
|
||||
EXPECT_STREQ(fs_result.c_str(),
|
||||
"%YAML:1.0\n"
|
||||
"%YAML 1.2\n"
|
||||
"---\n"
|
||||
"dvv:\n"
|
||||
" -\n"
|
||||
@@ -2278,4 +2278,50 @@ INSTANTIATE_TEST_CASE_P(Core_InputOutput,
|
||||
FileStorage_exact_type, Values(".yml", ".xml", ".json")
|
||||
);
|
||||
|
||||
TEST(Core_InputOutput, YAML_Compatibility)
|
||||
{
|
||||
string filename = cv::tempfile(".yaml");
|
||||
|
||||
// 1. Write using DEFAULT (should be 1.2 compatible now)
|
||||
{
|
||||
FileStorage fs(filename, FileStorage::WRITE | FileStorage::FORMAT_YAML);
|
||||
ASSERT_TRUE(fs.isOpened());
|
||||
fs << "bool_true" << true;
|
||||
fs << "bool_false" << false;
|
||||
fs.release();
|
||||
}
|
||||
|
||||
// 2. Verify Default is Modern (Literals + No Legacy Header)
|
||||
{
|
||||
std::ifstream file(filename.c_str());
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
std::string content = buffer.str();
|
||||
|
||||
EXPECT_NE(content.find("bool_true: true"), std::string::npos); // Found 'true'
|
||||
EXPECT_EQ(content.find("%YAML:1.0"), std::string::npos); // No 1.0 Header
|
||||
}
|
||||
|
||||
// 3. Write using LEGACY flag
|
||||
{
|
||||
FileStorage fs(filename, FileStorage::WRITE | FileStorage::FORMAT_YAML_1_0);
|
||||
ASSERT_TRUE(fs.isOpened());
|
||||
fs << "bool_true" << true;
|
||||
fs.release();
|
||||
}
|
||||
|
||||
// 4. Verify Legacy (Integers + Strict Header)
|
||||
{
|
||||
std::ifstream file(filename.c_str());
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
std::string content = buffer.str();
|
||||
|
||||
EXPECT_NE(content.find("bool_true: 1"), std::string::npos); // Found '1'
|
||||
EXPECT_NE(content.find("%YAML:1.0"), std::string::npos); // Found 1.0 Header
|
||||
}
|
||||
|
||||
remove(filename.c_str());
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -297,7 +297,7 @@ public class BruteForceDescriptorMatcherTest extends OpenCVTestCase {
|
||||
|
||||
matcher.write(filename);
|
||||
|
||||
String truth = "%YAML:1.0\n---\n";
|
||||
String truth = "%YAML 1.2\n---\n";
|
||||
assertEquals(truth, readFile(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ public class BruteForceHammingDescriptorMatcherTest extends OpenCVTestCase {
|
||||
|
||||
matcher.write(filename);
|
||||
|
||||
String truth = "%YAML:1.0\n---\n";
|
||||
String truth = "%YAML 1.2\n---\n";
|
||||
assertEquals(truth, readFile(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ public class BruteForceHammingLUTDescriptorMatcherTest extends OpenCVTestCase {
|
||||
|
||||
matcher.write(filename);
|
||||
|
||||
String truth = "%YAML:1.0\n---\n";
|
||||
String truth = "%YAML 1.2\n---\n";
|
||||
assertEquals(truth, readFile(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ public class BruteForceL1DescriptorMatcherTest extends OpenCVTestCase {
|
||||
|
||||
matcher.write(filename);
|
||||
|
||||
String truth = "%YAML:1.0\n---\n";
|
||||
String truth = "%YAML 1.2\n---\n";
|
||||
assertEquals(truth, readFile(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ public class BruteForceSL2DescriptorMatcherTest extends OpenCVTestCase {
|
||||
|
||||
matcher.write(filename);
|
||||
|
||||
String truth = "%YAML:1.0\n---\n";
|
||||
String truth = "%YAML 1.2\n---\n";
|
||||
assertEquals(truth, readFile(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ public class FASTFeatureDetectorTest extends OpenCVTestCase {
|
||||
|
||||
detector.write(filename);
|
||||
|
||||
String truth = "%YAML:1.0\n---\nname: \"Feature2D.FastFeatureDetector\"\nthreshold: 10\nnonmaxSuppression: 1\ntype: 2\n";
|
||||
String truth = "%YAML 1.2\n---\nname: \"Feature2D.FastFeatureDetector\"\nthreshold: 10\nnonmaxSuppression: true\ntype: 2\n";
|
||||
String data = readFile(filename);
|
||||
|
||||
assertEquals(truth, data);
|
||||
|
||||
@@ -51,7 +51,7 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
|
||||
+ " <type>8</type>\n" // FLANN_INDEX_TYPE_BOOL
|
||||
+ " <value>1</value></_></searchParams>\n"
|
||||
+ "</opencv_storage>\n";
|
||||
static final String ymlParamsDefault = "%YAML:1.0\n---\n"
|
||||
static final String ymlParamsDefault = "%YAML 1.2\n---\n"
|
||||
+ "format: 3\n"
|
||||
+ "indexParams:\n"
|
||||
+ " -\n"
|
||||
@@ -79,7 +79,7 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
|
||||
+ " name: sorted\n"
|
||||
+ " type: 8\n" // FLANN_INDEX_TYPE_BOOL
|
||||
+ " value: 1\n";
|
||||
static final String ymlParamsModified = "%YAML:1.0\n---\n"
|
||||
static final String ymlParamsModified = "%YAML 1.2\n---\n"
|
||||
+ "format: 3\n"
|
||||
+ "indexParams:\n"
|
||||
+ " -\n"
|
||||
|
||||
@@ -58,7 +58,7 @@ public class GFTTFeatureDetectorTest extends OpenCVTestCase {
|
||||
|
||||
detector.write(filename);
|
||||
|
||||
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 truth = "%YAML 1.2\n---\nname: \"Feature2D.GFTTDetector\"\nnfeatures: 1000\nqualityLevel: 0.01\nminDistance: 1.\nblockSize: 3\ngradSize: 3\nuseHarrisDetector: false\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);
|
||||
|
||||
@@ -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: 0.25\nminDiversity: 0.20000000000000001\nmaxEvolution: 200\nareaThreshold: 1.01\nminMargin: 0.0030000000000000001\nedgeBlurSize: 5\npass2Only: 0\n";
|
||||
String truth = "%YAML 1.2\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: false\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.2000000476837158\nnlevels: 8\nedgeThreshold: 31\nfirstLevel: 0\nwta_k: 2\nscoreType: 0\npatchSize: 31\nfastThreshold: 20\n";
|
||||
String truth = "%YAML 1.2\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: 0.040000000000000001\nedgeThreshold: 10.\nsigma: 1.6000000000000001\ndescriptorType: 5\n";
|
||||
String truth = "%YAML 1.2\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);
|
||||
|
||||
@@ -558,7 +558,7 @@ TEST( Features2d_DMatch, read_write )
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
TEST( Features2d_FlannBasedMatcher, read_write )
|
||||
{
|
||||
static const char* ymlfile = "%YAML:1.0\n---\n"
|
||||
static const char* ymlfile = "%YAML 1.2\n---\n"
|
||||
"format: 3\n"
|
||||
"indexParams:\n"
|
||||
" -\n"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
pyyml
|
||||
numpy
|
||||
@@ -4,7 +4,7 @@ import tempfile
|
||||
import os
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from tests_common import NewOpenCVTests
|
||||
from tests_common import NewOpenCVTests, unittest
|
||||
|
||||
|
||||
class persistence_test(NewOpenCVTests):
|
||||
@@ -42,3 +42,46 @@ class persistence_test(NewOpenCVTests):
|
||||
fs.release()
|
||||
|
||||
os.remove(fname)
|
||||
|
||||
def test_yml_python_interop(self):
|
||||
try:
|
||||
import yaml
|
||||
except:
|
||||
raise unittest.SkipTest('Pyyml is not available for interop test')
|
||||
|
||||
ref_data = {
|
||||
'int_value': 42,
|
||||
"bool_value": True,
|
||||
"float_value": 3.1415926,
|
||||
"int64_value": 2147483647 + 1024, # C++ INT_MAX + 1024
|
||||
"string_value": "opencv"
|
||||
}
|
||||
|
||||
fd, test_file_name = tempfile.mkstemp(prefix="opencv_python_persistence_", suffix=".yml")
|
||||
os.close(fd)
|
||||
|
||||
with open(test_file_name, 'w') as ff:
|
||||
yaml.dump(ref_data, ff)
|
||||
|
||||
# Notice: no cv.FileStorage_FORMAT_YAML flag needed now thanks to the C++ fix!
|
||||
fs = cv.FileStorage(test_file_name, cv.FILE_STORAGE_READ)
|
||||
self.assertTrue(fs.isOpened())
|
||||
|
||||
node = fs.getNode('int_value')
|
||||
self.assertTrue(node.isInt())
|
||||
self.assertEqual(42, int(node.real()))
|
||||
|
||||
node = fs.getNode('int64_value')
|
||||
self.assertTrue(node.isInt())
|
||||
self.assertEqual(2147483647 + 1024, int(node.real()))
|
||||
|
||||
node = fs.getNode('float_value')
|
||||
self.assertTrue(node.isReal())
|
||||
self.assertEqual(3.1415926, node.real())
|
||||
|
||||
node = fs.getNode('string_value')
|
||||
self.assertTrue(node.isString())
|
||||
self.assertEqual("opencv", node.string())
|
||||
|
||||
fs.release()
|
||||
os.remove(test_file_name)
|
||||
|
||||
Reference in New Issue
Block a user