lhahn
lhahn

Reputation: 1241

Use path as key in FileStorage

I am trying to write a file (json/yaml/xml, the format does not matter) that stores a filepath with a specific cv::Mat. As I ended up realizing here, the key combination does not allow for a path (/home/user, for example).

void
persist_histograms(const QString& filepath, const QHash<QString, Mat>& histograms)
{
    cv::FileStorage storage(filepath.toStdString(), cv::FileStorage::WRITE);

    QHashIterator<QString, Mat> it(histograms);

    while (it.hasNext()) {
        it.next();
        storage << it.key().toStdString() << it.value();
    }
}

Is this a real limitation of the cv::FileStorageclass? Or is there a way of going around it?

The end result should be something like:

{
    "/my/path/to/file.png": "<my cv::Mat serialization here>",
    "/my/path/to/another/file.png": "<my cv::Mat serialization here>",
    ...
}

Observation

The error occurs independently of the format. If I pass a filepath that ends with either yaml/json/xml the errors are the same: This is the error if a try adding a letter at the beginning of the key:

This is the error I get when trying the code above:

OpenCV Error: Unspecified error (Incorrect element name /home/user/dtd/images/freckled/freckled_0055.jpg) in operator<<, file /build/opencv/src/opencv-3.2.0/modules/core/src/persistence.cpp, line 6877
terminate called after throwing an instance of 'cv::Exception'
what():  /build/opencv/src/opencv 3.2.0/modules/core/src/persistence.cpp:6877: error: (-2) Incorrect element name /home/user/dtd/images/freckled/freckled_0055.jpg in function operator<<

This is the error I get if I try to add a letter to the beginning of the key.

OpenCV Error: Bad argument (Key names may only contain alphanumeric characters [a-zA-Z0-9], '-', '_' and ' ') in icvJSONWrite, file /build/opencv/src/opencv-3.2.0/modules/core/src/persistence.cpp, line 3896

Upvotes: 2

Views: 1386

Answers (1)

John Smith
John Smith

Reputation: 1089

It seems that I have encountered a similar error. If I try to store a matrix in YAML format like this

std::string fName("/path/to/cameraParams.yml");
cv::FileStorage fs(fName, cv::FileStorage::WRITE);
fs << "camera matrix" << cameraMatrix;

everything works fine. But as soon as I change the file format from YAML to XML

std::string fName("/path/to/cameraParams.xml");

I get an error

terminate called after throwing an instance of 'cv::Exception'
what():  OpenCV(4.0.0-pre) /home/shura/software.downloads/libraries/opencv/opencv/modules/core/src/persistence_xml.cpp:83: error: (-5:Bad argument) Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_' in function 'writeTag'

As I have realized, the reason is that XML format does not allow spaces in a tag, while YAML does. So for YAML the file below is completely valid

%YAML:1.0
---
camera matrix: !!opencv-matrix

while for XML something like this is not allowed

<?xml version="1.0"?>
<opencv_storage>
<camera matrix type_id="opencv-matrix">

As soon as I replace the space in "camera matrix" by underscore, everything works fine.

fs << "camera_matrix" << cameraMatrix;

As I have found out here XML format has some restrictions on symbols you can have in a tag name. In particular, slashes, which you have in names, are not allowed. Dots seem to be allowed in tags, but for some reason OpenCV refuses to work with tags, which contain dots.

Upvotes: 1

Related Questions