opencv-python常用函数解析及参数介绍(六)——图像梯度

news2024/9/24 1:15:50

图像梯度

  • 前言
  • Sobel算子
    • 算子的定义
    • Sobelx效果演示
    • Sobely效果演示
    • 完整轮廓
    • 直接计算
    • 复杂图片的轮廓
  • Scharr算子与laplacian算子
    • scharr算子的定义
    • laplacian算子定义
  • 三种算子的效果对比
  • 结尾

前言

前面的文章中我们介绍了用膨胀和腐蚀得到了图像轮廓,图像梯度也是一种可以得到图像轮廓的方式,同时他也是边缘检测的其中一个步骤,下面我们来介绍各种可以求得图像梯度的算子。

假设我们有这样一张名为water.jpg的水元素图片
在这里插入图片描述

首先我们读出灰度图并进行二值化

img = cv2.imread('water.jpg',cv2.IMREAD_GRAYSCALE)
ret, img = cv2.threshold(img, 220, 255, cv2.THRESH_BINARY)

为了方便展示我们先创建一个显示图片的函数

def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

Sobel算子

算子的定义

在这里插入图片描述

在opencv中可以使用cv2.Sobel使用sobel算子进行梯度计算
参数:cv2.Sobel(src, ddepth, dx, dy, ksize)

参数含义
ddepth图像的深度
dx和dy分别表示水平和竖直方向
ksizeSobel算子的大小

Sobelx效果演示

当第3个参数为1,第4个参数为0时进行Gx操作,其中的A为待处理的图像在卷积核中待处理的区域
Gx操作所使用的算子可以直观的看出来更加注重像素点的左右方向,如果左侧黑右侧白,那么求得的值就是正值反之则是负值

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,'sobelx')

在这里插入图片描述
我们可以发现轮廓并不完整,这是为什么呢,因为sobelx算子在左黑右白为正值,左白右黑为负值,而opencv自动将负值设成0,所以负值的边界在显示时会消失,但是实际上sobelx这个变量中负值的数值还是存在的,那么我们来进行一些操作让他显示出来,为了方便显示我们还是在原图上进行轮廓的绘制

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
idx1, idx2 = np.where(sobelx<0)
idx3, idx4 = np.where(sobelx>0)
idx5, idx6 = np.where(sobelx!=0)
water = cv2.imread('water.jpg')
water_1 = water.copy()
water_2 = water.copy()
water_3 = water.copy()
water_1[idx1,idx2,:]=(0 ,0, 255)
water_2[idx3,idx4,:]=(0 ,255, 0)
water_3[idx5,idx6,:]=(255 ,0, 0)
cv_show(np.hstack([water_1, water_2, water_3]),'sobelx')

在这里插入图片描述
那么如果我们还是想得到之前那种黑白的轮廓图要如何处理呢

我们可以使用cv2.convertScaleAbs函数将sobelx的值取绝对值

sobelx_1 = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx_1 = cv2.convertScaleAbs(sobelx_1)
cv_show(sobelx_1,'sobelx')

在这里插入图片描述
我们可以看到。整个轮廓都是左右两侧,上下均有间断,这是为什么呢,因为Gx操作只针对左右,而不针对上下,要想得到上下的轮廓我们需要使用Gy操作

Sobely效果演示

当dx=0,dy=1时

sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)  
cv_show(sobely,'sobely')

在这里插入图片描述
这次的间断变成了左右两侧

完整轮廓

我们可以发现上述的两种方式都存在间断,那么要得到完整的轮廓我们就需要将他们结合在一起
我们使用addWeighted将他们相加,addWeigthed的用法可以翻一翻之前的文章

sobelxy = cv2.addWeighted(sobelx_1,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

在这里插入图片描述

直接计算

当dx和dy参数都为1时,将会进行Gx和Gy相结合的计算,但是效果一般不如单独计算再求和

sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy) 
cv_show(sobelxy,'sobelxy')

在这里插入图片描述

复杂图片的轮廓

我们依然用之前的kl.png来进行演示
在这里插入图片描述

