OpenCV 边缘检测 Canny

1. Canny边缘检测

Canny 是最经典、最常用的边缘检测算法 ,目标:低误检、定位准、边缘单像素细线条

2. 算法四大核心步骤
  1. 高斯滤波降噪
    边缘检测对噪声极敏感,先用高斯模糊抹平噪点(Canny 内部自带)。
  2. Sobel 求梯度幅值 + 方向
    计算每个像素灰度变化大小、梯度方向(0°、45°、90°、135° 四类)。
  3. 非极大值抑制(NMS)【Canny 精髓】
    把梯度方向上不是局部最大值的像素置 0,把宽粗的边缘压缩成单像素细线,这是 Sobel 没有的一步OpenCV-Pyt...。
  4. 双阈值滞后判断(Hysteresis)
    • 梯度 > 高阈值:强边缘(确定是边缘)
    • 梯度 < 低阈值:直接舍弃,不是边缘
    • 中间(弱边缘):只有和强边缘连通,才保留,否则丢弃

推荐比例:高阈值:低阈值 = 2:1 ~ 3:1,你代码里 40 : 120 = 1:3,是标准配置OpenCV

3. 函数原型
cpp 复制代码
void Canny(
    InputArray image,
    OutputArray edges,
    double threshold1,  // 低阈值
    double threshold2,  // 高阈值
    int apertureSize = 3, // Sobel核大小
    bool L2gradient = false // 梯度计算方式
);
cpp 复制代码
void MainWindow::onCanny()
{
    cv::Mat gray;
    cv::cvtColor(srcMat, gray,cv::COLOR_BGR2GRAY);

    cv::Mat dst;
    cv::Canny(gray,srcMat, 40, 120);
    showMat(srcMat);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Sobel X

cpp 复制代码
void MainWindow::on_btnSobelX_clicked()
{
    cv::Mat gray, sobel;
    cv::cvtColor(srcMat, gray, cv::COLOR_BGR2GRAY);
    cv::Sobel(gray, sobel, CV_16S, 1, 0, 3);
    cv::convertScaleAbs(sobel, srcMat);
    showMat(srcMat);
}

Laplacian

cpp 复制代码
void MainWindow::on_btnLaplacian_clicked()
{
    cv::Mat gray, lap;
    cv::cvtColor(srcMat, gray, cv::COLOR_BGR2GRAY);
    cv::Laplacian(gray, lap, CV_16S, 3);
    cv::convertScaleAbs(lap, srcMat);
    showMat(srcMat);
}
4. 轮廓检测
cpp 复制代码
void MainWindow::on_btnContour_clicked() 
{
    // 1. 定义两个Mat,用来存灰度图、二值图
    cv::Mat gray, bin;
    // 2. BGR彩色图 → 单通道灰度图
    cv::cvtColor(srcMat, gray, cv::COLOR_BGR2GRAY);

    // 3. 灰度图 → 二值图(黑白图)
    cv::threshold(gray, bin, 100, 255, cv::THRESH_BINARY);

    // 4. 轮廓容器:contours存所有轮廓点集;hierarchy存轮廓层级关系
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;

    // 5. 查找轮廓
    cv::findContours(bin, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    // 6. 拷贝原图,在副本上画轮廓,避免直接修改原图
    cv::Mat draw = srcMat.clone();
    // 7. 在draw图上绘制轮廓
    cv::drawContours(draw, contours, -1, cv::Scalar(0,0,255), 2);

    // 8. 把画完轮廓的图赋值给srcMat,替换当前图
    srcMat = draw;
    // 9. 调用自定义函数刷新UI显示
    showMat(srcMat);
}

1. threshold(gray, bin, 100, 255, cv::THRESH_BINARY)

阈值二值化:

  • gray:输入灰度图
  • bin:输出二值图
  • 100:阈值
  • 255:大于阈值的像素设置成的值
  • THRESH_BINARY 规则:
    • 像素 > 100 → 置 255(白色)
    • 像素 ≤ 100 → 置 0(黑色)

⚠️ 坑点:这个阈值 100 是固定死的,光照一变效果就崩,后面可以改成自适应阈值 adaptiveThreshold

2. std::vector<std::vector<cv::Point>> contours

  • contours:轮廓数组
    • 外面一层 vector:有多少个轮廓
    • 里面一层 vector<cv::Point>:一个轮廓上所有的坐标点

示例:contours[0] 就是第 0 个轮廓的全部点

3. std::vector<cv::Vec4i> hierarchy

轮廓层级信息,每个轮廓对应一个 Vec4i = [next, prev, child, parent]

  • 本代码用的是 RETR_EXTERNAL,只找最外层轮廓,不抓取内部孔洞,所以 hierarchy 基本用不上

4. findContours(bin, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE)

这是核心函数:从二值图里寻找白色区域的轮廓

  • 参数 1:输入图,必须是二值图(黑白)
  • 参数 2、3:输出轮廓和层级
  • cv::RETR_EXTERNAL:只提取最外层轮廓 ,忽略内部孔洞轮廓(比如圆环,只会拿到外圈,内圈丢掉) 可选对比:
    RETR_TREE:提取所有轮廓,保留完整父子嵌套关系(适合孔洞检测)
  • cv::CHAIN_APPROX_SIMPLE:轮廓点压缩 比如一条直线,只保留起点终点,丢掉中间冗余点,节省内存; 另一个选项 CHAIN_APPROX_NONE:保存轮廓上每一个像素点,点会非常多

5. drawContours(draw, contours, -1, cv::Scalar(0,0,255), 2)

在图像上绘制轮廓

  • draw:在哪张图上画
  • contours:轮廓集合
  • -1:绘制所有轮廓;填 0 就是只画第 0 个轮廓
  • cv::Scalar(0,0,255):BGR,也就是红色
  • 2:线条粗细,单位像素;填 cv::FILLED 就是把轮廓内部填充

6. srcMat = draw; showMat(srcMat);

把画好轮廓的图覆盖掉成员变量 srcMat,下一次再点按钮,会在上一次画了红线的图上继续处理。

原图 (BGR) → 转灰度 → 固定阈值二值化 → 提取最外层物体轮廓 → 红色线条画在原图副本上 → 刷新 UI 显示

相关推荐
杰克尼1 小时前
今日面试题总结
java·开发语言·人工智能·langchain
TMT星球1 小时前
“什么值得买”兴趣消费服务接入乐奇AI眼镜,开启“看见即搜索”新体验
人工智能
tellmewhoisi1 小时前
深度学习19:PyTorch:自动微分模块
人工智能·pytorch·深度学习
乌恩大侠1 小时前
Supermicro 发布六款 NVIDIA ARC 服务器:从 1U 边缘基站到 4U 八卡 AI-RAN 平台,全面对比
运维·服务器·人工智能
辛迪聊物业数字化2 小时前
物业费收缴率从68%提升到97%落地复盘:中小物业收费系统选型避坑指南
人工智能·嵌入式硬件·物联网·网络协议·系统架构
科技之门2 小时前
大捷智能携手中科曙光打造工业AI设计超级云平台——AI设计应用进入快车道!
人工智能
4SAPI2 小时前
营销内容生成大模型 API 生产选型指南:4SAPI、硅基流动与 OpenRouter 的架构权衡
数据库·人工智能·架构·php
lazy熊2 小时前
AI 编程工具跑通后,第一条任务应该怎么写?
人工智能
天树星智源2 小时前
J-Comm:不传文本传雅可比坐标,token 省下 74.8%
人工智能·机器人·大模型