C++ OpenCV 基本模块(建议收藏)

C++ OpenCV 基本模块详解

C++ OpenCV 基本模块是计算机视觉开发中最核心的组件之一,包含图像处理、矩阵操作、绘图等功能。掌握这些模块,是进行 OpenCV C++ 开发的起点。

核心概念

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,被广泛用于图像和视频处理。C++ 是 OpenCV 最推荐的开发语言之一,其基本模块主要位于 opencv2/coreopencv2/imgprocopencv2/highguiopencv2/imgcodecs 等命名空间中。

这些模块提供了图像读取、显示、转换、滤波等常用功能,是后续高级视觉算法(如目标检测、图像识别)的基石。例如,core 模块管理数据结构和核心操作,imgproc 模块处理图像变换,而 highguiimgcodecs 则负责图像的显示和读写。

基础语法

图像读取与显示

#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    Mat img = imread("image.jpg"); // 读取图像
    if (img.empty()) {
        std::cout << "图像读取失败" << std::endl; // 检查是否读取成功
        return -1;
    }
    namedWindow("展示图像"); // 创建窗口
    imshow("展示图像", img); // 显示图像
    waitKey(0); // 等待按键
    return 0;
}

矩阵创建与操作

Mat A = Mat::eye(3, 3, CV_8UC1); // 创建一个 3x3 的单位矩阵,数据类型为 8 位无符号整数
std::cout << "矩阵 A: " << std::endl << A << std::endl; // 输出矩阵
Mat B = A + 1; // 矩阵加法
std::cout << "矩阵 B: " << std::endl << B << std::endl;

颜色空间转换

cvtColor(img, imgGray, COLOR_BGR2GRAY); // 将图像从 BGR 转换为灰度图

边缘检测

Canny(imgGray, edges, 100, 200); // 使用 Canny 算法检测边缘

进阶特性

OpenCV C++ 基本模块包含多个功能模块,以下是其中几个关键模块及其功能对比:

模块名称 功能说明 使用场景 示例函数
core 核心数据结构与数学操作 矩阵运算、数据操作 Mat, Point, Scalar
imgproc 图像处理函数 边缘检测、滤波、形态学操作 Canny, blur, dilate
highgui 图像显示和交互窗口 调试图像处理流程 imshow, waitKey
imgcodecs 图像编码解码 读取和保存图像文件 imread, imwrite
videoio 视频输入输出 实时视频处理、摄像头读取 VideoCapture, VideoWriter

实战应用

1. 实时摄像头图像灰度化

#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    VideoCapture cap(0); // 打开默认摄像头
    if (!cap.isOpened()) {
        std::cout << "无法打开摄像头" << std::endl;
        return -1;
    }
    Mat frame, grayFrame;
    while (true) {
        cap >> frame; // 读取一帧图像
        if (frame.empty()) break;
        cvtColor(frame, grayFrame, COLOR_BGR2GRAY); // 转换为灰度图
        imshow("灰度视频", grayFrame); // 显示灰度图像
        if (waitKey(30) >= 0) break; // 按任意键退出
    }
    return 0;
}

2. 图像二值化处理

#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    Mat img = imread("image.jpg", IMREAD_GRAYSCALE);
    Mat binary;
    threshold(img, binary, 128, 255, THRESH_BINARY); // 阈值分割,二值化图像
    imwrite("binary_image.jpg", binary); // 保存处理后的图像
    return 0;
}

注意事项

  1. 图像路径问题
    OpenCV 的 imread 函数对图像路径非常敏感,确保文件路径正确,避免使用中文或空格路径。

  2. 数据类型匹配
    使用 Mat 矩阵时,操作前后数据类型要保持一致,否则可能导致错误或数据丢失。例如,颜色空间转换前需确认图像是否为 CV_8UC3 格式。

  3. 资源释放问题
    使用摄像头或窗口时,务必在程序结束前调用 destroyAllWindows()release(),防止资源泄露。

  4. 阈值设置不合理
    使用 threshold 等函数时,阈值设置不当可能导致图像处理效果不佳,建议配合 imshowimwrite 动态调试。

高级技巧

1. 使用 ROI(Region of Interest)提取图像区域

Mat img = imread("image.jpg");
Rect roi(100, 100, 200, 200); // 定义感兴趣区域
Mat cropped = img(roi); // 提取 ROI 区域
imwrite("cropped_image.jpg", cropped); // 保存裁剪图像

2. 自定义图像滤波器

Mat kernel = (Mat_<float>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); // 定义锐化滤波器
filter2D(img, sharpened, -1, kernel); // 应用滤波

3. 多通道图像处理

Mat bgr[3];
split(img, bgr); // 将 BGR 图像拆分为三个单通道
Mat gray;
merge(bgr, 3, imgMerged); // 合并通道

常见问题

Q1: 为什么使用 imread 读取图像后窗口不显示?
A: 检查图像路径是否正确,以及是否使用了 waitKey。如果图像为 empty(),说明文件未正确读取。

Q2: OpenCV 的 Mat 矩阵如何转换为 OpenCV 中的其他类型?
A: 使用 convertTo() 方法,例如 img.convertTo(imgFloat, CV_32F); 可将图像转为浮点型。

Q3: 如何处理图像尺寸不一致的问题?
A: 使用 resize() 函数调整图像尺寸,例如 resize(img, resizedImg, Size(200, 200));

Q4: 如何使用 OpenCV 保存处理后的图像?
A: 使用 imwrite() 函数,格式参数支持 jpgpngbmp 等常见图像格式,例如 imwrite("output.png", img);

总结

C++ OpenCV 基本模块是图像处理开发的核心,包含图像读取、显示、转换、滤波等基本功能,掌握这些模块有助于快速构建计算机视觉应用。