Ask Your Question
1

Write sequence of int with FileStorage in Python

asked 2018-09-19 13:39:43 -0600

a1rb4Ck gravatar image

updated 2018-09-20 06:30:19 -0600

Hello,

I want to write a defaultConfig.xml file using the cv2.FileStorage Python bindings. For now I am using another lib to do the defaultConfig.xml generation because of a limit of the python bindings to write a right <camera_resolution> sequence of integers (defaultConfig.xml example).

I have a simple fix (bellow) and I would like to know if this is the best way to go.

The problem is with the <camera_resolution> integers sequence. I can't manage to write it using the actual python binding, as it is written as an opencv-matrix (Mat). Maybe the problem is that a Python binding must be create specifically for the sequence of integers, like it has be done for the sequence of Strings.

import cv2
fs = cv2.FileStorage('test.xml', cv2.FILE_STORAGE_WRITE)
fs.write("seq_int", [640, 480])
fs.release()

Produce the following problematic test.xml file:

<?xml version="1.0"?>
<opencv_storage>
<seq_int type_id="opencv-matrix">
  <rows>2</rows>
  <cols>1</cols>
  <dt>d</dt>
  <data>
    640. 480.</data></seq_int>
</opencv_storage>

In the last pre-4.0 released there are bindings for sequence of strings but not for sequence of integers. Line 202 in /modules/core/src/persistence_cpp.cpp

void FileStorage::write( const String& name, const std::vector<String>& val )
{
    *this << name << val;
}

I think I will propose as a PR (here is my actual fork) to add sequence of integers support:

void FileStorage::write( const String& name, const std::vector<int>& val )
{
    *this << name << val;
}

With this add, running test like in test_persistence.py

import cv2
fs = cv2.FileStorage('test.xml', cv2.FILE_STORAGE_WRITE)
fs.write("seq_int", [640, 480])
fs.release()

And I get the following good test.xml file:

<?xml version="1.0"?>
<opencv_storage>
<seq_int>
  640 480</seq_int>
</opencv_storage>

Do you thing it is the right way to go ?

I have read the PR discussion about vect strings support but could not find a definitive answer.

Thanks a lot if you take the time to read, and even more if you answer!

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-09-20 01:01:43 -0600

berak gravatar image

updated 2018-09-20 01:49:45 -0600

yea, there is a pitfall with the python FileStorage bindings, it supports only double type for single numbers there (which explains the outcome of your 1st experiment)

but i don't think, the library code needs to be expanded to support vector<int> , this is already handled by the internal vector <--> Mat conversion. (also: what about other types ? reading it back ?)

to work around it, you should pass a numpy array here (which maps to a cv::Mat), not a list:

>>> fs = cv2.FileStorage('test.xml', cv2.FILE_STORAGE_WRITE)
>>> a = np.array([1,2,3,4,5])
>>> fs.write("seq_int", a)
>>> fs.release()
>>> quit()

$ cat test.xml
<?xml version="1.0"?>
<opencv_storage>
<seq_int type_id="opencv-matrix">
  <rows>5</rows>
  <cols>1</cols>
  <dt>i</dt>
  <data>
    1 2 3 4 5</data></seq_int>
</opencv_storage>
edit flag offensive delete link more

Comments

Thanks for the fast answer!

I understand expanding the lib to specific types is not great. To read back vect<int> I use .at().real() then cast to int.

My use case is to write a valid camera_resolution element in defaultConfig.xml. Easy to do in C++. A Mat is not valid.

For now I use cv2.FileStorage and then append <camera_resolution>:

fs = cv2.FileStorage('test.xml', cv2.FILE_STORAGE_WRITE)
fs.release()
seq_int = (640, 480)
f = open('test.xml', 'r+')
ln = f.readline()
while ln != '</opencv_storage>\n':
    ln = f.readline()
f.seek(f.tell() - 18)
f.write('<camera_resolution>\n  %d %d</camera_resolution>\n</opencv_storage>\n')
f.close()
a1rb4Ck gravatar imagea1rb4Ck ( 2018-09-20 06:24:52 -0600 )edit

ah, i see. not what you wanted, then.

berak gravatar imageberak ( 2018-09-20 06:34:49 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-09-19 13:39:43 -0600

Seen: 2,047 times

Last updated: Sep 20 '18