openc —— Canny 边缘检测
边缘检测的一般步骤
【第一步】滤波
边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。常见的滤波方法主要有高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核,然后基于高斯核对图像灰度矩阵的每一点进行加权求和。
【第二步】增强
增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来,在具体编程实现时,可通过计算梯度幅值来确定。
【第三步】检测
通过增强的图像,往往领域中有很多点的梯度值比较大,而在特定的应用中这些点并不是要找的边缘点,所以应该采用某种方法来对这些点进行取舍,实际工程中,常用的方法是通过阈值化方法来检测。
Canny 算子简介
Canny 边缘检测算子是 John F.Canny 于 1986 年开发出来的一个多级边缘检测算法。更为重要的是,Canny 创立了边缘检测计算理论,解释了这项技术是如何工作的。Canny 边缘检测算法以 Canny 的名字命名,被很多人推崇为最优的边缘检测的算法。
最优边缘检测的三个主要评价标准:
- 低错误率:标识出尽可能多的实际边缘,同时尽可能地减少噪声产生的误差。
- 高定位性:标识出的边缘要与图像中的实际边缘尽可能接近。
- 最小相应:图像中的边缘只能标记一次,并且可能存在的图像噪声不应被识别为边缘。
Canny 边缘检测的步骤
【第一步】转化为灰度图并消除噪声
一般情况下,使用高斯平滑滤波器卷积降噪。下面显示了一个 的高斯内核示例:
【第二步】计算梯度幅值和方向
此处,按照 Sobel 滤波器的步骤来操作:
https://www.cnblogs.com/bjxqmy/p/12325852.html
① 运用一对卷积阵列 (分别作用于 和 方向)
② 使用下列公式计算梯度幅值和方向:
梯度方向近似到四个可能角度之一 —— 0 度, 45 度, 90 度, 135 度
【第三步】非极大值抑制
这一步排除非边缘像素,仅仅保留了一些细线条(候选边缘)。
【第四步】滞后阈值
滞后阈值需要两个阈值:
① 若某一像素位置的幅值超过高阈值,该像素被保留为边缘像素。
② 若某一像素位置的幅值小于低阈值,该像素被排除。
③ 若某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高阈值的像素时被保留。
Canny 边缘检测:Canny 函数
void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false);
- image,输入图像,即源图像,填 Mat 类对象即可,彩色或灰度图像均可,但一般为经过高斯模糊后的灰度图。
- edges,输出的边缘图,和源图像有一样的尺寸,且为二值图像。
- threshold1,第一个滞后性阈值。
- threshold2,第二个滞后性阈值。
- apertureSize,Sobel 算子的孔径大小,其有默认值 3。
- L2gradient,一个计算图像梯度值幅度的标识,如果为 true,则使用更精确的 L2 范数进行计算(即某点梯度 = 两个方向导数的平方和再开方),默认为 false,使用 L1 范数(某点梯度 = 两个方向导数的绝对值相加)。
需要注意的是,函数阈值 1 和函数阈值 2 两者中较小的值用于边缘连接,而较大的值用来控制强边缘的初始段,推荐的高低阈值比在 2:1 到 3:1 之间。
代码示例:
#include<opencv.hpp>
using namespace cv;
int main() {
Mat src = imread("C:/Users/齐明洋/Desktop/证件照/7.jpg");
GaussianBlur(src, src, Size(, ), , );
imshow("src", src);
Mat gray, canny_img;
cvtColor(src, gray, COLOR_BGR2GRAY);
Canny(gray, canny_img, , , );
imshow("canny_img", canny_img); waitKey();
}
效果演示:
借鉴博客:https://www.cnblogs.com/pacino12134/p/9877971.html
最新文章
- C# 高效编程笔记1
- 架构师养成记--3.synchronized细节问题
- 2Struts2配置----青软S2SH(笔记)
- mysql中更新或者删除语句中子语句不能操作同一个表You can&#39;t specify target table &#39;test&#39; for update in FROM clause
- 关于iOS10 Xcode8真机测试项目出现的问题 ";code signing is required for product type &#39;xxxxx&#39; in SDK &#39;iOS 10.0";..
- 使用Html来避免写复杂的app代码,跨平台
- 湘潭 A simple problem
- 九、mysql触发器的概念
- java Enumeration用法
- Linux标准输入、输出和错误和文件重定向(转) --- good
- hadoop format过程
- [Usaco2007 Jan]Running贝茜的晨练计划[一般DP]
- ios-Ineligible Devices 不被识别的设备
- 再说AutoComplete
- JavaBean转Map方法
- 201621123057 《Java程序设计》第9周学习总结
- PHP全栈学习笔记2
- man rpcbind(rpcbind中文手册)
- vuejs-指令详解
- MyISAM索引和InnoDB索引的区别
热门文章
- ios---CoreLocation框架实现定位功能
- .NET Core学习笔记(4)——谨慎混合同步和异步代码
- 解决linux安装软件:/lib/ld-linux.so.2: bad ELF interpreter: 没有那个文件或目录
- PAT乙级(Basic Level)真题,福尔摩斯的约会
- linux 修改系统时间 同步网络时间
- c++中值传递,址传递,引用传递
- 二、Shell变量
- 学过 C++ 的你,不得不知的这 10 条细节!
- javabst1an
- ubuntu+mysql+php+apache2+wordpress建站全记录