RebelsOnTheMoon
12 min readNov 8, 2023

--

Smoothen OpenCV C++ developement with the VCPKG package manager. You may download prebuilt Opencv libraries, build Opencv from git source, and set up your Opencv project in Visual Studio or Cmake. You can kind of bypass all the configuring processes to build custom configurations of Opencv libraries with the VCPKG package manager. The ultimate goal is to guide you from zero to a working C++ Opencv app that streams video to a VLC player using GStreamer. This article promises to guide you every step of the way, turning your goal into a reality faster with the VCPKG manager.

VCPKG faster from 0 to Opencv video streaming to VLC player

The beauty of VCPKG lies in its ability to streamline the configuration process for building OpenCV libraries. It integrates directly with Visual Studio and works seamlessly with CMake, saving you precious time in setting up your project’s include directories, configuring additional library directories, and managing specific lib dependencies.

One of its standout features is the automatic copying of DLL libraries to the folder with your executable. This eliminates the need to set up environmental variables for your DLLs locations.

With VCPKG, you can swiftly compile the ‘Hello World’ OpenCV project in Visual Studio and CMake much faster. It’s a game-changer that deserves to be highlighted in the world of OpenCV C++ development.

While I continue to build and configure OpenCV from source for certain specific needs without a package manager, there are instances where VCPKG proves to be a quicker alternative. It may not always be flawless, but more often than not, it’s the faster option.

My current objective is to integrate the OpenCV 4 with the GStreamer support library into my C++ project. So, let’s dive in and explore this exciting journey together. Let the games begin!

What is VCPKG good for the OpenCV project?

Vcpkg is a free C/C++ package manager for acquiring and managing libraries. It is under the roof of Microsoft and many open-source developers all over the world. It will download and build a library in single steps. So, You will just choose the configuration and hit the command.

To start with VCPKG is super simple, You will definitely need to have git installed. Then clone the VCPKG repository to your PC.

git clone https://github.com/Microsoft/vcpkg.git

Run this bat file or shell script if you are a Linux user.

.\vcpkg\bootstrap-vcpkg.bat
OR
./vcpkg/bootstrap-vcpkg.sh

You are ready to find the library for your project by search command. So let’s list Opencv in the picture below. You can see different configurations for the OpenCV library. I have used different builds of Opencv with FFmpeg and GStreamer support in the past.

./vcpkg.exe search opencv
.
.
opencv4[contrib] opencv_contrib module
opencv4[cuda] CUDA support for opencv
opencv4[cudnn] cuDNN support for opencv
opencv4[dc1394] Dc1394 support for opencv
opencv4[default-features] Platform-dependent default features
opencv4[dnn] Enable dnn module
opencv4[dnn-cuda] Build dnn module with CUDA support
opencv4[eigen] Eigen support for opencv
opencv4[ffmpeg] ffmpeg support for opencv
opencv4[freetype] Freetype support for opencv
opencv4[gdcm] GDCM support for opencv
opencv4[gstreamer] gstreamer support for opencv
opencv4[gtk] GTK support for opencv
opencv4[halide] Halide support for opencv
opencv4[ipp] Enable Intel Integrated Performance Primitives

By following the install command opencv4[gstreamer] will be built and installed. The default target in my case was the x86-windows platform.

./vcpkg.exe install opencv4[gstreamer]

Computing installation plan...
The following packages will be built and installed:
* bzip2[core,tool]:x64-windows -> 1.0.8#5
* bzip2[core,tool]:x86-windows -> 1.0.8#5
* dirent:x64-windows -> 1.23.2#3
* dirent:x86-windows -> 1.23.2#3
..
.
.
.
-- Using cached mingw-w64-i686-pkgconf-1~1.8.0-2-any.pkg.tar.zst.
-- Using cached msys2-msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst.
-- Using msys root at C:/vcpkg/vcpkg/downloads/tools/msys2/6f3fa1a12ef85a6f
-- Installing: C:/vcpkg/vcpkg/packages/opencv4_x86-windows/share/opencv4/copyright
-- Performing post-build validation
Stored binaries in 1 destinations in 18 s.
Elapsed time to handle opencv4:x86-windows: 15 min
Total install time: 2.6 h
If you do not install the meta-port *opencv*, the package opencv4 is compatible with CMake
if you set the OpenCV_DIR *before* the find_package call

set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x86-windows/share/opencv4")
find_package(OpenCV REQUIRED)

I realize that the target is x86-windows, during the configuration in Visual Studio. I set up a 64-bit debug project and the library was not found. After restart of Visual Studio, You should get your libraries ready to use without any configuration, but we will get there.

