Automatically Including OpenCV Libraries of Different Versions

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?

Answers


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.


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.


Need Your Help

Writing a Z80 assembler - lexing ASM and building a parse tree using composition?

parsing assembly lexical-analysis z80

I'm very new to the concept of writing an assembler and even after reading a great deal of material, I'm still having difficulties wrapping my head around a couple of concepts.