十二、OpenCV中的边缘检测

一、边缘检测的作用是什么?

它的核心作用是:在图像中找到亮度变化剧烈的地方,这些区域往往对应着物体的边界、轮廓或结构特征。
可以把边缘检测理解成“让计算机看到图像的轮廓”比如一张人物照片,边缘检测后,人脸、头发、衣服的轮廓都会变成清晰的线条,而背景细节被去掉。这就像人类看画时的“勾线稿” —— 简洁但包含结构信息。

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 是最常用的边缘检测算法,步骤包括:

  1. 高斯滤波降噪
  2. 计算梯度强度和方向
  3. 非极大值抑制(NMS)
  4. 双阈值检测和连接边缘

示例代码:

#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, 高阈值200

    imshow("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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值