Axi's Blog
RoboMaster 视觉组第三次培训Blur image

前言#

本教程为 RoboMaster 视觉组第三次培训,主要内容为 OpenCV 的安装以及使用。

安装 OpenCV#

在安装 OpenCV 之前需要安装部分的依赖:

sudo apt install libgtk2.0-dev
bash

一般来说,可以直接使用源代码对于 OpenCV 进行编译安装,代码如下:

wget https://github.com/opencv/opencv/archive/4.8.0.zip opencv-4.8.0.zip
unzip opencv-4.8.0.zip
cd opencv-4.8.0
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
bash

OpenCV 是 C++ 的库,因此可以使用 CMakeList 来使用。

此时的 CMakeLists.txt 在依次的地方添加:

find_package(OpenCV REQUIRED)
include_directories(
    ${OpenCV_INCLUDE_DIRS}
)
target_link_libraries(test
    ${OpenCV_LIBS}
)
cmake

此时在 main.cpp 中添加语句 #include <opencv2/core.hpp> 或者 #include <opencv4/opencv2/core.hpp> 并且进行编译,假如通过就没有问题。

OpenCV 基础#

图像的本质#

在计算机中,图像是以矩阵的形式存储的。彩色图片通常由三个通道(如 BGR)组成,而灰度图只有一个通道。OpenCV 使用 cv::Mat 数据类型来表示图像,它包含两部分数据:

  • 矩阵头 (Matrix Header):包含矩阵的大小、存储方法、存储位置等信息。
  • 指向像素值的指针:一个指向实际存储像素值的矩阵的指针。

cv::Mat 的常用构造与操作:

  • 构造函数cv::Mat(rows, cols, type, Scalar(value)) 是其经典构造函数,可以指定行、列、数据类型(如 CV_8UC3 代表 8位无符号3通道图像)和初始值。
  • 赋值与拷贝cv::Mat 支持直接通过等号赋值或拷贝构造。clone()copyTo() 函数可以实现底层矩阵的深度拷贝。
  • 访问成员
    • .rows.cols:获取矩阵的行数和列数。
    • .channels():获取图像的通道数。
    • .empty():返回一个布尔值,判断矩阵是否为空。
    • .at<Vec3b>(i, j)[t]:访问坐标为 (i, j) 的像素点的第 t 个通道的值。

OpenCV 基本操作#

读取与显示#

  • 读取图片cv::Mat src = imread("你的图片路径");
  • 显示图片cv::imshow("窗口名", src);
  • 等待按键cv::waitKey(0);,如果参数为0,则无限等待直到有按键按下。
  • 读取视频
    1. 创建 cv::VideoCapture 对象:cv::VideoCapture capture;
    2. 打开视频文件:capture.open("你的视频路径");
    3. 逐帧读取:在一个循环中使用 capture >> pic; 来读取下一帧。
    4. 循环播放:可以通过 capture.get(cv::CAP_PROP_FRAME_COUNT) 获取总帧数,判断播放结束后使用 capture.set(cv::CAP_PROP_POS_FRAMES, 0) 回到视频开头。

绘制图案#

在图像上绘制点、线、形状和文字对于调试和结果可视化至关重要。

  • 数据结构cv::Point 是一个核心数据类型,用于表示点的坐标。
  • 绘制圆形void circle(img, center, radius, color, thickness);
  • 绘制直线void line(img, pt1, pt2, color, thickness);
  • 绘制文字void putText(img, text, org, fontFace, fontScale, color, thickness);
  • 绘制折线/多边形void polylines(img, pts, isClosed, color, thickness);

图像预处理#

预处理旨在对原始图像进行初步筛选和优化,以便后续的特征提取。

滤波 (Filtering)#

滤波是一种平滑处理,主要用于去除图像中的噪声。

  • 均值滤波 (blur):使用一个所有元素值都相等的卷积核(如 3x3 大小的核,每个元素为 1/9)对图像进行卷积,将每个像素替换为其邻域像素的平均值。这会使图像变得模糊。
  • 高斯滤波 (GaussianBlur):使用基于高斯函数生成的卷积核,中心点的权重最大,离中心越远的像素权重越小。这种方法在去除噪声的同时,能更好地保留图像的边缘信息。

二值化 (Binarization)#

二值化根据设定的阈值将图像转换为只有黑白两色的图像,以突出感兴趣的区域。

  • 色彩空间转换:在二值化之前,通常需要将图像从 BGR 色彩空间转换到更符合人类视觉感知的 HSV 空间 (cv::cvtColor(src, dst, cv::COLOR_BGR2HSV);)。HSV 将颜色分为色相 (H)、饱和度 (S) 和亮度 (V)。
  • 彩色二值化 (inRange):在 HSV 空间下,可以设定一个颜色范围的上限和下限,使用 inRange 函数提取出这个范围内的所有像素,生成二值图。
  • 灰度二值化 (threshold):首先将图像转为灰度图 (cv::cvtColor(img, gray_img, cv::COLOR_BGR2GRAY);),然后使用 threshold 函数,将灰度值在指定阈值范围内的像素设为白色,其余设为黑色。

形态学操作 (Morphological Operations)#

膨胀和腐蚀是常用于二值图像的形态学操作,用以优化形状或减少噪声。

  • 膨胀 (dilate):扩展图像中的白色区域,可以用于填充小孔洞或连接断开的目标。
  • 腐蚀 (erode):收缩图像中的白色区域,可以用于消除小的噪声点或分离粘连的物体。
  • 开操作 (Opening):先进行腐蚀操作,然后进行膨胀操作。主要作用是去除小的噪声斑点,并分离连接的物体。
  • 闭操作 (Closing):先进行膨胀操作,然后进行腐蚀操作。主要作用是填充物体内部的小孔洞,并连接邻近的物体。

图像特征获取#

在预处理后的二值图上,我们可以提取轮廓等形状特征。

寻找轮廓#

使用 findContours 函数可以检测出二值图像中所有物体的轮廓。

  • 函数原型: cv::findContours(image, contours, hierarchy, mode, method);
  • 参数说明:
    • image: 输入的必须是二值图像。
    • contours: 用于存储所有找到的轮廓,通常是 vector<vector<Point>> 类型。
    • hierarchy: 存储轮廓之间的层级关系。
    • mode: 轮廓的检索模式,如 RETR_EXTERNAL(只检索最外层轮廓)或 RETR_TREE(检索所有轮廓并重建嵌套结构)。
    • method: 轮廓的逼近方法,如 CHAIN_APPROX_SIMPLE(压缩水平、垂直和对角线段,只保留端点)。

分析轮廓特征#

找到轮廓后,可以通过计算其几何特征来进行筛选和识别。

  • 面积 (contourArea):计算轮廓的面积。
  • 外接矩形 (boundingRect):找到包围轮廓的最小正立矩形,返回一个 cv::Rect 对象,包含矩形的坐标和宽高。
  • 长宽比:通过外接矩形的 widthheight 计算物体的长宽比 (aspectRatio = width / height)。
  • 面积比:通过计算轮廓面积与外接矩形面积的比值,可以用来区分不同形状的物体 (areaRatio = contourArea / boundingRectArea)。
RoboMaster 视觉组第三次培训
https://axi-blog.pages.dev/blog/rm-tutorial-section-3
Author 阿汐
Published at August 7, 2025
Comment seems to stuck. Try to refresh?✨