12- OpenCV:算子(Sobel和Laplance) 和Canny边缘检测 详解

news2024/11/18 8:33:17

目录

一、Sobel算子

1、卷积应用-图像边缘提取

2、Sobel算子(索贝尔算子)

3、相关的API(代码例子)

二、Laplance算子

1、理论

2、API使用(代码例子)

三、Canny边缘检测

1、Canny算法介绍

2、API使用(代码例子)


一、Sobel算子

1、卷积应用-图像边缘提取

         在这个红点变化最大,变化率很高的,梯度也是最陡。变化率做成一根曲线,所以变化率最大的就在顶点。

(1)边缘是什么 :是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。

(2)如何捕捉/提取边缘 – 对图像求它的一阶导数       

                delta =  f(x) – f(x-1), delta越大,说明像素在X方向变化越大,边缘信号越强,

(3)用Sobel算子就好!卷积操作!

2、Sobel算子(索贝尔算子)

(1)是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度;

(2)Soble算子功能集合高斯平滑和微分求导;

(3)又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方法与Y方向梯度图像;

(4)求取导数的近似值,kernel=3时不是很准确,OpenCV使用改进版本Scharr函数,算子如下:放大了权重,差异性更加大了,不过也更加准确些。

3、相关的API(代码例子)

(1)cv_Sobel函数原型

cv::Sobel (

InputArray Src // 输入图像

OutputArray dst// 输出图像,大小与输入图像一致

int depth // 输出图像深度.

int dx.  // X方向,几阶导数

int dy // Y方向,几阶导数.

int ksize, SOBEL算子kernel大小,必须是奇数,1、3、5、7,一般是3

double scale  = 1

double delta = 0

int borderType = BORDER_DEFAULT

)

(2)cv::Scharr

cv::Scharr (

InputArray Src // 输入图像

OutputArray dst// 输出图像,大小与输入图像一致

int depth // 输出图像深度.

int dx.  // X方向,几阶导数

int dy // Y方向,几阶导数.

double scale  = 1

double delta = 0

int borderType = BORDER_DEFAULT

)

(3)其他的API

— GaussianBlur( src, dst, Size(3,3), 0, 0, BORDER_DEFAULT );

— cvtColor( src,  gray, COLOR_RGB2GRAY );

— addWeighted( A, 0.5,B, 0.5, 0, AB); convertScaleAbs(A, B)// 计算图像A的像素绝对值,输出到图像B

(4)代码演示

图像处理流程:

-高斯平滑(高斯模糊)GaussianBlur( )

-转灰度

-求梯度X和Y:做Sobel索贝尔计算

-得到振幅图像

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("test.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_TITLE[] = "input image";
	char OUTPUT_TITLE[] = "sobel-demo";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);

	Mat gray_src;
	GaussianBlur(src, dst, Size(3, 3), 0, 0);
	cvtColor(dst, gray_src, CV_BGR2GRAY);
	imshow("gray image", gray_src);

	Mat xgrad, ygrad;
	Scharr(gray_src, xgrad, CV_16S, 1, 0);
	Scharr(gray_src, ygrad, CV_16S, 0, 1);

	// Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
	// Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);

    // 转为绝对值
	convertScaleAbs(xgrad, xgrad);
	convertScaleAbs(ygrad, ygrad);
	imshow("xgrad", xgrad);
	imshow("ygrad", ygrad);

	Mat xygrad = Mat(xgrad.size(), xgrad.type());
	printf("type : %d\n", xgrad.type());
	int width = xgrad.cols;
	int height = ygrad.rows;
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			int xg = xgrad.at<uchar>(row, col);
			int yg = ygrad.at<uchar>(row, col);
			int xy = xg + yg;
			xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}
	//addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
	imshow(OUTPUT_TITLE, xygrad);

	waitKey(0);
	return 0;
}

效果展示:

二、Laplance算子

1、理论

解释:在二阶导数的时候,最大变化处的值为零即边缘是零值。通过二阶 导数计算,依据此理论我们可以计算图像二阶导数,提取边缘。

实际上就是:拉普拉斯算子操作(Laplance operator)-> cv::Laplance

2、API使用(代码例子)

