OpenCV-Python(18):图像梯度

目录

背景介绍及应用

学习目标

原理

Sobel算子和Scharr算子

Laplacian 算子

代码示例

重要提醒 


背景介绍及应用

        图像的梯度是指图像中每个像素点的强度变化情况。计算图像的梯度可以帮助我们了解图像中物体的边界和纹理等信息。梯度在计算机视觉和图像处理领域有着广泛的应用,以下是一些常见的应用场景:

  1. 边缘检测:梯度可以帮助我们找到图像中物体之间的边界。通过计算图像的梯度,我们可以检测出物体的边缘,从而实现目标检测、物体识别和图像分割等任务。
  2. 图像增强:梯度可以帮助我们增强图像中的细节和纹理。通过计算图像的梯度,我们可以强调图像中的边缘和纹理,从而提高图像的清晰度和质量。
  3. 光照估计:梯度可以帮助我们估计图像中的光照条件。通过计算图像的梯度,我们可以分析图像中的亮度变化,从而了解图像的光照情况,进而进行光照校正和图像增强等操作。
  4. 特征提取:梯度可以帮助我们提取图像中的特征。通过计算图像的梯度,我们可以得到图像中的边缘和纹理等特征,从而用于图像分类、目标识别和图像检索等任务。

学习目标

  • 掌握图像梯度、图像边界等重要术语
  • 使用到的函数有cv2.Sobel()、cv2.Schar()、cv2.Laplacian() 等

原理

        梯度简单来说就是求导。OpenCV 提供了三种不同的梯度滤波器,或者说是高通滤波器,分别是Sobel,Scharr 和Laplacian。Sobel,Scharr 其实就是求一阶或二阶导数。Scharr 是对Sobel(使用小的卷积核求解梯度角度梯度角度时的优化)。Laplacian 是求二阶导数。

Sobel算子和Scharr算子

        Sobel算子和Scharr算子都是常用的图像梯度计算算子,用于边缘检测和图像增强等任务。它们可以计算图像在水平和垂直方向上的梯度,并且可以根据梯度的大小来判断图像中的边缘。

        Sobel算子是一种离散的差分算子,可以用于计算图像的一阶导数。它分为水平和垂直两个方向的算子,分别表示为Sobel_x和Sobel_y。这两个算子可以通过卷积运算来计算图像在水平和垂直方向上的梯度。Sobel算子的计算公式如下:

Sobel_x = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]

Sobel_y = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]

        Scharr算子是Sobel算子的一种改进版本,它使用了一种更加精确的差分算法,可以提供更好的梯度近似。Scharr算子也分为水平和垂直两个方向的算子,分别表示为Scharr_x和Scharr_y。Scharr算子的计算公式如下:

Scharr_x = [[-3, 0, 3], [-10, 0, 10], [-3, 0, 3]]

Scharr_y = [[-3, -10, -3], [0, 0, 0], [3, 10, 3]]

使用Sobel算子和Scharr算子可以通过卷积运算来计算图像的梯度。具体步骤如下:

  1. 将图像转换为灰度图像,如果图像已经是灰度图像则可以省略此步骤。
  2. 对图像进行平滑处理,可以使用高斯滤波器来进行平滑。
  3. 使用Sobel算子或Scharr算子进行卷积运算,计算图像在水平和垂直方向上的梯度。
  4. 根据梯度的大小来判断图像中的边缘,可以使用阈值来过滤掉低强度的边缘。
  5. 可选的,可以对图像进行非极大值抑制来细化边缘。
  6. 可选的,可以使用双阈值法来进一步筛选边缘,选择具有足够强度的边缘。

3x3 的Scharr 滤波器卷积核如下: 

Laplacian 算子

        Laplacian算子是一种常用的图像二阶导数算子,用于图像增强、边缘检测和特征提取等任务。它可以通过计算图像的二阶导数来检测图像中的边缘和纹理特征。

Laplacian算子的计算公式如下:

Laplacian = [[0, 1, 0], [1, -4, 1], [0, 1, 0]]

使用Laplacian算子可以通过卷积运算来计算图像的二阶导数。具体步骤如下:

  1. 将图像转换为灰度图像,如果图像已经是灰度图像则可以省略此步骤。
  2. 对图像进行平滑处理,可以使用高斯滤波器来进行平滑。
  3. 使用Laplacian算子进行卷积运算,计算图像的二阶导数。
  4. 根据导数的大小来判断图像中的边缘和纹理特征,可以使用阈值来过滤掉低强度的特征。
  5. 可选的,可以对图像进行非极大值抑制来细化边缘。
  6. 可选的,可以使用双阈值法来进一步筛选特征,选择具有足够强度的特征。

代码示例

下面的代码分别使用以上三种滤波器对同一幅图像操作。使用的卷积核是5x5 的。

