imgproc模块是 OpenCV 中最核心的图像处理模块,包含从基础色彩转换到高级形态学操作等丰富功能。
这个模块非常强大,建议从基础功能开始逐步实践,结合具体应用场景选择合适的算法组合。
常用函数速查
| 功能 | 主要函数 |
|---|---|
| 色彩转换(支持多种色彩空间) | cvtColor() |
| 滤波(去噪和平滑) | GaussianBlur(), medianBlur(), bilateralFilter() |
| 几何变换(缩放、旋转、透视) | resize(), warpAffine(), warpPerspective() |
| 阈值(二值化处理) | threshold(), adaptiveThreshold() |
| 形态学(形状操作) | erode(), dilate(), morphologyEx() |
| 边缘检测(提取边缘) | Sobel(), Laplacian(), Canny() |
| 直方图(统计分析) | calcHist(), equalizeHist() |
| 霍夫变换(检测几何形状) | HoughLines(), HoughCircles() |
| 轮廓(形状分析) | findContours(), drawContours() |
1. 色彩空间转换 (Color Conversions)
常用转换类型:
- COLOR_BGR2GRAY:彩色转灰度
- COLOR_BGR2HSV:彩色转 HSV(色调、饱和度、亮度)
- COLOR_BGR2YCrCb:彩色转 YCrCb(亮度、色度)
- COLOR_HSV2BGR:HSV 转彩色
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
Mat src = imread("test.jpg");
if (src.empty()) return -1;
Mat gray, hsv, ycrcb;
// 转换为灰度图
cvtColor(src, gray, COLOR_BGR2GRAY);
// 转换为 HSV 空间(常用于颜色分割)
cvtColor(src, hsv, COLOR_BGR2HSV);
// 转换为 YCrCb 空间
cvtColor(src, ycrcb, COLOR_BGR2YCrCb);
imshow("原图", src);
imshow("灰度图", gray);
imshow("HSV", hsv);
imshow("YCrCb", ycrcb);
waitKey(0);
return 0;
}
2. 图像滤波 (Image Filtering)
高斯模糊 (Gaussian Blur)
cpp
Mat blurred;
// 参数:输入、输出、核大小(必须为正奇数)、标准差
GaussianBlur(src, blurred, Size(5, 5), 0);
imshow("高斯模糊", blurred);
中值滤波 (Median Blur) - 去除椒盐噪声
cpp
Mat median;
// 核大小必须为大于1的奇数
medianBlur(src, median, 5);
imshow("中值滤波", median);
双边滤波 (Bilateral Filter) - 保边去噪
cpp
Mat bilateral;
// 参数:直径、颜色空间标准差、坐标空间标准差
bilateralFilter(src, bilateral, 9, 75, 75);
imshow("双边滤波", bilateral);
3. 几何变换 (Geometric Transformations)
缩放 (Resize)
cpp
Mat resized;
// 参数:目标大小、插值方法
resize(src, resized, Size(300, 300), 0, 0, INTER_LINEAR);
imshow("缩放", resized);
旋转 (Rotation)
cpp
Mat rotated;
// 获取旋转矩阵
Point2f center(src.cols/2.0, src.rows/2.0);
Mat rot_mat = getRotationMatrix2D(center, 45.0, 1.0); // 旋转45度,缩放1倍
// 应用仿射变换
warpAffine(src, rotated, rot_mat, src.size());
imshow("旋转", rotated);
透视变换 (Perspective Transform)
cpp
Mat perspective;
// 定义原图四个点和目标点
Point2f src_pts[4] = { {0,0}, {src.cols-1,0}, {0,src.rows-1}, {src.cols-1,src.rows-1} };
Point2f dst_pts[4] = { {50,50}, {src.cols-100,50}, {0,src.rows-1}, {src.cols-1,src.rows-1} };
Mat persp_mat = getPerspectiveTransform(src_pts, dst_pts);
warpPerspective(src, perspective, persp_mat, src.size());
imshow("透视变换", perspective);
4. 阈值处理 (Thresholding)
简单阈值
cpp
Mat thresh;
// 参数:阈值、最大值、类型
threshold(gray, thresh, 127, 255, THRESH_BINARY);
imshow("二值化", thresh);
自适应阈值 (Adaptive Threshold)
cpp
Mat adaptive_thresh;
// 参数:邻域大小、常数C
adaptiveThreshold(gray, adaptive_thresh, 255, ADAPTIVE_THRESH_GAUSSIAN_C,
THRESH_BINARY, 11, 2);
imshow("自适应阈值", adaptive_thresh);
Otsu 阈值 (自动确定最佳阈值)
cpp
Mat otsu;
// 必须与 THRESH_OTSU 组合使用
threshold(gray, otsu, 0, 255, THRESH_BINARY | THRESH_OTSU);
cout << "Otsu 计算的阈值: " << threshold(gray, otsu, 0, 255, THRESH_BINARY | THRESH_OTSU) << endl;
imshow("Otsu阈值", otsu);
5. 形态学操作 (Morphological Operations)
用于去除噪声、连接断开的区域等
cpp
// 创建结构元素
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat eroded, dilated, opened, closed;
// 腐蚀 (缩小白色区域)
erode(thresh, eroded, kernel);
// 膨胀 (扩大白色区域)
dilate(thresh, dilated, kernel);
// 开运算 (先腐蚀后膨胀,去噪)
morphologyEx(thresh, opened, MORPH_OPEN, kernel);
// 闭运算 (先膨胀后腐蚀,填充空洞)
morphologyEx(thresh, closed, MORPH_CLOSE, kernel);
imshow("腐蚀", eroded);
imshow("膨胀", dilated);
imshow("开运算", opened);
imshow("闭运算", closed);
6. 边缘检测 (Edge Detection)
Sobel 算子
cpp
Mat sobel_x, sobel_y, sobel;
// x方向梯度
Sobel(gray, sobel_x, CV_16S, 1, 0);
// y方向梯度
Sobel(gray, sobel_y, CV_16S, 0, 1);
// 转换为8位无符号
convertScaleAbs(sobel_x, sobel_x);
convertScaleAbs(sobel_y, sobel_y);
// 合并梯度
addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0, sobel);
imshow("Sobel边缘", sobel);
Laplacian 算子
cpp
Mat laplacian;
Laplacian(gray, laplacian, CV_16S);
convertScaleAbs(laplacian, laplacian);
imshow("Laplacian边缘", laplacian);
Canny 边缘检测 (推荐)
cpp
Mat canny_edges;
// 参数:低阈值、高阈值(推荐比例 1:2 或 1:3)
Canny(gray, canny_edges, 50, 150);
imshow("Canny边缘", canny_edges);
7. 直方图处理 (Histogram Processing)
计算和显示直方图
cpp
// 计算灰度直方图
Mat hist;
int histSize = 256;
float range[] = {0, 256};
const float* histRange = {range};
calcHist(&gray, 1, 0, Mat(), hist, 1, &histSize, &histRange);
// 绘制直方图
int hist_w = 512, hist_h = 400;
int bin_w = cvRound((double)hist_w / histSize);
Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0,0,0));
// 归一化直方图
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// 绘制折线
for(int i = 1; i < histSize; i++) {
line(histImage,
Point(bin_w*(i-1), hist_h - cvRound(hist.at<float>(i-1))),
Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))),
Scalar(255,0,0), 2, 8, 0);
}
imshow("直方图", histImage);
直方图均衡化
cpp
Mat equalized;
equalizeHist(gray, equalized);
imshow("均衡化后", equalized);
8. 图像金字塔 (Image Pyramids)
cpp
Mat pyramid;
// 高斯金字塔向下采样
pyrDown(src, pyramid);
imshow("下采样", pyramid);
// 高斯金字塔向上采样
pyrUp(pyramid, pyramid);
imshow("上采样", pyramid);
9. 霍夫变换 (Hough Transform)
霍夫直线检测
cpp
Mat edges, lines_img;
Canny(gray, edges, 50, 150);
cvtColor(edges, lines_img, COLOR_GRAY2BGR);
vector<Vec2f> lines;
// 参数:距离精度、角度精度、阈值
HoughLines(edges, lines, 1, CV_PI/180, 150);
// 绘制检测到的直线
for(size_t i = 0; i < lines.size(); i++) {
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line(lines_img, pt1, pt2, Scalar(0,0,255), 2);
}
imshow("霍夫直线", lines_img);
霍夫圆检测
cpp
Mat circles_img = src.clone();
vector<Vec3f> circles;
// 参数:方法、累加器分辨率、最小圆心距、高阈值、低阈值、最小半径、最大半径
HoughCircles(gray, circles, HOUGH_GRADIENT, 1, gray.rows/8, 200, 100, 0, 0);
for(size_t i = 0; i < circles.size(); i++) {
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(circles_img, center, radius, Scalar(0,255,0), 2);
}
imshow("霍夫圆", circles_img);
10. 轮廓检测 (Contour Detection)
cpp
Mat contours_img = Mat::zeros(thresh.size(), CV_8UC3);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
// 查找轮廓
findContours(thresh, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
// 绘制轮廓
for(size_t i = 0; i < contours.size(); i++) {
drawContours(contours_img, contours, (int)i, Scalar(0,255,0), 2);
}
imshow("轮廓", contours_img);
11. 模板匹配 (Template Matching)
cpp
Mat result;
Mat template_img = imread("template.jpg", IMREAD_GRAYSCALE); // 小模板
// 匹配方法
matchTemplate(gray, template_img, result, TM_CCOEFF_NORMED);
// 找到最佳匹配位置
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
// 在源图上绘制矩形框
rectangle(src, maxLoc, Point(maxLoc.x + template_img.cols, maxLoc.y + template_img.rows),
Scalar(0,0,255), 2);
imshow("模板匹配", src);
12. 综合示例:车牌区域检测
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main() {
Mat src = imread("car.jpg");
if (src.empty()) return -1;
Mat gray, blur, edges, morph;
// 预处理
cvtColor(src, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, blur, Size(5,5), 0);
Canny(blur, edges, 50, 150);
// 形态学闭运算连接边缘
Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 3));
morphologyEx(edges, morph, MORPH_CLOSE, kernel);
// 查找轮廓
vector<vector<Point>> contours;
findContours(morph, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 筛选可能的车牌区域
for(size_t i = 0; i < contours.size(); i++) {
Rect rect = boundingRect(contours[i]);
float aspect_ratio = (float)rect.width / rect.height;
// 根据长宽比和面积筛选
if(aspect_ratio > 2.0 && aspect_ratio < 5.0 && rect.area() > 1000) {
rectangle(src, rect, Scalar(0,255,0), 2);
}
}
imshow("车牌检测", src);
waitKey(0);
return 0;
}