(1)cv::Laplacian原型:

Laplacian(

InputArray src,

OutputArray dst,

int depth, //深度CV_16S

int kisze, // 3

double scale = 1,

double delta =0.0,

int borderType = 4

)

(2)代码演示

图像处理流程:

- 高斯模糊 – 去噪声GaussianBlur()

- 转换为灰度图像cvtColor()

- 拉普拉斯 – 二阶导数计算Laplacian()

-取绝对值convertScaleAbs()

-显示结果

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("test.jpg");
	if (!src.data) {
		printf("could not load image");
	}
	char input_title[] = "input image";
	char output_title[] = "Laplaiance Result";
	namedWindow(input_title, CV_WINDOW_AUTOSIZE);
	imshow(input_title, src);

	Mat gray_src, edge_image;
	GaussianBlur(src, dst, Size(3, 3), 0, 0);
	cvtColor(dst, gray_src, CV_BGR2GRAY);

	Laplacian(gray_src, edge_image, CV_16S, 3);
	convertScaleAbs(edge_image, edge_image);

    // 边缘处理
	threshold(edge_image, edge_image, 0, 255, THRESH_OTSU | THRESH_BINARY);
	namedWindow(output_title, CV_WINDOW_AUTOSIZE);
	imshow(output_title, edge_image);

	waitKey(0);
	return 0;
}

效果展示:

三、Canny边缘检测

1、Canny算法介绍

(1)简介:Canny算法是一种经典的边缘检测算法,常用于计算机视觉和图像处理领域。

它由John F. Canny在1986年提出,并被广泛应用于图像分割、目标检测等任务中。

(3)图像处理流程:

图像处理流程:

- 高斯模糊 - GaussianBlur,对图像进行降噪,避免影响最终的结果

- 灰度转换 - cvtColor,必须是8位的灰度图像

- 计算梯度 – Sobel/Scharr

- 非最大信号抑制

- 高低阈值

- 输出二值图像

(3)非最大信号抑制:图表边缘的信号很强,边缘信号只有一个,要对非边缘信号进行抑制。要对法线或者切线方向的值去掉。

        对梯度幅值图像进行非极大值抑制。这一步骤的目的是将边缘细化为单像素宽度,并抑制非最大值区域。具体来说,对于每个像素,只有在其梯度方向上具有最大幅值的像素才被保留。

(4)高低阈值输出二值图像:

        根据两个阈值(高阈值和低阈值)对非极大值抑制后的图像进行阈值处理。高阈值用于确定强边缘,而低阈值用于确定弱边缘。具体来说,如果某个像素的梯度幅值大于高阈值,则将其标记为强边缘;如果某个像素的梯度幅值介于低阈值和高阈值之间,则将其标记为弱边缘;如果某个像素的梯度幅值小于低阈值,则将其丢弃。

一个为高阈值,一个为低阈值(T1和T2);

— T1, T2为阈值,凡是高于T2的都保留(是很强的边缘像素 ),凡是小于T1都丢弃,从高于T2的像素出发,凡是大于T1而且相互连接的,都保留。最终得到一个输出二值图像。

— 推荐的高低阈值比值为 T2: T1 = 3:1/2:1,其中T2为高阈值,T1为低阈值。

(5)边缘连接

        通过连接强边缘和与之相连的弱边缘来形成完整的边缘。具体来说,如果某个弱边缘与某个强边缘在空间上相邻接,则将其标记为强边缘。

2、API使用(代码例子)

(1)cv::Canny原型

