19

I noted that opencv 4 is released and one difference is that API changed to be c++11 compliant.

What this really means?

How should I change my codes to be compatible with this version?

mans
  • 17,104
  • 45
  • 172
  • 321
  • 1
    Good, but probably very broad question. Not sure on the C++ side, but there are definitely some API changes in the Python wrappers. One thing that immediately comes to mind is `findContours` going back to returning a pair (like in 2.x sans the modification of the input image) as opposed to the triple in 3.x. – Dan Mašek Dec 24 '18 at 01:29

4 Answers4

12

I think the most different is, the OpenCV 4.0 use more C++11 features. Now cv::String == std::string and cv::Ptr is a thin wrapper on top of std::shared_ptr.

The Opencv 4.0 remove folder include/opencv and only keep include/opencv2. A lot of C API from OpenCV 1.x has been removed. The affected modules are objdetect, photo, video, videoio, imgcodecs, calib3d. The old macro defination or unnamed enum is not suggested, use named enum insted.

//! include/opencv2/imgcodes.hpp
namespace cv
{

//! @addtogroup imgcodecs
//! @{

//! Imread flags
enum ImreadModes {
       IMREAD_UNCHANGED            = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
       IMREAD_GRAYSCALE            = 0,  //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
       IMREAD_COLOR                = 1,  //!< If set, always convert image to the 3 channel BGR color image.
       IMREAD_ANYDEPTH             = 2,  //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
       IMREAD_ANYCOLOR             = 4,  //!< If set, the image is read in any possible color format.
       IMREAD_LOAD_GDAL            = 8,  //!< If set, use the gdal driver for loading the image.
       IMREAD_REDUCED_GRAYSCALE_2  = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
       IMREAD_REDUCED_COLOR_2      = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
       IMREAD_REDUCED_GRAYSCALE_4  = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
       IMREAD_REDUCED_COLOR_4      = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
       IMREAD_REDUCED_GRAYSCALE_8  = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
       IMREAD_REDUCED_COLOR_8      = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
       IMREAD_IGNORE_ORIENTATION   = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
     };

    // ...
}

Such as, when read image, it should be something like this:

cv::Mat img = cv::imread("test.png", cv::IMREAD_COLOR);

Except the new featues, the most C++ APIs keep the same. While the biggest different I found is cv2.findContours (in Python OpenCV):

In OpenCV 3.4:

findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> image, contours, hierarchy

enter image description here

In OpenCV 4.0:

findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy

enter image description here

An alternative to work with 2.x 、3.x、4.x is:

cnts, hiers = cv2.findContours(...)[-2:]

Some links:

  1. OpenCV Release
  2. OpenCV ChangeLog
  3. OpenCV Introduction
  4. OpenCV Documentation
  5. How to use `cv2.findContours` in different OpenCV versions?
  6. OpenCV on Stackoverflow

Kinght 金
  • 17,681
  • 4
  • 60
  • 74
  • An interesting question: Why they did not use class enum and used enum? I think in C++11, the preference is class enum? – mans Dec 24 '18 at 09:36
  • 2
    Maybe they just use historical writing? Actually I think `enum class` or `enum struct` maybe better, because they are scopped. But as the code base is so large, there exist so many code that use unscoped one. If change `enum` to `enum class`, the existing code using `cv::IMREAD_COLOR` will compile failed, unless modified to `cv::ImreadModes::IMREAD_COLOR`. And there're still many bugs related to `enum` changing when wrapping the `C++ OpenCV API` into `Python|Java|C#`. So they just keep? I'm not really sure. – Kinght 金 Dec 24 '18 at 10:01
  • 1
    And here is [a `enum struct` issue on github in Java binding](https://github.com/opencv/opencv/pull/13471) – Kinght 金 Dec 24 '18 at 10:09
8

According to OpenCV 4.0.0, you don't have to make any significant modifications (most likely any at all) to your source codes, unless you are using some C API which has been removed.

As already stated

OpenCV is now C++11 library and requires C++11-compliant compiler

To use c++11, clang version 3.3 and higher is required with flag -std=c++11. Same for g++ 4.3 and higher.

It allows them to use std::string instead of cv::String, and other c++11 features. But don't worry, cv::String will still work, but is now allias for std::string. Similliar for smart pointers, etc.

kocica
  • 6,412
  • 2
  • 14
  • 35
  • Just curious, have you tried upgrading any sort of production code to 4.x? With this you're tempting me to spend the holidays building new deps and porting the code :D – Dan Mašek Dec 24 '18 at 01:34
  • 1
    Actually I have re-written few modules from C API to C++. It is not as hard as it might seem -- almost all C functions e.g. `cvCvtColor` have their equivalents in C++ `cv::cvtColor` (with same functionality). Also there is support for conversion from old-style C types to C++ types, as you can see e.g. [here](https://physics.nyu.edu/grierlab/manuals/opencv/classcv_1_1Mat.html#ac54e1c5025e8afd7641fd2a37a3deef7). Hopefully you won't spend holidays that way :D – kocica Dec 24 '18 at 09:36
  • @FilipKočica The official OpenCV documentation is [here](https://docs.opencv.org/) by the way. – Catree Dec 24 '18 at 12:14
2

I think the most vital impact is you need to use a c++11 compiler.

Also, it may not change the interface but allow them to make use of the updated Language changes, such as smart pointers, etc.

Eddie C.
  • 155
  • 8
1

The above comment "According to OpenCV 4.0.0, you don't have to make any significant modifications (most likely any at all) to your source codes, unless you are using some C API which has been removed." appears to be far from true.

I and my partner developed a package for a collaborator. We used v 3.4 (C++140 ; the collaborator has installed v 4.5. Now we are finding our code can't be compiled on their system because of numerous symbol name changes. Examples: CV_THRESH_TOZERO, CV_GRAYTORGB.

We do know how to solve the problem (short of rewriting our software) which involves a pile of #ifdefs. However this is not the usual meaning of "backward compatible". And it should not have been necessary: the opencv people should have kept the old definitions as well as the new ones.

Kurt
  • 11
  • 1