So, I rebuilt with x64 bit target opencv4[gstreamer]:x64-windows.

C:\vcpkg\vcpkg>vcpkg.exe install opencv4[gstreamer]:x64-windows   
.
.
.
Total install time: 30 min
If you do not install the meta-port *opencv*, the package opencv4 is compatible with CMake
if you set the OpenCV_DIR *before* the find_package call

set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x64-windows/share/opencv4")
find_package(OpenCV REQUIRED)

Visual Studio integration with VCPKG for Opencv

Visual Studio integration is great. I am currently using VS 2022 (64-bit) - Preview Version 17.8.0 Preview 1.0. There is no need to set up an include directory, and no need to set up libraries. You are ready to go after the restart of Visual Studio. There is one prerequisite to issue VCPKG integrate install command in the following code sample. You are notified with the information “All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available.”

C:\vcpkg\vcpkg>vcpkg.exe integrate install   
Applied user-wide integration for this vcpkg root.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake"

All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available.

Now the problem of mixing targets. I initially installed x86 and tried to use this library in the x64 project. So, I have one lesson learned. Created C++ console application, and set target for x64.

VCPKG mixing target platform
VS target platform

The basic project cannot find the headers, which I was expecting after integrating the install command.

VCPKG include not found mixing platform
Opencv headers not found

I checked what was installed by default opencv4[gstreamer] and all was x86. You can see the output of the list command below.

vcpkg.exe list
..
..
opencv4[default-features]:x86-windows Platform-dependent default features
opencv4[dnn]:x86-windows Enable dnn module
opencv4[gstreamer]:x86-windows gstreamer support for opencv
opencv4[jpeg]:x86-windows JPEG support for opencv
opencv4[png]:x86-windows PNG support for opencv
opencv4[quirc]:x86-windows Enable QR code module
opencv4[tiff]:x86-windows TIFF support for opencv
opencv4[webp]:x86-windows WebP support for opencv

This was the point to check if the change build x86 option in Visual Studio will include the header files correctly. Yes, All was resolved and I reinstalled the library by VCPKG for the correct target opencv4[gstreamer]:x64-windows and changed the target back to x64 in VS as well.

So, check what you’ve installed against what you want.

Check Opencv Build information

With the corrected target, here is a simple program to check the Build information of your Opencv library.

#include <opencv2/opencv.hpp>
#include <iostream>

int main()
{
std::cout << cv::getBuildInformation() << std::endl;
std::cout << "Hello World!\n";
}

The partial program output includes information about used Opencv library in my project. So you can see that the GStreamer Video IO backend is included.

  Video I/O:
GStreamer: YES (1.20.5)
DirectShow: YES
Media Foundation: YES
DXVA: YES

What is great about the integration is that Opencv DLLs are copied to a folder, where your Opencv exe file is located. So, no need for any configuration of the linker to handle DLL libraries or global environmental variables.

VCPKG Opencv dll management
Compiled Opencv project executable with DLLs

CMAKE is our great friend with Opencv and VCPKG

Now, jump to CMAKE using just VS code. The user experience from CMAKE depends on your experience, we need to pay attention to what CMAKE tells us if there is a problem. Let's assume that my VCPKG is located in Directory: C:\vcpkg\vcpkg. The structure of my sample project in opencv_p1 directory is in the following image. Inside my project directory is one source code file main.cpp, the CMakeLists.txt, and the build directory, where the program will be compiled and linked.

Cmake opencv project
Opencv Cmake project

My CMakeList.txt file content:

cmake_minimum_required(VERSION 3.15)
project(opencv_p1 CXX)

find_package(OpenCV REQUIRED)
find_package(protobuf REQUIRED)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE ${OpenCV_LIBS} protobuf::libprotoc protobuf::libprotobuf protobuf::libprotobuf-lite)

The configuration based on CMakeList.txt is performed by command from the build directory in the following format.

C:\cmake_tut\opencv_p1\build>cmake .. 
"-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake"

The -DCMAKE_TOOLCHAIN_FILE needs to point to vcpkg.cmake location. As, I have both 2019 and 2022 Visual Studio, By default Cmake creates a project for Visual Studio 16 (2019). Let's change this to VS 2022.

CMake configuration

Let's try to configure the project again. I clean the build directory. You can simply delete the content of the build directory and recreate the configuration. So, the -G generator will be VS 17, and -A architecture x64. Now, The following command will configure my project again.

build> cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake"
-G "Visual Studio 17 2022" -A x64
-- The CXX compiler identification is MSVC 19.38.33030.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.38.33030/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Protobuf: C:/vcpkg/vcpkg/installed/x64-windows/tools/protobuf/protoc.exe (found version "3.21.12.0")
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - not found
-- Found Threads: TRUE
-- Found TIFF: optimized;C:/vcpkg/vcpkg/installed/x64-windows/lib/tiff.lib;debug;C:/vcpkg/vcpkg/installed/x64-windows/debug/lib/tiffd.lib (found version "4.5.1")
-- Found OpenCV: C:/vcpkg/vcpkg/installed/x64-windows (found version "4.7.0")
CMake Warning (dev) at C:/Program Files/CMake/share/cmake-3.27/Modules/FindPackageHandleStandardArgs.cmake:438 (message):
The package name passed to `find_package_handle_standard_args` (Protobuf)
does not match the name of the calling package (protobuf). This can lead
to problems in calling code that expects `find_package` result variables
(e.g., `_FOUND`) to follow a certain pattern.
Call Stack (most recent call first):
C:/Program Files/CMake/share/cmake-3.27/Modules/FindProtobuf.cmake:652 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
C:/vcpkg/vcpkg/installed/x64-windows/share/protobuf/vcpkg-cmake-wrapper.cmake:16 (_find_package)
C:/vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake:809 (include)
CMakeLists.txt:10 (find_package)
This warning is for project developers. Use -Wno-dev to suppress it.

-- Found Protobuf: optimized;C:/vcpkg/vcpkg/installed/x64-windows/bin/libprotobuf.dll;debug;C:/vcpkg/vcpkg/installed/x64-windows/debug/bin/libprotobufd.dll (found version "3.21.12")
-- Configuring done (44.2s)
-- Generating done (0.2s)
-- Build files have been written to: C:/cmake_tut/opencv_p1/build

Once the project is configured. The building and linking can be started by the following build command.

PS C:\cmake_tut\opencv_p1\build> cmake --build .
MSBuild version 17.8.0-preview-23431-02+3c910ba83 for .NET Framework

1>Checking Build System
Building Custom Rule C:/cmake_tut/opencv_p1/CMakeLists.txt
main.cpp
main.vcxproj -> C:\cmake_tut\opencv_p1\build\Debug\main.exe
Building Custom Rule C:/cmake_tut/opencv_p1/CMakeLists.txt

The Debug project option is built and the folder contains all the DLL opencv_code4D.dll needed to run the main.exe project.

Opencv build directory with copied DLL by VCPKG
VCPKG Opencv Cmake project

Simple Opencv GStreamer project

I will ask GPT4 to create some examples for you. So my question was as follows:

Bing chat generates tutorial code for Opencv
Microsoft Bing chat

The generated code needs some adjustments. I commented out gst_init in the first place. The code was compiled without major problems, but the GStreamer pipeline needs some updates. The dependent .dll libraries even from GStreamer were copied to the directory next to my executable. All dependencies are handled by VCPKG itself. So, I need to focus just on coding.

Visual Studio Code for VCPKG CMAKE project
VS code CMAKE Opencv Project

Rebuild Opencv with FFmpeg and GStreamer, fix missing DLLs

My project is missing some of the dependencies. So I will install OpenCV 4 again with FFmpeg and GStreamer. So The following command with the recurse option can be useful to reinstall your library. The multiple options are in square brackets simply divided by a comma.

vcpkg install opencv4[ffmpeg,gstreamer]:x64-windows --recurse

You can see the “The following packages will be rebuilt:” OpenCV part and additionally: The following packages will be built and installed: FFmpeg.

C:\vcpkg\vcpkg>vcpkg install opencv4[ffmpeg,gstreamer]:x64-windows 
Computing installation plan...
The following packages will be rebuilt:
opencv4[core,default-features,dnn,ffmpeg,gstreamer,jpeg,png,quirc,tiff,webp]:x64-windows -> 4.7.0#6
The following packages will be built and installed:
* ffmpeg[avcodec,avdevice,avfilter,avformat,core,swresample,swscale]:x64-windows -> 5.1.2#7
* pkgconf:x64-windows -> 1.8.0#5
* vcpkg-cmake-get-vars:x64-windows -> 2023-03-02
* vcpkg-pkgconfig-get-modules:x64-windows -> 2023-02-25
Additional packages (*) will be modified to complete this operation.
warning: If you are sure you want to rebuild the above packages, run the command with the --recurse option.

