Tuesday, May 11, 2010

gst-opencv design choices

While continuing wrapping new OpenCV functions into GstElements yesterday, I faced an interesting design choice on the mappings of OpenCV functions' parameters to GstElement's properties.

Take a look at cvSmooth docs. You can see that it has a type parameter, followed by param1, param2, param3 and param4 that have different semantics if different type is used. The question is how to expose those in the 'cvsmooth' GstElement?

I could think of 3 different choices here:

1) Go straightforward and use the same API as OpenCV
As a result, we should have an element with the properties named after the OpenCV parameters:
"cvsmooth type=blur param1=5 param2=3 param3=0.0 param4=0.0"

This results in a very not intuitive API, but we keep it aligned with OpenCV's, making it easy to people that already know one API to use the other one. The element docs would mostly point to OpenCV's docs. Resulting code is simple and easy to maintain.

2) Have multiple elements: cvsmoothblur, cvsmoothgaussian, cvsmooth...
We could have each smooth algorithm (type) into a separate element and have its properties reflect the semantics of this type. For example, we would have cvsmoothblur, cvsmoothmedian and one for each type. The properties of each one would named accordingly to its semantics, instead of some paramX.

This provides a nice API but might increase the number of elements for every function that has this type or a similar parameter. I don't know how common this is. This might be a good solution if there are a few of those. A downside is that switching the type has to use hot-swapping but I don't think this is a common use case.

3) Expose properties for each semantics and use them only if their type is selected.
We still keep it to one element, but we add one property for each semantic a parameter can assume. Those would only be used it we have its corresponding type is selected.

For example: param3 might be the "gaussian standard deviation" or the "color sigma" if type is gaussian or bilateral respectively. We add those 2 properties (standard-deviation and color-sigma) that are only going to be used if their types are selected.

This makes those lines possible:
"cvsmooth type=gaussian standard-deviation=5.0" or
"cvsmooth type=bilateral color-sigma=1.0"

Code is a little messier than options above.

Given those options, I really don't like option 3. I'm considering 1 or 2. From a quick look at some pages of OpenCV's transformations API I could see that this is not very common, and when it happens, only one parameter has a 'variable semantic', looks like I picked the trickiest one as my example.

So, which option would you chose?


bilboed said...

Option 1 is the best imho. You could just copy over the documentation for each parameter into the gobject properties descriptions, that'll remove any problems. Also, make the default the same as the method default values.

Josh said...

I would prefer Option 2, as Option 1 propagates a bad design decision. Just look at how OpenCV exposes the same functions via C++ (http://opencv.willowgarage.com/documentation/cpp/image_filtering.html). I'm fine with a function/element that allows for smoothing/blurring types to be specified via a parameter, but not if the parameters of said types vary from one to the next. Please go for Option 2 and break out such functions into multiple elements!

Josh said...

The comment I just left got me thinking about something else. Apparently you are using the C bindings to OpenCV; are you opposed to using C++ directly in the gst-opencv elements? It's funny to see how cvSmooth is implemented (at least as of 2.1) simply as an if/else if structure to call the appropriate C++ methods (boxFilter, medianBlur, etc.)

thiagoss said...

Yes, I'm using the C API. I already implemented with option 1, which is anyway the basis for option 2, just add subclasses and hide one parameter from them. And I agree that it is a bad design choice from OpenCV, but I guess option 1 eases maintenance in the longer term, and keeps the elements closer to the C API.

AFAIK OpenCV C functions are just wrapping around its C++ versions.