Ask Your Question
2

make python binder return a list

asked 2018-07-14 11:58:32 -0600

js4267 gravatar image

updated 2018-07-15 10:32:16 -0600

Hello

I made a custom module in c++ in which I have a function that extract a sequence of images (aka a video with a uncommon format, not an image set) from a file. My function is declare as:

CV_EXPORTS_W void read_myJFile(const String& filename, OutputArrayOfArrays img);

And instantiate as:

void read_myJFile(const cv::String &filename, cv::OutputArrayOfArrays img, const int &fmt)
{

    CV_Assert(img.isMat() || img.isMatVector() || img.isUMatVector());

    std::vector<cv::Mat> data;
    std::vector<cv::Mat> dst;

// Here goes the code that  fill data with the content of the file specified.

    if(img.isMat()) // work as long data's size is lower than CV_MAX_CN.
        cv::merge(datas,img);

    img.create(data.size(),1,data.front().type());
    img.assign(data);


}

The compilation work like a charm, how when I try to call it from python I receive that message:

OpenCV(4.0.0-pre) /home/smile/lib_dir/opencv/opencv_400/opencv/modules/core/src/matrix_wrap.cpp:1280: error: (-215:Assertion failed) i < 0 in function 'create'

I investigate a little bit it is because the binder pass a Mat container as second argument of my function. Is there any way to tell the binder that the second argument of my function is std::vector<cv::mat> ? Somehow this case is a little bit like the builtin function cv::split in the sense it does not return a cv::Mat

Otherwise what should I do (write) for make the binder understand ?

Thanks in advance for any help

edit retag flag offensive close merge delete

Comments

