Using Cmake for Building OpenCV Application

On Fedora install CMake using dnf

$ sudo dnf install cmake

on Debian based distros you can isntall it using

$ sudo apt install cmake

CMake is an open-source, cross-platform family of tools designed to build, test and package software.

We have CMake installed now. Let’s build a C++ Hello World program using CMake.

#include <iostream>

using namespace std;

int main(int argc, const char **argv){
    if(argc < 2)
        cout<<"Hello World\n";
    else
        cout<<"Hello "<< argv[1]<< "\n";
    return 0;
}

Typically in order to build this program the command looks something like

$ g++ -o hello hello.cpp

Now let’s see how to compile this program using CMake

The CMakeLists.txt looks like.

cmake_minimum_required(VERSION 3.13)
project(hello)

set(CMAKE_CXX_STANDARD 11)

add_executable(hello hello.cpp)

Let’s see what we have got in CMakeLists.txt.

With that said let’s buld this program.

[04:04 PM][girish@battle-ship]:cmake-hello-world
$ ls
CMakeLists.txt  hello.cpp
[04:04 PM][girish@battle-ship]:cmake-hello-world
$ mkdir build
[04:04 PM][girish@battle-ship]:cmake-hello-world
$ cd build
[04:04 PM][girish@battle-ship]:build
$ cmake ..
-- The C compiler identification is GNU 10.2.1
-- The CXX compiler identification is GNU 10.2.1
-- Check for working C compiler: /usr/lib64/ccache/cc
-- Check for working C compiler: /usr/lib64/ccache/cc - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib64/ccache/c++
-- Check for working CXX compiler: /usr/lib64/ccache/c++ - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/girish/git/cmake-hello-world/build
[04:04 PM][girish@battle-ship]:build
$ make
Scanning dependencies of target hello
[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable hello
[100%] Built target hello
[04:04 PM][girish@battle-ship]:build
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  hello  Makefile
[04:04 PM][girish@battle-ship]:build
$ ./hello 
Hello World
[04:04 PM][girish@battle-ship]:build
$ 

At this point we have CMake installed on the system. Let’s now install OpenCV. To build OpenCV applications using C++ we need to install binary and development packages for OpenCV and OpenCV Contrib.

On Fedora

$ sudo dnf install opencv opencv-contrib opencv-devel

So now that we have installed both OpenCV and CMake let’s start building OpenCV application. As always let’s build a Hello World program for video using OpenCV. The C++ code for that looks something like following.

#include "opencv2/opencv.hpp"
#include <iostream>
 
using namespace std;
using namespace cv;
 
int main(int argc, char **argv){
 
  // Create a VideoCapture object and open the input file
  // If the input is the web camera, pass 0 instead of the video file name
  VideoCapture cap(argv[1]); 
    
  // Check if camera opened successfully
  if(!cap.isOpened()){
    cout << "Error opening video stream or file" << endl;
    return -1;
  }
     
  while(1){
 
    Mat frame;
    // Capture frame-by-frame
    cap >> frame;
  
    // If the frame is empty, break immediately
    if (frame.empty())
      break;
 
    // Display the resulting frame
    imshow( "Frame", frame );
 
    // Press  ESC on keyboard to exit
    char c=(char)waitKey(25);
    if(c==27)
      break;
  }
  
  // When everything done, release the video capture object
  cap.release();
 
  // Closes all the frames
  destroyAllWindows();
     
  return 0;
}

The command to compile this hello world code would be

$ g++ -w hello_opencv.cpp -o hello-opencv $(pkg-config --cflags --libs opencv)

In the command above, $(pkg-config --cflags --libs opencv) returns the include path and the libraries for opencv.

Now let’s create a CMakeLists.txt file to build this exe using CMake.

cmake_minimum_required(VERSION 2.6)

# set the project name and version
project (temp)

#set (CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED) 

include_directories(${OpenCV_INCLUDE_DIRS}) # not needed for opencv>=4.0
add_executable(hello-opencv hello_opencv.cpp)
target_link_libraries(hello-opencv ${OpenCV_LIBS})

In this file CMakeLists.txt function find_package is responsible for finding the OpenCV pakcage form the environment/package-config and setting all of the required variable for using OpenCV as a dependency. Out of those veriables we are using OpenCV_INCLUDE_DIRS and OpenCV_LIBS which holds the include path for OpenCV and libraries provided by OpenCV.

To build the this program.

# go to the project directory
$ cd <proj-directory>
# create a new directory
$ mkdir build
$ cd build
# run cmake and pass the location of CMakeLists.txt as an argument to it.
$ cmake ..

After running cmake .. you will have Makefile and a lot of other stuff created in the build folder. Now go ahead and run

$ make

and you will have the binary executable for the OpenCV Hello World program under build directory with the name hello_opencv. You can run it

$ hello_opencv <path to a video file>

NOTE: There is a specific reason that you need to create a separate folder to generate build files. You can read more about that here.

This post covers the very basics of CMake (and may not be complete). But it can be a good point to start from. For further reading following links can be useful