Canny(

InputArray src, // 8-bit的输入图像

OutputArray edges,// 输出边缘图像, 一般都是二值图像,背景是黑色

double threshold1,// 低阈值,常取高阈值的1/2或者1/3

double threshold2,// 高阈值

int aptertureSize,// Soble算子的size,通常3x3,取值3

bool L2gradient // 选择 true表示是L2来归一化,否则用L1归一化

(2)代码演示

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
Mat src, gray_src, dst;
int t1_value = 50;
int max_value = 255;
const char* OUTPUT_TITLE = "Canny Result";
void Canny_Demo(int, void*);
int main(int argc, char** argv) {
	src = imread("test,jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_TITLE[] = "input image";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);

	cvtColor(src, gray_src, CV_BGR2GRAY);
	createTrackbar("Threshold Value:", OUTPUT_TITLE, &t1_value, max_value, Canny_Demo);
	Canny_Demo(0, 0);

	waitKey(0);
	return 0;
}

void Canny_Demo(int, void*) {
	Mat edge_output;
	blur(gray_src, gray_src, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);
	Canny(gray_src, edge_output, t1_value, t1_value * 2, 3, false);

	//dst.create(src.size(), src.type());

    // 使用遮罩层,只有非零的元素才会被copy到模板中
	//src.copyTo(dst, edge_output);

    // ~取反输出
	imshow(OUTPUT_TITLE, ~edge_output);
}

效果展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vulnhub-LORD OF THE ROOT: 1.0.1

一、信息收集 端口扫描、发现只开了22端口 连接ssh后提示端口碰撞&#xff1a; 端口敲门是一种通过在一组预先指定的关闭端口上产生连接请求&#xff0c;从外部打开防火墙上的端口的方法。一旦收到正确地连接请求序列&#xff0c;防火墙规则就会被动态修改&#xff0c;以允许…

eNSP学习——配置通过Telnet登陆系统

实验内容&#xff1a; 模拟公司网络场景。R1是机房的设备&#xff0c;办公区与机房不在同一楼层&#xff0c;R2和R3模拟员工主机&#xff0c; 通过交换机S1与R1相连。 为了方便用户的管理&#xff0c;需要在R1上配置Telnet使员工可以在办公区远程管理机房设备。 为…

探究Java中的链表

引言&#xff1a; 在Java编程中&#xff0c;链表是一种常见的数据结构&#xff0c;具有灵活的内存管理和动态的元素插入与删除能力。本篇博客将深入探讨链表的结构和概念&#xff0c;比较链表与顺序表的区别&#xff0c;介绍Java中LinkedList的常用函数并通过示例说明LinkedLis…

2023:既是结束也是开始

2023年注定是不平凡的一年&#xff0c;这一年真的经历了很多事&#xff0c;包括学习、生活、工作等等&#xff0c;上半年忙着毕业以及一些其他的事情&#xff0c;很多挖的坑都没来得及填&#xff0c;下半年研一开学以后终于有了足够的时间学习&#xff0c;接下来就用这篇文章来…

【linux】Debian10.0配置vsftpd

一、基本步骤 在 Debian 10 (Buster) 上要配置 vsftpd (Very Secure FTP Daemon)&#xff0c;请按照以下步骤操作&#xff1a; 1. 安装 vsftpd: sudo apt update sudo apt install vsftpd 2. 在启动配置之前&#xff0c;建议备份原始的配置文件: sudo cp /etc/vsftpd.con…

python解释器多版本设置

当你的项目很多&#xff0c;切python版本不一样时&#xff0c;如何为每个项目设置不同的python解释器版本和虚拟环境&#xff1a; 1、安装pyenv brew install pyenv 配置 Pyenv&#xff1a; 将以下内容添加到你的 shell 配置文件&#xff08;如 ~/.bashrc、~/.zshrc 或 ~/.ba…

【c++】初始c++

1. 什么是C 下图就是我们c的祖师爷 C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; 20世纪80年代&#xff0c; 计算…

Ubuntu使用docker-compose安装chatGPT

ubuntu环境搭建专栏&#x1f517;点击跳转 Ubuntu系统环境搭建&#xff08;十五&#xff09;——使用docker-compose安装chatGPT Welcome to the AI era! 使用docker compose安装 在/usr/local文件夹下创建chatgpt mkdir chatgpt创建docker-compose.yaml vim docker-compos…

P2P DMA并不是所有场景都会有性能提升

P2P (Peer-to-Peer) DMA技术理论上可以带来性能提升&#xff0c;特别是在特定的工作负载和场景下。例如&#xff0c;当两个高速设备&#xff08;如GPU与NVMe SSD&#xff09;需要频繁进行大量数据交换时&#xff0c;通过P2P DMA&#xff0c;数据可以直接在设备间传输&#xff0…

【Linux】常见指令解析下

目录 前言1. cp指令&#xff08;重要&#xff09;2. mv指令 &#xff08;重要&#xff09;3. cat指令4. more指令5. less指令 &#xff08;重要&#xff09;6. head指令7. tail指令8. 时间相关的指令8.1 data显示8.2 时间戳 9. cal指令10. find指令&#xff08;非常重要&#x…

[绍棠] docxtemplater实现纯前端导出word

1.下载需要的依赖 2.util文件夹下创建doc.js文件 doc.js import docxtemplater from docxtemplater import PizZip from pizzip import JSZipUtils from jszip-utils import { saveAs } from file-saver import ImageModule from "docxtemplater-image-module-free"…

TCP服务器最多支持多少客户端连接

目录 一、理论数值 二、实际部署 参考 一、理论数值 首先知道一个基础概念&#xff0c;对于一个 TCP 连接可以使用四元组&#xff08;src_ip, src_port, dst_ip, dst_port&#xff09;进行唯一标识。因为服务端 IP 和 Port 是固定的&#xff08;如下图中的bind阶段&#xff0…

利用HTML+CSS+JS打造炫酷时钟网页的完整指南

引言 在现代Web开发中&#xff0c;制作一个引人注目的时钟网页是一种常见而令人愉悦的体验。本文将介绍如何使用HTML、CSS和JavaScript来创建一个炫酷的时钟网页&#xff0c;通过这个项目&#xff0c;你将学到如何结合这三种前端技术&#xff0c;制作一个动态且美观的时钟效果…

SpringMVC数据校验

导包 配置springmvc.xml <bean id"validator" class" org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"><property name"providerClass" value"org.hibernate.validator.HibernateValidator ">…

React16源码: React中的renderRoot的源码实现

renderRoot 1 &#xff09;概述 renderRoot 是一个非常复杂的方法这个方法里处理很多各种各样的逻辑, 它主要的工作内容是什么&#xff1f;A. 它调用 workLoop 进行循环单元更新 遍历整个 Fiber Tree&#xff0c;把每一个组件或者 dom 节点对应的Fiber 节点拿出来单一的进行更…

烟火检测AI边缘计算智能分析网关V4如何通过ssh进行服务器远程运维

智能分析网关V4是一款高性能、低功耗的AI边缘计算硬件设备&#xff0c;它采用了BM1684芯片&#xff0c;集成高性能8核ARM A53&#xff0c;主频高达2.3GHz&#xff0c;并且INT8峰值算力高达17.6Tops&#xff0c;FB32高精度算力达到2.2T&#xff0c;每个摄像头可同时配置3种算法&…

启动低轨道卫星LEO通讯产业与6G 3GPP NTN标准

通讯技术10年一个大跃进&#xff0c;从1990年的2G至2000年的3G网路&#xff0c;2010年的4G到近期2020年蓬勃发展的5G&#xff0c;当通讯技术迈入融合网路&#xff0c;当前的 5G 技术不仅可提供高频宽、低延迟&#xff0c;同时可针对企业与特殊需求以 5G 专网的模式提供各式服务…

vue-微信H5-拍照和视频,加人像框

图片拍照: <template><div><v-easy-camera:fullscreen"true"ref"easyCamera"v-model"pictureData.picture"class"main-camera"><template #header><div class"top"><van-imageclass"…

【跳槽面试】Redis中分布式锁的实现

分布式锁常见的三种实现方式&#xff1a; 数据库乐观锁&#xff1b;基于Redis的分布式锁&#xff1b;基于ZooKeeper的分布式锁。 本地面试考点是&#xff0c;你对Redis使用熟悉吗&#xff1f;Redis中是如何实现分布式锁的。 在Redis中&#xff0c;分布式锁的实现主要依赖于R…

【JavaEE Spring】SpringBoot 配置文件

SpringBoot 配置文件 1. 配置文件的作用1.1 配置文件的说明1.2 SpringBoot 配置文件 2. 配置文件的格式特殊说明 3. properties 配置文件说明3.1 properties 基本语法3.2 读取配置文件3.3 properties 缺点分析 4. yml 配置文件说明4.1 yml 的基本语法4.2 yml 使⽤进阶4.2.1 yml…