hi, nice you finally made it ! (and apologies for being some kind of brutal before, i'm sure , that was just bad luck, or a network hickup)

berak gravatar imageberak ( 2018-07-14 12:06:47 -0600 )edit

I don't want to be impolite but Insult me, and block my account for a mistake is it a bit a lot don't you think ? I taught I was just refreshing the page I did not realize that each time I press F5 my question was resubmit. However I would to get my other account because of the email I am using with this account is temporary, what can I do ? Nevertheless I am happy to work with you.

js4267 gravatar imagejs4267 ( 2018-07-14 12:15:02 -0600 )edit

@js4267, i'm sure you did not intend to sent out 15 indentical posts, yet it happened. and you showed no intent to clean those up, immediately, so some red button pushed here.

(since this site is abused by spammers a lot, there's a moderation queue in place, re-sending it won't do any good, until one of the mods here gives you a green light)

please. let's get over this.you had a bad start, but your question is entirely valid (and even some kind of interesting !)

berak gravatar imageberak ( 2018-07-14 12:20:01 -0600 )edit

If I had figure that out obviously I would have remove all the duplicates I just need one post. Agree with you about the actual question, so there any Keyword or file that I can add in order to make the binder understand the expected type of the second argument of my function ?

js4267 gravatar imagejs4267 ( 2018-07-14 12:25:50 -0600 )edit

Initially In order to prevent a duplication in memory I set the output vector of Mat by doing :

img.create(data.size(),1,data.front().depth());

Where data is and internal vector of Mat and then I just do a for loop with img.getMat(i) = data.at(i);

Seeing that it does not work I take a look to cv::split then I try to preallocate the memory of each image of image by doing: img.create(image_size,image_depth,i); I was thinking that may by doing this the binder would understand that what I return is a list. But nothing change.

js4267 gravatar imagejs4267 ( 2018-07-14 12:48:29 -0600 )edit

btw, can you explain, why this is needed ? (which problem does it solve, exactly ?)

both python and opencv have a glob like function to traverse a diirectory / file list

berak gravatar imageberak ( 2018-07-14 12:55:49 -0600 )edit

:( I have several files that containt a video streams using a particular format (I am working with infrared images) I want to load those files (the function we are discussing about have this purpose) then make a processing and save each stream image per image in a directory. glob like function only list files and subdirectories, recursively or not depending of the arguments.

js4267 gravatar imagejs4267 ( 2018-07-14 13:35:51 -0600 )edit

I just in python to preset a list and send it as second argument of the function without success. Basically what I am looking for is a kind behaviour of cv::split in python concerning the ability to return a list (or even a tuple) of arguments.

js4267 gravatar imagejs4267 ( 2018-07-14 13:45:10 -0600 )edit

Does the native modules (core, imgproc,...) function and classes procces by the binder ?

js4267 gravatar imagejs4267 ( 2018-07-14 23:34:14 -0600 )edit

yes, it does.

you can see the generated code in opencv/build/modules/python_bindings_generator/pyopencv_generated_funcs.h , that's also, where the wrapper for your function will show up.

maybe it's helpful, if you add the c++ function & the generated code for it to your question (it won't fit into a comment !) , also maybe your intended python usage of it ?

berak gravatar imageberak ( 2018-07-15 01:09:44 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
2

answered 2018-07-16 23:03:57 -0600

js4267 gravatar image

I figure out why the python_binder does not wrap the output type of the second argument properly neither with my declaration nor with the one of @berak. It seem to be related to the name of the second argument. Inspired by the declaration of the OpenCV's function split I just change my declaration from :

CV_EXPORTS_W void read_myJFile(const String& filename, OutputArrayOfArrays img);

to

CV_EXPORTS_W void read_myJFile(const String& filename, OutputArrayOfArrays mv);

By just doing that I saw the wraping type in the file:

opencv/build/modules/python_bindings_generator/pyopencv_generated_funcs.h

change from Mat to vector_Mat.

I guess the reason why the binder use the name of the output variable to determine the wrapping type is related to the fact that OutputArrayOfArrays is a typedef of OutputArray, samething for InputArrayOfArrays is a typedef of InputArray (this is not true for InputArray, OutputArray and InputOutputArray that are three different classes). The fact they are typedef mean the binder cannot deduct the type of the wrapping output variable by just analysing the type of the output variable.

@berak thank you for your help.

edit flag offensive delete link more
0

answered 2018-07-15 01:48:26 -0600

berak gravatar image

updated 2018-07-15 02:26:08 -0600

imho, it should work like this:

// signature
CV_EXPORTS_W void read_myJFile(const String& filename, OutputArrayOfArrays img);

// implementation
void read_myJFile(const String& filename, OutputArrayOfArrays img) {
    std::vector<Mat> vec;
    for (...) { // each item in your filesystem
        Mat m = ...; // get a Mat and process it
        vec.push_back(m); // push it into the vector
    }
    img.create(vec.size(), 1, vec[0].type());
    img.assign(vec);
}

// c++ usage:
vector<Mat> imgs;
read_myJFile("xy.z", imgs);

// python:
imgs = cv2.read_myJFile("xy.z") # the wrapper code will generate a vector<Mat> to return
edit flag offensive delete link more

Comments

I did not know the assign method, I'll use to replace some sections otherwise it but it looklike similar to the code I made. We agree that in order to be able to write in python: imgs = cv2.read_myJFile("xy.z") the binder will create a C++ function that should looklike more or less that:

Python_return_type read_myJFile(Python_string_type str)
{
    An_Opencv_Type dst;
    read_myJFile(convertToStdString(str),dst);

    return ConvertToDstType(dst);
}

The conversion may not be there or manage differently. In my case when I looked the error it sent to me (I look at the specified line in the specified file) it is because the OpenCV type use to get the output is a Mat.

js4267 gravatar imagejs4267 ( 2018-07-15 09:17:28 -0600 )edit

I modify my code and use assign to set the output and I got a new error:

error: OpenCV(4.0.0-pre) /home/smile/lib_dir/opencv/opencv_400/opencv/modules/core/src/matrix_wrap.cpp:1934: error: (-213:The function/feature is not implemented)  in function 'assign'
js4267 gravatar imagejs4267 ( 2018-07-15 09:36:55 -0600 )edit

please try to make it work in c++ first.

and don't speculate about python signatures, but look at opencv/build/modules/python_bindings_generator/pyopencv_generated_funcs.h

berak gravatar imageberak ( 2018-07-15 10:40:43 -0600 )edit

It does work in C++. The issue does only exist in python. I am actually using it in C++ at this moment.

js4267 gravatar imagejs4267 ( 2018-07-15 10:54:58 -0600 )edit

neither the code in you question, nor the code in any comments does match, * what you're really doing*

berak gravatar imageberak ( 2018-07-15 12:07:42 -0600 )edit

I am opening a file with a proprietary format that is an image sequence (aka a video). My code work on C++, but does not on python because the python binder does not interpret the second argument properly.

js4267 gravatar imagejs4267 ( 2018-07-15 13:10:05 -0600 )edit

@berak I figure out :) but even your code would have generate exactly the same assertion has the one I reported in the question for exactly the same reason my code reported that assertion..

js4267 gravatar imagejs4267 ( 2018-07-15 13:20:39 -0600 )edit

@berak I tried to post the solution but I have to wait :(

js4267 gravatar imagejs4267 ( 2018-07-15 13:34:58 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-07-14 11:58:32 -0600

Seen: 338 times

Last updated: Jul 16 '18