C:\vcpkg\vcpkg>vcpkg install opencv4[ffmpeg,gstreamer]:x64-windows --recurse
Computing installation plan...
The following packages will be rebuilt:
opencv4[core,default-features,dnn,ffmpeg,gstreamer,jpeg,png,quirc,tiff,webp]:x64-windows -> 4.7.0#6
The following packages will be built and installed:
* ffmpeg[avcodec,avdevice,avfilter,avformat,core,swresample,swscale]:x64-windows -> 5.1.2#7
* pkgconf:x64-windows -> 1.8.0#5
* vcpkg-cmake-get-vars:x64-windows -> 2023-03-02
* vcpkg-pkgconfig-get-modules:x64-windows -> 2023-02-25

Now, let's wait until the VCPKG will do the job.

C:\vcpkg\vcpkg>vcpkg integrate install
Applied user-wide integration for this vcpkg root.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake"

All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available.

Gstreamer User/System variables configuration

You need to install GStreamer, the link for Windows full installation procedure here. There is a developer installer, which is not needed if you are using VCPKG. The runtime installer is needed even in this case. Without environmental variables to GStreamer executables and plugin directory. You will be able to compile your project, but may fail to use the GStreamer pipeline while executing the program. In short, My environmental variables are set to the following GStreamer locations.

User variables:

Path: C:\gstreamer\1.0\msvc_x86_64\bin

System variable:

Gstreamer windows configuration
Gstreamer system variables

Opencv video stream to VLC project

The project will stream video from the C++ Opencv program to the VLC player. It is as simple as that.

As std::string pipeline generated by ChatGPT is not fully working for me. I need to use my own head.

cv::VideoWriter writer_udp(
"appsrc ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! x264enc ! mpegtsmux !udpsink host=192.168.0.165 port=5000 sync=false",
0,
20,
cv::Size(640, 480),
true);

Here is the comparison of the generated pipeline by GPT 3.5 and my modifications. The x264enc was placed incorrectly as some other adjustments were needed.

ChatGPT appsrc ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast ! rtph264pay ! udpsink host=127.0.0.1 port=5000
Me appsrc ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! x264enc ! mpegtsmux !udpsink host=127.0.0.1 port=5000 sync=false

The final code is close to the one generated by Bing GPT. The GPT definitely sped up my tutorial code to focus just on some final tuning. If you try this code with the correct configuration the host IP adjustment will be needed on your environment.

#include <opencv2/opencv.hpp>

int main(int argc, char** argv)
{

// Open the webcam
cv::VideoCapture cap(0);

if (!cap.isOpened()) {
std::cerr << "Could not open webcam" << std::endl;
cv::waitKey(0);
return -1;
}
// Get the webcam frame size
int frame_width = cap.get(cv::CAP_PROP_FRAME_WIDTH);
int frame_height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);

cv::VideoWriter writer_udp(
"appsrc ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! x264enc ! mpegtsmux !udpsink host=127.0.0.1 port=5000 sync=false",
0,
20,
cv::Size(640, 480),
true);


if (!writer_udp.isOpened()) {
std::cerr << "Could not open VideoWriter" << std::endl;
cv::waitKey(0);
return -1;
}

cv::Mat frame;

while (true) {
// Capture frame from webcam
cap >> frame;

if (frame.empty()) {
break;
}
cv::resize(frame, frame, cv::Size(640, 480));
writer_udp << frame;

// Display the resulting frame
imshow("Frame", frame);
cv::waitKey(25);
// Press 'q' on the keyboard to exit
if (cv::waitKey(1) == 'q') {
break;
}
}

cap.release();
return 0;
}

In VLC you need to “Open network stream” and use the URL of this form udp://@127.0.0.1:5000 depending on your network configuration.

As a result of this effort, Video output is streamed from the Opencv C++ app to VLC. How cool is that? VCPKG saves us tons of time.

Streaming from Opencv to VLC

Conclusion of using VCPKG for Opencv development

You have just learned how to use the VCPKG package manager to simplify your OpenCV C++ development. You have seen how easy it is to prepare custom OpenCV libraries with VCPKG for FFmpeg and GStreamer. You have also an opportunity to learn and create a C++ Opencv app that streams video to a VLC player using GStreamer. Congratulations on achieving your goal! Otherwise, let me know what doesn’t work for you. It could be many little puzzle pieces.

We hope you enjoyed this article and found it useful. If you did, please give it a like, clap and follow me for more content like this. We would love to hear your feedback and suggestions in the comments section below. Thank you for reading and happy coding! 😊

More tutorials on https://funvision.blogspot.com

--

--

RebelsOnTheMoon

Ph.D. degree in cybernetics, computer vision enthusiast, runner, a guitar player in service of software engineering.