opencv学习笔记
这里写自定义目录标题
- 数据结构
-
- cv::Mat
- cv::Matx (小型矩阵)
- cv::Point
- cv::Rect
- cv::Scalar
- cv::Size
- cv::Vec
- cv::KeyPoint
- cv::DMatch
- cv::RotatedRect
- cv::InputArray / OutputArray
- 图像变换
-
- 色彩空间
- 几何变换
-
- 1. 仿射变换 (Affine Transformation)
-
- 平移变换 (Translation)
- 旋转变换 (Rotation)
- 缩放变换 (Scaling)
- 2. 投影变换 (Perspective Transformation)
- 3. 插值方法 (Interpolation)
-
- INTER_NEAREST - 最近邻插值
- INTER_LINEAR - 双线性插值
- INTER_CUBIC - 双三次插值
- INTER_LANCZOS4 - Lanczos插值
- 图像滤波
-
- 线性滤波
-
- 方框滤波 (Box Filter)
- 高斯滤波 (Gaussian Blur)
- 非线性滤波
-
- 中值滤波 (Median Blur)
- 双边滤波 (Bilateral Filter)
- 形态学滤波
-
- 腐蚀 (Erosion)
- 膨胀 (Dilation)
- 开运算 (Opening)
- 闭运算 (Closing)
- 边缘检测滤波器
-
- Sobel算子
- Scharr算子
- Laplacian算子
- Canny边缘检测
- 边缘检测滤波器比较
- 选择建议
- 关键参数说明
- 滤波方法选择指南
- 图像分割
-
- 基于阈值的分割
-
- 简单阈值分割
- 自适应阈值分割
- 基于边缘的分割
-
- Canny边缘检测
- 边缘连接与轮廓提取
- 基于区域的分割
-
- 区域生长法
- 分水岭算法 (Watershed)
- 基于图论的分割
-
- GrabCut算法
- 基于聚类的分割
-
- K-means聚类分割
- Mean-Shift分割
- 特征提取
-
- 颜色特征
-
- 颜色直方图 (Color Histogram)
- 颜色矩 (Color Moments)
- 纹理特征
-
- 灰度共生矩阵 (GLCM - Gray Level Co-occurrence Matrix)
- LBP (Local Binary Pattern)
- HOG (Histogram of Oriented Gradients)
- 形状特征
-
- 轮廓特征
- Hu矩不变量 (Hu Moments)
- 关键点与描述符
-
- SIFT (Scale-Invariant Feature Transform)
- SURF (Speeded-Up Robust Features)
- ORB (Oriented FAST and Rotated BRIEF)
- BRISK (Binary Robust Invariant Scalable Keypoints)
- 关键点与描述符的应用
- 深度特征
-
- 使用预训练深度学习模型
- 特征提取方法选择指南
- 特征提取流程总结
数据结构
cv::Mat
用于存储多维数组(如图像、矩阵),是 OpenCV 最核心的数据结构。
#include <opencv2/opencv.hpp>
cv::Mat img = cv::imread("image.jpg"); // 读取图像为 Mat 对象
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); // 转换为灰度图
cv::Matx (小型矩阵)
固定大小的轻量矩阵,常用于小规模运算。
cv::Matx33f matx(1, 0, 0, 0, 1, 0, 0, 0, 1); // 3x3 单位矩阵
float val = matx(1, 1); // 访问元素
cv::Point
表示二维点,模板类支持多种数据类型(如 int
, float
)。
cv::Point pt1(10, 20); // 整数坐标点
cv::Point2f pt2(5.5f, 3.2f); // 浮点坐标点
cv::circle(img, pt1, 5, cv::Scalar(0, 255, 0), -1); // 绘制点
cv::Rect
表示矩形区域,包含左上角坐标和宽高。
cv::Rect roi(50, 50, 100, 100); // x, y, width, height
cv::Mat cropped = img(roi); // 裁剪图像区域
cv::rectangle(img, roi, cv::Scalar(255, 0, 0), 2); // 绘制矩形
cv::Scalar
存储 1-4 个通道的数值,常用于表示颜色。
cv::Scalar color(0, 0, 255); // BGR 颜色 (红色)
cv::Mat blank(300, 300, CV_8UC3, color); // 创建纯色图像
cv::Size
表示尺寸(宽度和高度)。
cv::Size sz(640, 480);
cv::resize(img, img, sz); // 调整图像尺寸
cv::Vec
模板类表示固定长度的向量,常用于像素值访问。
cv::Vec3b pixel = img.at<cv::Vec3b>(10, 10); // 获取 BGR 像素值
pixel[0] = 255; // 修改蓝色通道值
cv::KeyPoint
存储特征点检测结果(如 SIFT、ORB)。
std::vector<cv::KeyPoint> keypoints;
cv::Ptr<cv::FeatureDetector> detector = cv::ORB::create();
detector->detect(img, keypoints); // 检测特征点
cv::drawKeypoints(img, keypoints, img); // 绘制特征点
cv::DMatch
存储特征匹配结果。
std::vector<cv::DMatch> matches;
cv::BFMatcher matcher(cv::NORM_HAMMING);
matcher.match(descriptors1, descriptors2, matches); // 特征匹配
cv::RotatedRect
表示旋转矩形(中心点、尺寸、旋转角度)。
cv::RotatedRect rRect(cv::Point2f(100, 100), cv::Size2f(50, 30), 45);
cv::Point2f vertices[4];
rRect.points(vertices); // 获取四个顶点
cv::InputArray / OutputArray
通用输入/输出接口,支持 Mat、vector 等。
void processImage(cv::InputArray input, cv::OutputArray output) {cv::Mat img = input.getMat();cv::cvtColor(img, output, cv::COLOR_BGR2GRAY);
}
图像变换
色彩空间
特性 | RGB | HSV | YUV/YCbCr |
---|---|---|---|
核心组成 | 红、绿、蓝 | 色相、饱和度、明度 | 亮度、色度(蓝色差、红色差) |
模型类型 | 加色模型 (用于发光设备) | 用户直观模型 (基于感知) | 亮度-色度分离模型 |
设计目的 | 匹配显示器硬件 | 方便人类理解和选择颜色 | 高效压缩、兼容黑白电视 |
优点 | 硬件原生支持,处理快 | 非常直观,易于颜色操作和分割 | 利用人眼特性实现高效压缩 |
主要缺点 | 不符合直觉,亮色耦合 | 需要与RGB转换才能显示 | 不直观,不适合直接编辑 |
典型应用 | 所有显示器、数码成像、游戏图形 | 颜色选择器、图像处理、颜色分割 | 视频编码 (H.264/HEVC)、电视广播、JPEG |
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>using namespace cv;
using namespace std;// 创建测试图像 - 彩色渐变
Mat createTestImage(int width, int height) {Mat image(height, width, CV_8UC3);for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {// 创建从红到蓝的渐变Vec3b& pixel = image.at<Vec3b>(y, x);pixel[0] = static_cast<uchar>(255 * x / width); // Bluepixel[1] = static_cast<uchar>(255 * y / height); // Green pixel[2] = static_cast<uchar>(255 * (1 - x / width)); // Red}}return image;
}// 显示RGB图像及其通道
void displayRGB(const Mat& image) {cout << "显示RGB色彩空间..." << endl;// 分离RGB通道vector<Mat> rgbChannels;split(image, rgbChannels);// 创建各个通道的显示图像(单通道显示为灰度)Mat redChannel, greenChannel, blueChannel;// 创建纯黑图像作为背景Mat black = Mat::zeros(image.size(), CV_8UC1);// 合并通道来显示单个颜色通道vector<Mat> channels;// 红色通道channels = {black, black, rgbChannels[2]}; // B, G, Rmerge(channels, redChannel);// 绿色通道channels = {black, rgbChannels[1], black};merge(channels, greenChannel);// 蓝色通道channels = {rgbChannels[0], black, black};merge(channels, blueChannel);// 显示图像imshow("1. RGB - 原始图像", image);imshow("2. RGB - 红色通道", redChannel);imshow("3. RGB - 绿色通道", greenChannel);imshow("4. RGB - 蓝色通道", blueChannel);waitKey(0);destroyAllWindows();
}// 显示HSV图像及其通道
void displayHSV(const Mat& image) {cout << "显示HSV色彩空间..." << endl;Mat hsvImage;cvtColor(image, hsvImage, COLOR_BGR2HSV);// 分离HSV通道vector<Mat> hsvChannels;split(hsvImage, hsvChannels);// 显示各个通道imshow("5. HSV - 原始BGR图像", image);imshow("6. HSV - 色相 (Hue) 通道", hsvChannels[0]); // 色相imshow("7. HSV - 饱和度 (Saturation) 通道", hsvChannels[1]); // 饱和度imshow("8. HSV - 明度 (Value) 通道", hsvChannels[2]); // 明度// 解释:色相通道看起来像灰度图,但实际上每个灰度值代表一个颜色角度cout << "注意:色相通道中,不同的灰度值代表不同的颜色角度(0-180°,OpenCV中H范围是0-180)" << endl;waitKey(0);destroyAllWindows();
}// 显示YUV图像及其通道
void displayYUV(const Mat& image) {cout << "显示YUV色彩空间..." << endl;Mat yuvImage;cvtColor(image, yuvImage, COLOR_BGR2YUV);// 分离YUV通道vector<Mat> yuvChannels;split(yuvImage, yuvChannels);// 显示各个通道imshow("9. YUV - 原始BGR图像", image);imshow("10. YUV - 亮度 (Y) 通道", yuvChannels[0]); // 亮度imshow("11. YUV - 色度 U (Cb) 通道", yuvChannels[1]); // 蓝色差imshow("12. YUV - 色度 V (Cr) 通道", yuvChannels[2]); // 红色差// 解释YUV通道的含义cout << "Y通道:亮度信息,相当于黑白图像" << endl;cout << "U通道:蓝色差信息(B-Y)" << endl;cout << "V通道:红色差信息(R-Y)" << endl;waitKey(0);destroyAllWindows();
}// 显示颜色分割示例(使用HSV)
void displayColorSegmentation(const Mat& image) {cout << "演示HSV在颜色分割中的应用..." << endl;Mat hsvImage;cvtColor(image, hsvImage, COLOR_BGR2HSV);// 定义要检测的红色范围(在HSV空间中)Scalar lower_red1(0, 70, 50); // 红色范围1(0-10°)Scalar upper_red1(10, 255, 255);Scalar lower_red2(170, 70, 50); // 红色范围2(170-180°)Scalar upper_red2(180, 255, 255);// 创建掩码Mat mask1, mask2, redMask;inRange(hsvImage, lower_red1, upper_red1, mask1);inRange(hsvImage, lower_red2, upper_red2, mask2);redMask = mask1 | mask2;// 应用掩码到原图Mat result;image.copyTo(result, redMask);// 显示结果imshow("13. 原始图像", image);imshow("14. 红色区域掩码", redMask);imshow("15. 颜色分割结果 - 只保留红色", result);cout << "HSV颜色分割完成!可以看到只有红色区域被保留下来。" << endl;waitKey(0);destroyAllWindows();
}int main() {cout << "开始演示不同色彩空间的图像表示..." << endl;cout << "=========================================" << endl;// 创建测试图像Mat testImage = createTestImage(400, 300);// 显示各个色彩空间displayRGB(testImage);displayHSV(testImage);displayYUV(testImage);// 创建另一个测试图像(包含明显的红色区域)Mat colorImage(300, 400, CV_8UC3, Scalar(100, 100, 100));// 添加一些红色区域rectangle(colorImage, Point(50, 50), Point(150, 150), Scalar(0, 0, 255), -1); // 红色矩形rectangle(colorImage, Point(200, 100), Point(300, 200)