Ask Your Question
0

Mixing opencv 2.4.x and 3.3.x in one application (single process)

asked 2017-11-13 15:45:19 -0600

Henok gravatar image

Hi, thank you in advance for your help.

I am in a situation where I need to use a library from latest opencv and use it side by side with an older version. So far my attempts have been:

  • Change the include paths so that the two don't conflict. That is change all opencv to opencv_3.3.x for the latest version and try static linking. The project builds fine but when it is referenced by a project that uses an older version of opencv, all hell breaks loose and I get all kinds of redefinition errors.

Is it worth the effort to try and run the two side by side. The reason is I need to integrate a deep learning network to a legacy application that uses opencv. The easiest way to do that is to use the latest opencv dnn library.

I'm using Visual Studio 12 with vc11 compiler package.

Thank you -Henok

edit retag flag offensive close merge delete

Comments

1

One way would be to make two wrapper DLLs that act as a buffer between your code and the OpenCV code. That way you can build one version into one DLL, and build the other version into the other DLL. None of your current redefinition problems will occur. Writing a DLL is not very hard -- Visual Studio has a template DLL project even.

Another way would be to write just one DLL, and build one version into it, and then build the other version directly into the exe file. In this case I'd make the DLL encapsulate the newest version of OpenCV, since that's the API that you work the least with (you only have to encapsulate the DNN functionality).

It's your call.

sjhalayka gravatar imagesjhalayka ( 2017-11-13 20:25:12 -0600 )edit

On second thought, this solution might not work at first. I'm using VS Community 2017 (VC19), and I had no problem making the DLL file, but when I add code that uses the OpenCV library, I get linker errors; undefined references.

I put the DLL wrapper code at: https://github.com/sjhalayka/OpenCV3_...

I put the DLL wrapper user code at: https://github.com/sjhalayka/OpenCV3_...

It looks like you might have to also encapsulate the Mat class, or better yet, just pass around the raw image data between the exe (wrapper user) and the DLL (wrapper). I'll play around with it for a bit more to see what I come up with.

sjhalayka gravatar imagesjhalayka ( 2017-11-14 10:26:19 -0600 )edit

Thanks a bunch for your help. What you described above, option 2, is what I'm leaning towards as well. I'll be expecting a cv::Mat or just buffer of pixels from legacy code and do transform\convert to cv::Mat before passing input through network.

Henok gravatar imageHenok ( 2017-11-14 11:00:18 -0600 )edit

Hi again, I fixed the wrapper and wrapper user code. They pass around a vector<float> by reference, to store floating-point image data. You can grab a pointer to the vector's memory block by using the address-of operator

&image_vector[0]

So the Mat constructor (in your OpenCV 2.x code) would be

Mat m = Mat(image_height, image_width, CV_32FC1, &image_vector[0]).clone();

My GitHub repositories listed above are using option #2.

P.S. If you come up with a solution, write about it as an answer to this question.

sjhalayka gravatar imagesjhalayka ( 2017-11-14 11:25:38 -0600 )edit

Thanks my friend. I'm pretty much using what you have, except I need char* instead of vector<float>. Cross fingers :-( Will close the case for now.

Henok gravatar imageHenok ( 2017-11-15 10:25:50 -0600 )edit

Alright, well let us know if you need help with anything else. It was a fun project to work on. :)

sjhalayka gravatar imagesjhalayka ( 2017-11-15 11:17:18 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-11-20 10:25:46 -0600

Henok gravatar image

Here is a solution that worked for me using boost.extension extensiblity library which is long deprecated but had it at my disposal. You can look into Microsoft's COM or Mozilla's XPCOM (Cross-platform COM) as an alternative to boost.extension. Probably better too.

Compiler packages: vc11 visual studio 12  
OS: windows 7 x64  Integration
target: Legacy application with opencv 2.4.5 
New version: opencv 3.3.1 - the dnn module in particular

The end solution was to write a wrapper\extension with network interface. This wraps API in COM server for version 3. The interface defines entry to opencv dnn stuff and is called by the legacy code that uses earlier version of opencv. Notice the interface makes no opencv3 references.

Interface :

// This is the dispatcher that gets statically linked to the legacy code 
class IOpenCV3Interface 
{
public: 
         typedef boost::shared_ptr<IOpenCV3Interface> ptr; // will be used by extension manager to load this class 
         virtual bool Classify(const char* data, const int &width, const int &height)
}

In legacy code we use boost extension manager to instantiate this object and call classify:

IOpencv3Interface::ptr _opencv3Interface = ExtensionFinder<IOpencv3Interface>().CreateSingle()
_opencv3Ingerface.Classify(data,10,10)

at this point a call to opencv 3 is on its way

Now have a derived class implement classify which uses opencv stuff.

//This gets loaded by the dispatcher dynamically using boost.extension manager 
class Classifier : IOpenCV3Interface 
{
            public: 
                 bool Classify(const char* data, const int& w, const int& h) override;
}

clasifier.cpp 
Classifer::Classify(const char* data, const int& w, const int &h)
{
          //use open cv 3. 
}

This approach essentially decouples the two libraries by adding the opencv 3 code as a plugin. Compiler is okay with this so far. I'll update the answer if anything changes

Let me know if you have any questions

edit flag offensive delete link more

Comments

I used XPCOM to write a Firefox plugin once. Is this similar?

sjhalayka gravatar imagesjhalayka ( 2017-11-20 15:25:19 -0600 )edit

I would think yes. Most plugins are written this way (not my expertise however - had to get more help from others). Basically since it is impossible to link 2 libs of competing interfaces with the same exe we wrap opencv3 in COM server and use a dispatcher API that wraps to the COM server. Legacy code uses boost to dynamically load COM server and uses the dispatcher ( using generic data types) to gain access to opencv3.

Henok gravatar imageHenok ( 2017-11-20 16:54:58 -0600 )edit

Very cool. :) I'm proud.

sjhalayka gravatar imagesjhalayka ( 2017-11-20 16:56:01 -0600 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2017-11-13 15:45:19 -0600

Seen: 70 times

Last updated: Nov 20