十二、OpenCV中的边缘检测
文章目录
- 一、边缘检测的作用是什么?
- 二、Sobel 边缘检测
- 三、Laplacian 边缘检测
- 四、Canny 边缘检测
一、边缘检测的作用是什么?
它的核心作用是:在图像中找到亮度变化剧烈的地方,这些区域往往对应着物体的边界、轮廓或结构特征。
可以把边缘检测理解成“让计算机看到图像的轮廓”比如一张人物照片,边缘检测后,人脸、头发、衣服的轮廓都会变成清晰的线条,而背景细节被去掉。这就像人类看画时的“勾线稿” —— 简洁但包含结构信息。
1.提取物体轮廓
检测出图像中的边界线,方便后续:
- 物体识别(例如:检测行人、车辆、零件轮廓)
- 形状分析(面积、周长、角度)
- 图像分割(将不同物体区域分开)
示例:
原图 → 边缘检测 → 获得物体轮廓 → 提取目标区域
2.特征提取
很多视觉算法不会直接处理整张图像,而是基于边缘、角点、纹理等特征。
边缘检测是这些特征的前置步骤,例如:
- SIFT / SURF / ORB 等特征点检测依赖梯度;
- HOG(方向梯度直方图) 用于行人检测;
- Canny 边缘 结果常被用于模板匹配或形状识别。
3.图像分割与识别
在医学影像、工业检测中,边缘能帮助:
- 分割出组织器官边界;
- 检测零件缺陷;
- 自动定位目标区域。
4.辅助视觉理解
边缘可以让系统理解场景结构:
- 识别道路边缘(自动驾驶);
- 检测文字轮廓(OCR 文字识别);
- 建立 3D 重建中的特征线。
二、Sobel 边缘检测
原理:Sobel 算子通过计算图像的梯度(gradient) 来检测边缘,分为 x 和 y 方向。
示例代码:
#include <opencv2/opencv.hpp>
using namespace cv;int main() {Mat src = imread("test.jpg", IMREAD_GRAYSCALE);if (src.empty()) return -1;Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y, grad;// 分别计算x和y方向的梯度Sobel(src, grad_x, CV_16S, 1, 0);Sobel(src, grad_y, CV_16S, 0, 1);// 转换为绝对值并合并convertScaleAbs(grad_x, abs_grad_x);convertScaleAbs(grad_y, abs_grad_y);addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);imshow("Original", src);imshow("Sobel Edge", grad);waitKey(0);return 0;
}
三、Laplacian 边缘检测
原理:Laplacian 算子是二阶导数检测算子,通过检测亮度变化的“加速度”来发现边缘。
示例代码:
#include <opencv2/opencv.hpp>
using namespace cv;int main() {Mat src = imread("test.jpg", IMREAD_GRAYSCALE);if (src.empty()) return -1;Mat lap, abs_lap;Laplacian(src, lap, CV_16S, 3);convertScaleAbs(lap, abs_lap);imshow("Original", src);imshow("Laplacian Edge", abs_lap);waitKey(0);return 0;
}
四、Canny 边缘检测
Canny 是最常用的边缘检测算法,步骤包括:
- 高斯滤波降噪
- 计算梯度强度和方向
- 非极大值抑制(NMS)
- 双阈值检测和连接边缘
示例代码:
#include <opencv2/opencv.hpp>
using namespace cv;int main() {Mat src = imread("test.jpg", IMREAD_GRAYSCALE);if (src.empty()) return -1;Mat edges;GaussianBlur(src, src, Size(3, 3), 0); // 降噪Canny(src, edges, 100, 200); // 低阈值100, 高阈值200imshow("Original", src);imshow("Canny Edge", edges);waitKey(0);return 0;
}
实时可调的 Canny 边缘检测:
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;// 全局变量
Mat src, grayImg, edgeImg;
int lowThreshold = 50; // 低阈值初始值
int maxThreshold = 200; // 高阈值最大值// 滑动条回调函数
void onCannyChange(int, void*)
{// 降噪Mat blurred;GaussianBlur(grayImg, blurred, Size(3, 3), 0);// Canny 边缘检测Canny(blurred, edgeImg, lowThreshold, lowThreshold * 3); // 高阈值设为低阈值的3倍// 显示结果imshow("Canny Edge Detection", edgeImg);
}int main()
{// 读取图像src = imread("test.jpg");if (src.empty()) {cout << "无法打开图像文件!" << endl;return -1;}// 转灰度cvtColor(src, grayImg, COLOR_BGR2GRAY);// 创建窗口namedWindow("Canny Edge Detection", WINDOW_AUTOSIZE);// 创建滑动条createTrackbar("Low Threshold", "Canny Edge Detection", &lowThreshold, maxThreshold, onCannyChange);// 初始化显示一次onCannyChange(0, 0);waitKey(0);return 0;
}