OpenCV 速查手册

2062 字
10 分钟
OpenCV 速查手册

面向传统计算机视觉与 RoboMaster 视觉入门的 OpenCV 快速参考。
主要基于 OpenCV 4.x,C++ 为主,同时补充 Python 常用写法。

建议收藏的官方资源:


目录#

  1. 安装与环境
  2. 常见模块与头文件
  3. 核心数据结构
  4. cv::Mat 详解
  5. 图像与视频 I/O
  6. 颜色空间与通道操作
  7. 几何变换与滤波
  8. 二值化与阈值
  9. 形态学操作
  10. 边缘检测
  11. 轮廓与几何拟合
  12. 绘制与可视化
  13. 传统视觉 Detector 思路(灯条 / 装甲板)
  14. 常用速查表
  15. 实用 Tips 与常见陷阱

1. 安装与环境#

Ubuntu(推荐新人方式)#

Terminal window
sudo apt update
sudo apt install -y libopencv-dev pkg-config cmake g++

验证:

Terminal window
pkg-config --modversion opencv4
pkg-config --cflags --libs opencv4

CMake 最小工程示例#

cmake_minimum_required(VERSION 3.16)
project(opencv_demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(OpenCV REQUIRED)
add_executable(opencv_demo main.cpp)
target_include_directories(opencv_demo PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(opencv_demo PRIVATE ${OpenCV_LIBS})

编译运行:

Terminal window
mkdir -p build && cd build
cmake ..
cmake --build . -j
./opencv_demo ../test.jpg

Python#

Terminal window
pip install opencv-python # 或 opencv-contrib-python
import cv2
print(cv2.__version__)

2. 常见模块与头文件#

模块头文件主要用途
Coreopencv2/core.hppMat、Point、Rect、Scalar、矩阵运算
Imgcodecsopencv2/imgcodecs.hppimread / imwrite
HighGUIopencv2/highgui.hppimshow、waitKey、Trackbar
Imgprocopencv2/imgproc.hpp颜色、滤波、阈值、形态学、轮廓、绘图
VideoIOopencv2/videoio.hppVideoCapture

新人可直接:

#include <opencv2/opencv.hpp>

3. 核心数据结构#

类型含义常见用途
cv::Mat多维稠密数组图像、Mask、中间结果
cv::Point / Point2f二维点像素坐标、中心、角点
cv::Point3f三维点PnP、空间几何
cv::Size / Size2f宽高图像尺寸、核尺寸
cv::Rect / Rect2f水平矩形ROI、Bounding Box
cv::Scalar最多 4 个标量颜色、阈值、初始化
cv::Vec3b3 个 uchar读取 BGR 像素
cv::RotatedRect旋转矩形灯条、细长目标拟合
cv::Moments面积、质心

常用构造#

cv::Point p(100, 50);
cv::Point2f pf(100.5f, 50.2f);
cv::Size sz(1280, 1024); // width, height
cv::Rect rect(100, 80, 300, 200); // x, y, width, height
cv::Scalar green(0, 255, 0); // BGR
cv::RotatedRect rr(cv::Point2f(300, 200), cv::Size2f(40, 120), 20.0f);

注意坐标系:图像原点在左上角,x 向右,y 向下。Mat.at(row, col) = at(y, x)


4. cv::Mat 详解#

常见类型#

类型含义场景
CV_8UC18-bit 无符号 1 通道灰度 / 二值
CV_8UC38-bit 无符号 3 通道BGR 彩色
CV_16UC116-bit 无符号 1 通道深度图
CV_32FC132-bit float 1 通道浮点计算

属性查看#

std::cout << image.rows << " " << image.cols << " "
<< image.channels() << " " << image.type() << " "
<< image.empty() << std::endl;

浅拷贝 vs 深拷贝#

cv::Mat a = image; // 共享数据(引用计数)
cv::Mat b = image.clone(); // 深拷贝
image.copyTo(b); // 显式深拷贝

像素访问#

// 灰度
uchar v = gray.at<uchar>(y, x);
// BGR
cv::Vec3b pixel = image.at<cv::Vec3b>(y, x);
uchar b = pixel[0], g = pixel[1], r = pixel[2];
// 高性能按行遍历
for (int y = 0; y < gray.rows; ++y) {
uchar* row = gray.ptr<uchar>(y);
for (int x = 0; x < gray.cols; ++x) {
// 使用 row[x]
}
}

ROI#

cv::Rect roi_rect(x, y, w, h);
cv::Mat roi = image(roi_rect); // 视图
cv::Mat roi_copy = image(roi_rect).clone(); // 独立

5. 图像与视频 I/O#

图像#

cv::Mat color = cv::imread(path, cv::IMREAD_COLOR); // BGR
cv::Mat gray = cv::imread(path, cv::IMREAD_GRAYSCALE);
if (color.empty()) { /* 失败处理 */ }
cv::imwrite("out.jpg", color);
img = cv2.imread(path, cv2.IMREAD_COLOR)
cv2.imwrite("out.jpg", img)

显示#

cv::imshow("win", image);
int key = cv::waitKey(0); // 0 = 永久等待
if (key == 27) { /* ESC */ }
cv::destroyAllWindows();

视频 / 摄像头#

cv::VideoCapture cap(path_or_index);
if (!cap.isOpened()) { /* 错误 */ }
cv::Mat frame;
while (cap.read(frame)) {
// 处理 frame
cv::imshow("frame", frame);
if (cv::waitKey(1) == 27) break;
}

6. 颜色空间与通道操作#

常用转换#

cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV);
cv::cvtColor(src, rgb, cv::COLOR_BGR2RGB); // 注意:matplotlib 等需要

HSV 注意:OpenCV 中 H 范围为 0179(不是 0360)。

通道分离 / 合并#

std::vector<cv::Mat> chs;
cv::split(image, chs); // chs[0]=B, [1]=G, [2]=R
cv::merge(chs, merged);

颜色阈值 Mask(inRange)#

cv::Scalar lower(90, 80, 80); // HSV 蓝示例
cv::Scalar upper(130, 255, 255);
cv::Mat mask;
cv::inRange(hsv, lower, upper, mask);
cv::Mat selected;
cv::bitwise_and(image, image, selected, mask);

传统 RM 中也常用通道差(如 B - R)增强灯条对比度。


7. 几何变换与滤波#

resize#

cv::resize(src, dst, cv::Size(640, 480), 0, 0, cv::INTER_LINEAR);
// 或按比例
cv::resize(src, dst, cv::Size(), 0.5, 0.5, cv::INTER_AREA);

常用滤波#

cv::GaussianBlur(src, dst, cv::Size(5, 5), 1.2);
cv::medianBlur(src, dst, 5); // 对椒盐噪声好
cv::blur(src, dst, cv::Size(5, 5)); // 均值
cv::bilateralFilter(src, dst, 9, 75, 75); // 保边

其他:

cv::flip(src, dst, 1); // 1=水平, 0=垂直, -1=两者
cv::rotate(src, dst, cv::ROTATE_90_CLOCKWISE);
cv::normalize(src, dst, 0, 255, cv::NORM_MINMAX, CV_8U);

8. 二值化与阈值#

固定阈值#

cv::threshold(gray, binary, 180, 255, cv::THRESH_BINARY);
// 常用类型:THRESH_BINARY, THRESH_BINARY_INV, THRESH_OTSU, THRESH_TOZERO

自适应阈值#

cv::adaptiveThreshold(gray, binary, 255,
cv::ADAPTIVE_THRESH_GAUSSIAN_C,
cv::THRESH_BINARY, 11, 2);

固定阈值简单可解释,但对光照变化敏感;自适应更适合局部亮度不均场景。实际工程需用真实数据验证。


9. 形态学操作#

cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
// 或 MORPH_ELLIPSE, MORPH_CROSS
cv::erode(binary, eroded, kernel);
cv::dilate(binary, dilated, kernel);
cv::morphologyEx(binary, opened, cv::MORPH_OPEN, kernel); // 去小白噪点
cv::morphologyEx(binary, closed, cv::MORPH_CLOSE, kernel); // 填小黑洞、连接断裂
操作效果
Erode白区域收缩,去细小突出
Dilate白区域扩张,填裂缝
Open先腐蚀后膨胀,去小噪点
Close先膨胀后腐蚀,连接目标

形态学不是必须步骤,只有在数据中能稳定解决问题时才加入。


10. 边缘检测#

cv::Canny(gray_or_blurred, edges, 80, 160);

Canny 对梯度敏感,常配合 GaussianBlur 使用。RM 灯条检测中若颜色/亮度二值化已足够干净,可直接找轮廓,不必强行加入 Canny。


11. 轮廓与几何拟合#

findContours#

std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(binary, contours, hierarchy,
cv::RETR_EXTERNAL, // 只外层
cv::CHAIN_APPROX_SIMPLE); // 压缩共线点

常用模式:

  • RETR_EXTERNAL:只最外层
  • RETR_TREE:完整层级
  • CHAIN_APPROX_NONE:保留所有点
  • CHAIN_APPROX_SIMPLE:压缩

常用轮廓属性#

double area = cv::contourArea(contours[i]);
double peri = cv::arcLength(contours[i], true);
cv::Rect bbox = cv::boundingRect(contours[i]);
cv::RotatedRect rrect = cv::minAreaRect(contours[i]);
cv::Moments m = cv::moments(contours[i]);
cv::Point2f center(m.m10 / m.m00, m.m01 / m.m00);

近似多边形#

std::vector<cv::Point> approx;
cv::approxPolyDP(contours[i], approx, 0.02 * peri, true);

绘制轮廓#

cv::drawContours(debug, contours, -1, cv::Scalar(0, 255, 0), 2);

RotatedRect 使用#

cv::Point2f vertices[4];
rrect.points(vertices);
// 可转成自己的 Light 结构,统一长边/短边/倾角定义

12. 绘制与可视化#

cv::line(img, pt1, pt2, color, thickness);
cv::rectangle(img, rect, color, thickness); // thickness < 0 填充
cv::circle(img, center, radius, color, thickness);
cv::putText(img, text, org, cv::FONT_HERSHEY_SIMPLEX, scale, color, thickness);
cv::fillPoly(img, {pts}, color);

颜色顺序始终是 BGR


13. 传统视觉 Detector 思路(灯条 / 装甲板)#

一套简化流水线(来自 RoboMaster 实践):

Image → Preprocess → Binary / Feature → Contours → Light Candidates → Armor Pairs → 2D Corners

最终输出示例:

struct Armor {
cv::Point2f center;
std::array<cv::Point2f, 4> corners;
};

典型步骤概览#

  1. 预处理:灰度 / HSV / 通道差 + 滤波
  2. 二值化 / Mask:固定阈值或 inRange,得到亮灯条区域
  3. 形态学(可选):开运算去噪、闭运算连接
  4. 找轮廓findContours + 面积、长宽比、角度筛选 → 得到 Light 候选
  5. 配对:根据两灯条距离、角度差、高度比等先验规则组成装甲板
  6. 几何minAreaRect 或四点拟合得到 corners 与 center

核心原则

  • OpenCV 只是工具,真正的“哪个是灯条、哪两根能组成装甲板”需要根据目标先验自己写判据。
  • 保持每一步可解释、可调试(输出中间图)。
  • 参数必须用真实赛场数据验证,而不是“感觉高级”。

14. 常用速查表#

图像读取标志#

标志含义
IMREAD_COLOR3 通道 BGR
IMREAD_GRAYSCALE单通道灰度
IMREAD_UNCHANGED原样(含 alpha)

插值方式#

标志场景
INTER_LINEAR通用放大
INTER_AREA缩小推荐
INTER_NEAREST最近邻(快)
INTER_CUBIC高质量放大

常见颜色常量(BGR)#

cv::Scalar(255, 0, 0) // 蓝
cv::Scalar(0, 255, 0) // 绿
cv::Scalar(0, 0, 255) // 红
cv::Scalar(0, 255, 255) // 黄
cv::Scalar(255, 255, 255) // 白
cv::Scalar(0, 0, 0) // 黑

15. 实用 Tips 与常见陷阱#

  1. 永远检查 empty()imread / VideoCapture 失败不会抛异常。
  2. BGR 不是 RGB:与 matplotlib、Pillow 交互时记得转换。
  3. 浅拷贝陷阱:修改 ROI 或赋值后的 Mat 可能影响原图,需要独立数据时用 clone()
  4. at(y, x):行列顺序与日常 (x, y) 习惯相反。
  5. HSV 范围:H 是 0~179。
  6. 不要盲目堆函数:每加一步就增加参数和失败模式,用数据验证必要性。
  7. 调试友好:中间结果全部 imshowimwrite,方便调参。
  8. 性能:大图循环优先 ptr,避免频繁 at;正式程序少依赖 GUI。
  9. 版本差异:以当前安装版本官方文档为准。
  10. 从工具到算法:学会 API 只是第一步,真正的 Detector 需要目标先验与可解释的规则。

附录:最小可运行示例(C++)#

#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <image>\n";
return 1;
}
cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
if (image.empty()) return 1;
cv::Mat gray, blurred, binary;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 1.2);
cv::threshold(blurred, binary, 180, 255, cv::THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
cv::Mat debug = image.clone();
cv::drawContours(debug, contours, -1, cv::Scalar(0, 255, 0), 2);
cv::imshow("original", image);
cv::imshow("binary", binary);
cv::imshow("debug", debug);
cv::waitKey(0);
return 0;
}

文档版本:2026-09
参考来源:OpenCV 官方文档 + Zhejiang University RoboMaster Vision 传统视觉教程
使用建议:边读边编译,修改参数观察结果,逐步把基础 API 组合成完整 Detector。

祝调试顺利!

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或投喂支持!

投喂
OpenCV 速查手册
https://www.infvar.com/posts/opencv/
作者
Dignite
发布于
2026-09-11
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
Dignite
技术,学习,生活,旅行。
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
站点统计
文章
158
分类
5
标签
282
总字数
338,254
运行时长
0
最后活动
0 天前

目录