Automatically Including OpenCV Libraries of Different Versions

Go To StackoverFlow.com

1

I've been automatically including the opencv library files for my c++ code on Visual Studio 2008 on Windows 7 with the following code:

#ifndef NDEBUG
#pragma comment(lib, "opencv_core231d.lib")
#pragma comment(lib, "opencv_highgui231d.lib")
#pragma comment(lib, "opencv_imgproc231d.lib")
#else
#pragma comment(lib, "opencv_core231.lib")
#pragma comment(lib, "opencv_highgui231.lib")
#pragma comment(lib, "opencv_imgproc231.lib")
#endif 

but I run into trouble when the system has a different version of the opencv library installed because the .lib files have the version (in this case, 2.31) in the filename. Is there a good way to automatically or near-automatically detect what version of the opencv library is available then slide in the appropriate version string into the pragma?

2012-04-05 21:18
by Steve
Not that I'm aware of - karlphillip 2012-04-06 02:01
I was reviewing this old problem and was wondering about a scheme of concatenation? See: http://gcc.gnu.org/onlinedocs/cpp/Concatenation.htm - Steve 2012-12-04 07:47


2

I have worked out a solution to having code run on various versions of OPENCV by merging the following articles:

  1. How to make a string out of macros
  2. Concatenating strings in macros
  3. Pragma statements in #defines with support for VS2008 here on MSDN
  4. Bonus: How to have global settings defined in a solution

As noted, this can cause some serious grief if you pop between incompatible versions but for those versions and features supported this may be useful to some. Use this technique to set the opencv version once and have your code automatically link to the desired version by either

  1. define the OPENCV_VERSIONin one place in your source code

  2. Define it in a Property Sheet
  3. Define it in a system environment variable.

My code ended up like so:

#include <iostream>

// #define OPENCV_VERSION $(OPENCV_VERSION)
// #define OPENCV_VERSION 220

#define QUOTE(name) #name
#define STR(macro) QUOTE(macro) 

#define LINK_TO_OPENCV(libname) __pragma(comment(lib, "opencv_" #libname STR(OPENCV_VERSION)))
#define LINK_TO_OPENCV_DEBUG(libname) __pragma(comment(lib, "opencv_" #libname STR(OPENCV_VERSION) "d"))

#ifndef NDEBUG
LINK_TO_OPENCV_DEBUG("core")
LINK_TO_OPENCV_DEBUG("highgui")
LINK_TO_OPENCV_DEBUG("imgproc")
#else
LINK_TO_OPENCV("core")
LINK_TO_OPENCV("highgui")
LINK_TO_OPENCV("imgproc")
#endif 


int main()
{
    std::cout << STR(LINK_TO_OPENCV("core")) << "\n";
    return 0;
}

And now to set the OPENCV_VERSION anywhere you like. For example, you can have a single header file included by everyone that has the line:

#define OPENCV_VERSION 220

Or you can goto Project->Properties->C/C++->Preprocessor and set Preprocessor Definitions to OPENCV_VERSION=220. Or you can do the same thing in a shared property sheet for the entire solution.

Or, and this is important, you can use this technique to define a global environment variable in windows itself called OPENCV_VERSION_ENV and set its value to the version code (say, 220). Then you can put set the preprocessor definition to OPENCV_VERSION=$(OPENCV_VERSION_ENV) and you will bring in the environment variable into the link command. You CANNOT do a #define OPEN_VERSION $(OPENCV_VERSION_ENV) but since the property pages will automatically translate $(macros) we can get environment variables there.

2013-02-20 07:07
by Steve
oh, there's a similar construct already in modules/core/include/opencv2/core/version.hp - berak 2013-02-20 09:46
@berak That's a good comment. We can use this to define the OPENCV_VERSION in an even better way with: #define OPENCV_VERSION CVAUX_STR(CV_MAJOR_VERSION)CVAUX_STR(CV_MINOR_VERSION)CVAUX_STR(CV_SUBMINOR_VERSION) Steve 2013-02-20 20:19


2

There are small changes between different OpenCV versions - not much, but enough to crash your app when you change from 2.0 to 2.2 or from 2.2 to 2.3.1. Also, the beta 2.4 release has enough changes from previous ones.

So best is to test your app with an OpenCV version, and deliver it with those dlls only.

A small example:

Mat a(3,3,CV_8UC3);

a.setTo( Scalar(10) ); // in 2.3.1 will set all channels to 10,
// in 2.2 will only set first channel. 

The corresponding 2.2 call would be

a.setTo(Scalar::all(10));

Or

a = 0; // runs fine on 2.3.1. Equivalent to setTo().
// Does not compile on earlier versions

Another example is cv::drawPoly(), which has a different signature on 2.2 and 2.3.1.

Given the fact that those changes are not well documented, the chance to miss one of them by mistake is really high.

2012-04-06 05:39
by Sam
That's a valid comment and is noted. However, it's 1) theoretically possible to support multiple versions at the same time by branching and 2) lots of my code uses basic functions that aren't changing between versions. In either case, I came up with an approach to use a project, solution, or system-wide version definition in the code. This subsequently allows the code to automatically link to the correct version and could (if one was really determined) detect and execute the correct code for the opencv version installed and thereby address your concern - Steve 2013-02-20 07:15
While your approach is fine and easy to implement when working with compile issues, it's hard to find all the small changes that affect your program without crashing it. My first example will be really hard to find, because it compiles, it runs, it affects the image, but in a subtle different way. And you'll have a lot of headaches finding such bug - Sam 2013-02-20 08:06
Ads