img = cv2.imread('kl.png',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

在这里插入图片描述
可以看到图像轮廓被完美的显示出来了
为了美观我们可以将图片反色
在这里插入图片描述

看到这个效果是不是跟之前文章中的边缘检测生成的线稿风格图像很像,事实上已经很接近了,我们将在后边的文章介绍边缘检测,本篇文章将继续介绍生成梯度的其他算子

Scharr算子与laplacian算子

scharr算子的定义

在这里插入图片描述
scharr算子和sobel算子基本思路是一样的,只不过他的值更大,呈现在图像中的效果就是对比更加明显,因为最终得到的值是sobel的倍数,而在opencv中,数越大就越白,对比度也就越高

laplacian算子定义

在这里插入图片描述
laplacian算子可以兼顾上下左右4个方向,但是因为上下左右四个方向的值都为1,这就导致得到的最终的数值将会比sobel算子得到的数值更小,所以对比度将会更低

三种算子的效果对比

为了方便观察我们依然在显示时进行反色处理,即255减去图像

img = cv2.imread('kl.png',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  

scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 

laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)   

res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(cv2.resize(255-res, (1600, 500)),'res')

在这里插入图片描述

结尾

有兴趣的话可以参照之前的文章:边缘检测生成(伪)手绘线稿风格的视频简易版教程
可以自己找一个视频运用本文中的方式生成(伪)线稿视频

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

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

相关文章

五年六次

今天是 2022 年的最后一天&#xff0c;可算等来了。讽刺的是&#xff0c;就在昨天&#xff0c;小号写了篇文章&#xff0c;啥主题就不说了&#xff0c;然后晚上文章被删了&#xff0c;账号居然也被封了。2022 全年虽然我写过很多文章都被和谐了&#xff0c;但是最后一天喜提封号…

二、Django

Django 提示&#xff1a;本文根据b站黑马python课整理 链接指引 > 黑马程序员python企业级开发项目-手把手从0到1开发《美多商城》 文章目录DjangoMVT图解项目准备1.创建项目2.创建应用3.更换python解释器4.安装应用5.本地化6.项目中匹配urls7.应用中匹配urls.py8.准备视图…

Tensorflow游乐场 在线可视化

playground.tensorflow.org Tensorflow游乐场 Tensorflow游乐场提供了一个在线可视化AI训练。A Neural Network Playgroundhttp://playground.tensorflow.org/ Tensorflow游乐场 是干啥的呢 给一堆点分出蓝色部分和橙色部分。也就是二分类。 它提供了4种数据来训练 每种数据…

致敬客户、致敬行业,知道创宇2022“宇”你并肩前行!

2022回首2022&#xff0c;一幅数字化、智能化升级的壮阔云图徐徐展开&#xff0c;顺势催生出安全技术的全新变革……这一年&#xff0c;中国网络安全企业代表——知道创宇&#xff0c;持续从技术创新、安全服务、行业融合等方面深入网络安全产业升级。我们坚守攻防博弈战场、纵…

burp suite爆破sqli-labs的 less-5

一. 使用proxy抓包&#xff0c;具体数据包如下图&#xff1a; 二. 鼠标右键&#xff0c;将其发送到 intruder中&#xff0c;具体如下图&#xff1a; 三.选择下图选项卡&#xff1a; 1.默认为sniper模式&#xff0c;即如果有多个变量&#xff0c;对每个变量依次进行破解&#xf…

【 shell 编程 】第3篇 循环

循环 文章目录循环一、for 循环1.for 语法结构二、while、until 循环1.while 语法结构2.until 语法结构三、expect一、for 循环 1.for 语法结构 for 变量名 [ in 取值列表 ] do 循环体 done例子1 需求&#xff1a;自动循环创建10个用户 #&#xff01;/bin/bash read -p &quo…

【C++常用容器】STL基础语法学习set容器

目录 ●set构造和赋值 ●set大小和交换 ●set插入和删除 ●set查找和统计 ●set排序&#xff08;改变其排序规则&#xff0c;仿函数的运用&#xff09; ●set和multiset 1.对组&#xff08;pair&#xff09;的创建 2.set的验证&#xff08;不可以重复插入数据&#xff…

《QDebug 2022年12月》

一、Qt Widgets 问题交流 二、Qt Quick 问题交流 1、在 C 中关联 QQuickWindow 的 closing 信号提示 "使用了未定义类型QQuickCloseEvent" 因为 closing 信号中的参数类型是 private 模块中定义的&#xff0c;但是通过第二句提示我们知道找到了完整定义才能使用 Q_…

安装并配置uwsgi(1)

今天分享的主题是安装并配置uwsgi。 假设我们‍‍腾讯云主机里面的整个后端的源码&#xff0c;包括运行环境都已经没有问题了&#xff0c; 我们要把这个给挂到我们的 uwsgi 的服务器上&#xff0c; 因为这个服务器它支持 uwsgi 的协议&#xff0c;它能够跟我们的Django的进行一…

Shell——echo、printf及彩色打印

文章目录printfprintf格式常用的转义字符echoecho打印的格式echo打印的三种方式echo支持的转义字符关于打印叹号&#xff08;!&#xff09;彩色输出printf printf格式 printf “格式化字符串” 变量 printf的使用方法与C语言一样&#xff0c;并且不需要括号和逗号进行分隔&…

【自学Python】Python诞生

Python诞生 Python诞生教程 1989 年的圣诞节期间&#xff0c;吉多范罗苏姆为了在阿姆斯特丹打发时间&#xff0c;决心开发一个新的解释程序&#xff0c;作为 ABC 语言的一种继承。 ABC 语言是由吉多参加设计的一种教学语言&#xff0c;就吉多本人看来&#xff0c;ABC 这种语…

如何使用 Java Stream API ,一行代码将 List 转换为 Map 类型

文章目录一句话场景语法测试关键语句截图Source Code控制台输出一句话 List<User> --> Map<User对象中欲作为key的字段的类型, User> List<User> userList getUserList(); Map<Integer, User> idAndUserMap userList.stream().collect(Collecto…

2022朝花夕拾-持续快速成长

2022年又过去了&#xff0c;学业繁忙好久没和大家聊天了。2020年终总结2020朝花夕拾-不务正业的大学生做了什么比赛&#xff1f;和2021年终总结2021朝花夕拾-我在校搞副业实现经济独立在此&#xff0c;幸好去年立了年度目标。如今在回忆这一年的收获时&#xff0c;也可以一项项…

通过SQLserver执行系统命令

前言 咋说呢&#xff0c;就是把&#xff0c;我最近找工作然后库库投校招的简历&#xff0c;然后呢&#xff0c;我接到了一个青藤云的笔试机会&#xff0c;哇&#xff01;我激动的不行&#xff0c;然后我什么都没有准备的上线进行一波答题&#xff0c;答完总结下来&#xff0c;…

使用python实现跨年烟花代码

朋友们&#xff0c;有多久没放烟花了&#xff1f;今年你所在的地方允许放烟花么&#xff1f;既然我们不能线下放&#xff0c;那么我们就在线上放个够吧&#xff08;还是那句话&#xff1a;你~有~对~象~了~嘛~&#xff09; 一下是动态图&#xff08;图片我使用的我上几次的背景图…

算法设计与分析复习02:分而治之算法

算法设计与分析复习02&#xff1a;分而治之算法 文章目录算法设计与分析复习02&#xff1a;分而治之算法复习重点分而治之算法全排列递归算法矩阵乘法的Strassen算法棋盘覆盖线性时间选择复习重点 分而治之算法 全排列递归算法 #include<vector> #include<iostream&g…

await如何优雅的捕获异常?

传统方式 try { const res await getUser(id) }catch(err){console.log(err) } await让我们使用异步方式开发的代码简便不少&#xff0c;但是每次使用如果都用try..catch来捕获异常反而埋没了它的优势。 [ err, user ] await to(UserModel.findById(1)); 如果我们使用await…

CSS var() 自定义的属性值和使用

声明全局 CSS 变量 :root{<自定义属性名>: <自定义属性值>; }自定义属性名必需以 -- 开头。 :root :root 这个 CSS 伪类匹配文档树的根元素。对于 HTML 来说&#xff0c;:root 表示 <html> 元素&#xff0c;除了优先级更高之外&#xff0c;与 html 选择器…

【Docker】构建自定义镜像

文章目录1. 镜像制作的两种方法2. Commit构建自定义镜像3. Dockerfile构建镜像4. 镜像的分层结构5. Dockerfile基础指令6. Java服务器镜像构建7. Nginx镜像构建8. Redis镜像构建9. 快速部署MySQL并初始化1. 镜像制作的两种方法 基于Docker Commit制作镜像基于Dockerfile制作镜…

WIKO+鸿蒙生态:海外品牌中国化的新范式

想要理解快速变化的科技行业&#xff0c;往往要锚定一些标杆型企业&#xff0c;它们的风吹草动&#xff0c;可能就是行业接下来的地动山摇。就像互联网绕不过BAT&#xff0c;手机行业的趋势也少不了鸿蒙的消息。最近&#xff0c;有一件鸿蒙生态的新闻是比较特别的。我们报道过很…