Finding OpenCV
OpenCV ships CMake config files with every installation, making discovery straightforward. The library exports a single package with selectable components:
# Basic OpenCV discovery
cmake_minimum_required(VERSION 3.20)
project(VisionApp LANGUAGES CXX)
find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui dnn)
add_executable(vision_app main.cpp)
target_link_libraries(vision_app PRIVATE ${OpenCV_LIBS})
# Print version and modules found
message(STATUS "OpenCV version: ${OpenCV_VERSION}")
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
message(STATUS "OpenCV include path: ${OpenCV_INCLUDE_DIRS}")
If OpenCV is installed to a custom location:
# Point CMake to OpenCV's config directory
set(OpenCV_DIR "/opt/opencv-4.9/lib/cmake/opencv4" CACHE PATH "OpenCV cmake config")
# Or use CMAKE_PREFIX_PATH
list(APPEND CMAKE_PREFIX_PATH "/opt/opencv-4.9")
find_package(OpenCV 4.5 REQUIRED)
${OpenCV_LIBS}) and modern imported targets (opencv_core, opencv_imgproc). For new projects, prefer the imported targets for proper transitive dependency handling.
# Using imported targets (OpenCV 4.x modern approach)
find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui)
add_executable(processor main.cpp)
target_link_libraries(processor PRIVATE
opencv_core
opencv_imgproc
opencv_highgui
)
Selecting Modules
OpenCV is modular — only link what you need to minimize binary size and build times:
# Common module groupings by use case
find_package(OpenCV REQUIRED COMPONENTS
# Core functionality
core # Mat, basic operations, memory management
imgproc # Filtering, transforms, color conversion
# I/O and display
imgcodecs # Image file reading/writing (PNG, JPEG, etc.)
highgui # Window management, trackbars, mouse events
videoio # Video capture and writing
# Computer vision
features2d # Feature detection (ORB, SIFT, AKAZE)
calib3d # Camera calibration, stereo, 3D reconstruction
objdetect # Cascade classifiers, HOG
# Deep learning
dnn # Neural network inference (ONNX, TensorFlow, Caffe)
)
add_executable(detector detector.cpp)
target_link_libraries(detector PRIVATE ${OpenCV_LIBS})
// detector.cpp — OpenCV module usage example
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>
int main() {
// Load an image
cv::Mat image = cv::imread("input.jpg");
if (image.empty()) {
std::cerr << "Failed to load image\n";
return 1;
}
// Convert to grayscale (imgproc)
cv::Mat gray;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
// Apply Gaussian blur (imgproc)
cv::Mat blurred;
cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 1.5);
// Edge detection (imgproc)
cv::Mat edges;
cv::Canny(blurred, edges, 50, 150);
// Display result (highgui)
cv::imshow("Edges", edges);
cv::waitKey(0);
return 0;
}
CUDA Acceleration
OpenCV's CUDA modules provide GPU-accelerated versions of many imgproc and video functions:
# OpenCV with CUDA support
cmake_minimum_required(VERSION 3.20)
project(GpuVision LANGUAGES CXX CUDA)
find_package(OpenCV REQUIRED COMPONENTS
core imgproc highgui
cudaimgproc cudafilters cudawarping cudaarithm
)
# Check if OpenCV was built with CUDA
if(NOT OpenCV_CUDA_VERSION)
message(FATAL_ERROR "OpenCV was not built with CUDA support")
endif()
message(STATUS "OpenCV CUDA version: ${OpenCV_CUDA_VERSION}")
add_executable(gpu_vision gpu_processor.cpp)
target_link_libraries(gpu_vision PRIVATE ${OpenCV_LIBS})
// gpu_processor.cpp — CUDA-accelerated OpenCV
#include <opencv2/core.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudafilters.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
int main() {
// Check CUDA device availability
int cuda_devices = cv::cuda::getCudaEnabledDeviceCount();
if (cuda_devices == 0) {
std::cerr << "No CUDA devices found\n";
return 1;
}
std::cout << "CUDA devices: " << cuda_devices << "\n";
cv::Mat host_image = cv::imread("input.jpg");
cv::cuda::GpuMat gpu_image, gpu_gray, gpu_blurred;
// Upload to GPU
gpu_image.upload(host_image);
// GPU color conversion
cv::cuda::cvtColor(gpu_image, gpu_gray, cv::COLOR_BGR2GRAY);
// GPU Gaussian blur
auto filter = cv::cuda::createGaussianFilter(
CV_8UC1, CV_8UC1, cv::Size(5, 5), 1.5);
filter->apply(gpu_gray, gpu_blurred);
// Download result back to CPU
cv::Mat result;
gpu_blurred.download(result);
cv::imshow("GPU Result", result);
cv::waitKey(0);
return 0;
}
opencv_contrib Integration
The opencv_contrib repository provides extra modules (ArUco markers, text detection, tracking, etc.) not included in the main distribution. These must be built from source:
# Clone both repositories
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git
cd opencv
git checkout 4.9.0
cd ../opencv_contrib
git checkout 4.9.0
# Build with contrib modules
cd ../opencv
mkdir build && cd build
cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/opencv-4.9 \
-DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-DBUILD_EXAMPLES=OFF \
-DBUILD_TESTS=OFF \
-DWITH_CUDA=ON \
-DCUDA_ARCH_BIN="8.6" \
-DOPENCV_DNN_CUDA=ON
cmake --build . --parallel 8
cmake --install .
# Using contrib modules in your project
find_package(OpenCV REQUIRED COMPONENTS
core imgproc
aruco # ArUco marker detection (contrib)
xfeatures2d # SURF, BRIEF descriptors (contrib)
tracking # Object tracking algorithms (contrib)
text # Text detection/recognition (contrib)
)
add_executable(aruco_app aruco_detect.cpp)
target_link_libraries(aruco_app PRIVATE ${OpenCV_LIBS})
Building from Source
Building OpenCV from source gives you full control over enabled modules, optimizations, and third-party integrations:
# Superbuild pattern for OpenCV
include(ExternalProject)
ExternalProject_Add(opencv_build
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.9.0
GIT_SHALLOW ON
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DBUILD_LIST=core,imgproc,highgui,dnn,imgcodecs,videoio
-DBUILD_SHARED_LIBS=ON
-DBUILD_TESTS=OFF
-DBUILD_PERF_TESTS=OFF
-DBUILD_EXAMPLES=OFF
-DWITH_FFMPEG=ON
-DWITH_TBB=ON
-DWITH_OPENMP=ON
-DOPENCV_GENERATE_PKGCONFIG=ON
BUILD_COMMAND cmake --build <BINARY_DIR> --parallel 8
)
BUILD_LIST CMake variable restricts which modules OpenCV builds. This dramatically reduces compile time — a full OpenCV build can take 30+ minutes, while a focused build with 5-6 modules finishes in under 5 minutes.
OpenCV with ONNX Runtime
OpenCV's DNN module can load ONNX models directly for inference, but for maximum performance you may want to combine OpenCV preprocessing with ONNX Runtime inference:
# OpenCV + ONNX Runtime side by side
cmake_minimum_required(VERSION 3.20)
project(InferenceApp LANGUAGES CXX)
find_package(OpenCV REQUIRED COMPONENTS core imgproc dnn)
find_package(onnxruntime REQUIRED)
add_executable(inference inference.cpp)
target_link_libraries(inference PRIVATE
${OpenCV_LIBS}
onnxruntime::onnxruntime
)
// inference.cpp — OpenCV preprocessing + DNN inference
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>
int main() {
// Load ONNX model via OpenCV DNN
cv::dnn::Net net = cv::dnn::readNetFromONNX("model.onnx");
// Select backend (CUDA if available)
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
// Preprocess input image
cv::Mat image = cv::imread("input.jpg");
cv::Mat blob = cv::dnn::blobFromImage(
image, 1.0/255.0, cv::Size(640, 640),
cv::Scalar(0, 0, 0), true, false);
// Run inference
net.setInput(blob);
cv::Mat output = net.forward();
std::cout << "Output shape: " << output.size << "\n";
return 0;
}
Cross-Platform Considerations
OpenCV behaves differently across platforms. Handle these variations in your CMakeLists.txt:
# Cross-platform OpenCV project
cmake_minimum_required(VERSION 3.20)
project(CrossPlatformVision LANGUAGES CXX)
# Platform-specific OpenCV hints
if(WIN32)
# Windows: OpenCV from pre-built binaries
set(OpenCV_DIR "C:/opencv/build" CACHE PATH "OpenCV build directory")
elseif(APPLE)
# macOS: OpenCV from Homebrew
list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt/opencv")
endif()
# Linux: system package or /usr/local (no hints needed)
find_package(OpenCV 4.5 REQUIRED COMPONENTS core imgproc highgui)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE ${OpenCV_LIBS})
# Platform-specific video backend selection
if(WIN32)
target_compile_definitions(app PRIVATE CV_BACKEND_MSMF)
elseif(APPLE)
target_compile_definitions(app PRIVATE CV_BACKEND_AVFOUNDATION)
else()
target_compile_definitions(app PRIVATE CV_BACKEND_V4L2)
endif()
${OpenCV_VERSION} matches your development environment, especially in CI pipelines that may have a different system OpenCV installed.
- Use
BUILD_LISTto limit modules when building from source - Prefer imported targets (
opencv_core) over${OpenCV_LIBS}variable - Set
OpenCV_DIRto the directory containingOpenCVConfig.cmake - Use CUDA modules for batch processing — overhead makes single-image GPU slower
- Pin the OpenCV version in
find_package()for reproducible builds - Build contrib from source when you need specialized modules