# -*- coding: utf-8 -*-import cv2
import numpy as np
from matplotlib import pyplot as pltimg=cv2.imread('dave.jpg',0)#cv2.CV_64F 输出图像的深度(数据类型)可以使用-1, 与原图像保持一致np.uint8
laplacian=cv2.Laplacian(img,cv2.CV_64F)# 参数1,0 为只在x 方向求一阶导数􈙽最大可以求2阶导数。
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)# 参数0,1 为只在y 方向求一阶导数􈙽最大可以求2阶导数。
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])plt.show()

效果如下:

重要提醒 

        在查看上面这个例子的注释时不知到你有没有注意到,我们可以使用参数-1 来设定输出图像的深度(数据类型)与原图像保持一致,但是我们在代码中使用的却是cv2.CV_64F。这是为什么呢?想想一下一个从黑到白的边界的导数是正数,而一个从白到黑的边界点导数却是负数。如果原图像的深度是np.int8 时,所有的负值会被截断变成0,换句话说就就是把边界信息丢失掉所以如果这两种边界你都想检测到,最好的的办法就是将输出的数据类型设置的更高,比cv2.CV_16S,cv2.CV_64F 等。取绝对值然后再把它转回到cv2.CV_8U。下面的示例演示了输出图片的深度不同造成的不同效果。

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('boxs.png',0)# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)# 也可以将参数􄕭为-1
#sobelx8u = cv2.Sobel(img,-1,1,0,ksize=5)
# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8Usobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])plt.show()

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android开发——添加图片

1、首先选择一张需要的图片,通过左侧的Resource Manage选择“”并选择Import Drawables 选择一张图片 并调整以下两个内容 这两个内容的作用借用谷歌官方的Android开发教程的内容: *Android 设备具有不同的屏幕尺寸(手机、平板电脑和电视等…

Keil5软件仿真 定时器互补通道 波形输出(Logic Analyzer)

步骤一:管脚配置确认。 ①配置定时器的管脚模式为复用推挽输出模式(GPIO_MODE_AF_PP)!!!,注意:复用开漏模式软件仿真时无波形。 步骤二:编译程序。 ①点击编译按钮。 …

java: -source 7 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)

目录 1、检查项目中 JDK 的设置: 2、检查模块中 JDK 的设置: 3、检查Idea 中的SDK设置 4、检查 IDEA 中 JDK 的设置(我出现的问题在这): 今天遇见了一个报错: 问题产生的原因是 JDK 版本太低&#xf…

信息收集 - 谷歌hack

搜索引擎 FOFA网络空间测绘:https://fofa.info/ FOFA(FOcus on Assets)是一个网络空间搜索引擎,可以帮助用户快速定位和收集特定目标的信息。 ZoomEye:https://www.zoomeye.org ZoomEye 是一个网络空间搜索引擎,可以用于发现和收集特定目标的网络设备、Web应用程序、开放…

华为设备命令行操作基础

熟悉VRP命令行并且熟练掌握VRP配置是高效管理华为网络设备的必备基础。 设备初始化启动 管理员和工程师如果要访问在通用路由平台VRP上运行的华为产品,首先要进入启动程序。开机界面信息提供了系统启动的运行程序和正在运行的VRP版本及其加载路径。启动完成以后&am…

MyBatis的延迟加载!!!

首先:MyBatis的关联查询!!!(一对一、一对多、多对多)-CSDN博客以这个项目为基础。 1.在UserMapper接口中创建一个方法: package com.by.mapper;import com.by.pojo.User;import java.util.Lis…

Python接口自动化测试实战(视频教程+源码)

接口自动化测试是指通过编写程序来模拟用户的行为,对接口进行自动化测试。Python是一种流行的编程语言,它在接口自动化测试中得到了广泛应用。下面详细介绍Python接口自动化测试实战。 1、接口自动化测试框架 在Python接口自动化测试中,我们…

阿里云 ACK One 新特性:多集群网关,帮您快速构建同城容灾系统

云布道师 近日,阿里云分布式云容器平台 ACK One[1]发布“多集群网关”[2](ACK One Multi-cluster Gateways)新特性,这是 ACK One 面向多云、多集群场景提供的云原生网关,用于对多集群南北向流量进行统一管理。 基于 …

智能优化算法应用:基于鹰栖息算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于鹰栖息算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于鹰栖息算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鹰栖息算法4.实验参数设定5.算法结果6.参考文…

【数据结构】递归与分治

一.递归 1.递归的概念: 子程序(或函数). 接调用自己或通过一系列调用语句间接调用自己,成为递归。 递归是一种描述问题和解决问题的基本方法。 重复地把问题转化为与原问题相似的新问题,直到问题解决为止。 2.递归…

面试 Java 算法高频题五问五答第二期

面试 Java 算法高频题五问五答第二期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的! ⭐点赞⭐收藏⭐不迷路!⭐ 寻找峰值: 主要思想:二分查找,利用get函数&#xff0…

基于ssm+jsp理发店管理系统源码和论文

随着信息化时代的到来,管理系统都趋向于智能化、系统化,理发店管理系统也不例外,但目前国内的市场仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化&#xff0…