Python从零到壹丨图像增强的顶帽运算和底帽运算

摘要:这篇文章详细介绍了顶帽运算和底帽运算,它们将为后续的图像分割和图像识别提供有效支撑。

本文分享自华为云社区《[Python从零到壹] 四十九.图像增强及运算篇之顶帽运算和底帽运算》,作者:eastmount。

数学形态学(Mathematical Morphology)是一种应用于图像处理和模式识别领域的新方法。数学形态学(也称图像代数)表示以形态为基础对图像进行分析的数学工具,其基本思想是用具有一定形态的结构元素去量度和提取图像中对应形状以达到对图像分析和识别的目的。

一.图像顶帽运算

图像顶帽运算(top-hat transformation)又称为图像礼帽运算,它是用原始图像减去图像开运算后的结果,常用于解决由于光照不均匀图像分割出错的问题。其公式定义如下:

图像顶帽运算是用一个结构元通过开运算从一幅图像中删除物体,顶帽运算用于暗背景上的亮物体,它的一个重要用途是校正不均匀光照的影响。其效果图如图1所示。

在Python中,图像顶帽运算主要调用morphologyEx()实现,其中参数cv2.MORPH_TOPHAT表示顶帽处理,函数原型如下:

dst = cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel)

  • src表示原始图像
  • cv2.MORPH_TOPHAT表示图像顶帽运算
  • kernel表示卷积核,可以用numpy.ones()函数构建

假设存在一张光照不均匀的米粒图像,如图2所示,我们需要调用图像顶帽运算解决光照不均匀的问题。

图像顶帽运算的Python代码如下所示:

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2  
import numpy as np  
#读取图片
src = cv2.imread('test01.png', cv2.IMREAD_UNCHANGED)
#设置卷积核
kernel = np.ones((10,10), np.uint8)
#图像顶帽运算
result = cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel)
#显示图像
cv2.imshow("src", src)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

其运行结果如图3所示。

下图展示了“米粒”顶帽运算的效果图,可以看到顶帽运算后的图像删除了大部分非均匀背景,并将米粒与背景分离开来。

为什么图像顶帽运算会消除光照不均匀的效果呢?

通常可以利用灰度三维图来进行解释该算法。灰度三维图主要调用Axes3D包实现,对原图绘制灰度三维图的代码如下:

# -*- coding: utf-8 -*-
# By:Eastmount
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
#读取图像
img = cv.imread("test02.png")
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
imgd = np.array(img) #image类转numpy
#准备数据
sp = img.shape
h = int(sp[0]) #图像高度(rows)
w = int(sp[1]) #图像宽度(colums) of image
#绘图初始处理
fig = plt.figure(figsize=(16,12))
ax = fig.gca(projection="3d")
x = np.arange(0, w, 1)
y = np.arange(0, h, 1)
x, y = np.meshgrid(x,y)
z = imgd
surf = ax.plot_surface(x, y, z, cmap=cm.coolwarm) 
#自定义z轴
ax.set_zlim(-10, 255)
ax.zaxis.set_major_locator(LinearLocator(10)) #设置z轴网格线的疏密
#将z的value字符串转为float并保留2位小数
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) 
# 设置坐标轴的label和标题
ax.set_xlabel('x', size=15)
ax.set_ylabel('y', size=15)
ax.set_zlabel('z', size=15)
ax.set_title("surface plot", weight='bold', size=20)
#添加右侧的色卡条
fig.colorbar(surf, shrink=0.6, aspect=8) 
plt.show()

运行结果如图5所示,其中x表示原图像中的宽度坐标,y表示原图像中的高度坐标,z表示像素点(x, y)的灰度值。

从图像中的像素走势显示了该图受各部分光照不均匀的影响,从而造成背景灰度不均现象,其中凹陷对应图像中灰度值比较小的区域。

通过图像白帽运算后的图像灰度三维图如图6所示,对应的灰度更集中于10至100区间,由此证明了不均匀的背景被大致消除了,有利于后续的阈值分割或图像分割。

绘制三维图增加的顶帽运算核心代码如下:

二.图像底帽运算

图像底帽运算(bottom-hat transformation)又称为图像黑帽运算,它是用图像闭运算操作减去原始图像后的结果,从而获取图像内部的小孔或前景色中黑点,也常用于解决由于光照不均匀图像分割出错的问题。其公式定义如下:

图像底帽运算是用一个结构元通过闭运算从一幅图像中删除物体,常用于校正不均匀光照的影响。其效果图如图8所示。

在Python中,图像底帽运算主要调用morphologyEx()实现,其中参数cv2.MORPH_BLACKHAT表示底帽或黑帽处理,函数原型如下:

dst = cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel)

  • src表示原始图像
  • cv2.MORPH_BLACKHAT表示图像底帽或黑帽运算
  • kernel表示卷积核,可以用numpy.ones()函数构建

Python实现图像底帽运算的代码如下所示:

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2  
import numpy as np  
#读取图片
src = cv2.imread('test02.png', cv2.IMREAD_UNCHANGED)
#设置卷积核
kernel = np.ones((10, 10), np.uint8)
#图像黑帽运算
result = cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel)
#显示图像
cv2.imshow("src", src)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

其运行结果如图9所示:

三.总结

该系列主要讲解了图像数学形态学知识,结合原理和代码详细介绍了图像腐蚀、图像膨胀、图像开运算和闭运算、图像顶帽运算和图像底帽运算等操作。这篇文章详细介绍了顶帽运算和底帽运算,它们将为后续的图像分割和图像识别提供有效支撑。

参考文献:

  • [1]冈萨雷斯著,阮秋琦译. 数字图像处理(第3版)[M]. 北京:电子工业出版社,2013.
  • [2]阮秋琦. 数字图像处理学(第3版)[M]. 北京:电子工业出版社,2008.
  • [3]毛星云,冷雪飞. OpenCV3编程入门[M]. 北京:电子工业出版社,2015.
  • [4]Eastmount. [Python图像处理] 八.图像腐蚀与图像膨胀[EB/OL]. (2018-10-31). http://blog.csdn.net/Eastmount/article/details/83581277.

 

点击关注,第一时间了解华为云新鲜技术~

本文转载于网络 如有侵权请联系删除

相关文章

  • Hadoop环境搭建与测试

    Hadoop环境搭建请参看下面的连接:CentOS安装和配置Hadoop2.2.0 http://www.linuxidc.com/Linux/2014-01/94685.htmUbuntu13.04上搭建Hadoop环境http://www.linuxidc.com/Linux/2013-06/86106.htmUbuntu12.10+Hadoop1.2.1版本集群配置http://www.linuxidc.com/Linux/2013-09/90600.htmUbuntu上搭建Hadoop环境(单机模式+伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htmUbuntu下Hadoop环境的配置http://www.linuxidc.com/Linux/2012-11/74539.htm单机版搭建Hadoop环境图文教程详解http://www.linuxidc.com/Linux/2012-02/53927.htm搭建Hadoop环境(在Winodws环境下用虚拟机虚拟两个Ubuntu系统进行搭建)http://www.linux

  • 打开微信小程序,显示网络异常的解决方法

    前几天心血来潮想着把小程序的轮播更换几张图片,然后就在后台操作了,然后打开小程序发现网络异常,各种打不开啊,不知道是什么原因,我当初以为是我本地网络环境问题,然后重新修改DNS或者网卡mac地址都无效,肯定不是本地的问题,那会不会是腾讯的问题(当然不可能是腾讯问题啊),然后浏览别的小程序,发现并没有任何问题。。。陷入僵局!今天上班偶然间看见小程序,又开始折腾了,真的是无从下手啊,没办法请求外援,嗯,小程序插件的开发者大神@橙色阳光,是的,按照大神的指引,最后修改了“rule”修改成“1”然后真机测试,OK,现在知道问题所在了,就是伪静态引起了(正常是rule为了0,开启伪静态),然后灵光一闪,我前几天添加了一个伪静态规则,然后登录服务器删除规则,又将rule修改为0,一切正常了。原因是:因为Apache系统会在目录结尾直接添加“/”反斜杠而Nginx没有这个功能,需要自行添加规则(如下):(正常情况下此规则是正确的,没有任何问题)if (!-f $request_filename){     rewrite ^/([^\.]+[^/])$ http://$host/$1$2/ perm

  • 网站变色字体代码

    <divid="blink"> <strong> <divalign="left"style="text-align:center;"> 开源世界ym.baisou.ltd,广告位招租中。 </div> <strong> <scriptlanguage="javascript">functionchangeColor(){varcolor="#f00|#0f0|#00f|#880|#808|#088|yellow|green|blue|gray";color=color.split("|");document.getElementById("blink").style.color=color[parseInt(Math.random()*color.length)];}setInterval("changeColor()",200);</sc

  • fedora 28 29 重新生成 /boot/grub2/grub.cfg

    使用情景:    之前电脑安装了windows7/fedora28双系统,由于特殊原因,需要删除windows系统。在格式化硬盘后,我们还需要跟新grub2的启动条目;删除grub启动的界面的windows7选项。解决方法:grub硬盘启动选项由 /boot/grub2/grub.cfg决定,所以我们需要更新grub.cfg文件。我们可以手动删除其中的条目,也可以使用专用的命令来进行更新。更新命令为:grub2-mkconfig我们使用man查看grub2-mkconfig的使用方法:NAME grub-mkconfig-GenerateaGRUBconfigurationfile. SYNOPSIS grub-mkconfig[-o|--output=FILE] DESCRIPTION grub-mkconfiggeneratesaconfigurationfileforGRUB. OPTIONS --output=FILE WritegeneratedoutputtoFILE.复制更新步骤:grub2-mkconfig|less进行先预览内容,然后使用: grub2-mkco

  • Android开发中简单设置启动界面的方法

    本文实例讲述了Android开发中简单设置启动界面的方法。分享给大家供大家参考,具体如下:启动界面的意义是为了让后台处理耗时的复杂工作,当工作处理完成后,即可进入主界面。相比让用户等待布局加载完成,使用一张图片作为启动背景,会带来更好的体验。首先,需要建立一个简单的布局:<?xmlversion="1.0"encoding="utf-8"? <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/launch" android:orientation="vertical" </LinearLayout复制这里我直接把整个布局的背景设为一张图片

  • 如何预览要上传的图片?

    (新手编程1001问-0004)Q:上传图片时,如何实现图片预览?A:昨天我们讨论了如何借助FormData通过Ajax上传文件。有同学留言谈到上传图片文件时,有时需要进行图片预览,这样能及时发现选择的图片文件是否正确,但是,不知道如何实现?##图片上传前预览真的那么重要吗?$$哈哈,有些喜欢私藏图片的同学万一上传错了,那可真要出大事了!##嗯~,看来还真是蛮重要的。OK,那我们今天就来介绍一下图片上传前如何实现预览功能。说实话,早起的网页和浏览器貌似还真不好解决这个问题,但是,自从HTML5以后,图片、音频、视频等对象都有了很好的解决方案。为此,我需要用到JanaScript的FileReader()类(对象)。FileReader()对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容。以下代码创建了一个FileReader的实例:varmyReader=newFileReader();FileReader包含4个用于读取文件的选项:FileReader.readAsBinaryString(Blob|File):result属性将包含二进制字符串的fi

  • 【每周一库】- Tonic 基于Rust的gRPC实现

    TonicgRPC的rust实现,高性能,开源,为移动设备与HTTP/2准备的通用RPC框架tonic是基于HTTP/2的gRPC实现,专注于高性能,互通性和灵活性。创建该库的目的是为了对async/await具有一流的支持,并充当用Rust编写的生产系统的核心构建块。特性双向流传输高性能异步io互通性通过rustls进行TLS加密支持负载均衡自定义元数据身份认证健康检查入门本教程作为Tonic的入门指导,前提是你对Rust有基础了解并且使用过protocolbuffers。先决条件运行此教程中的代码,唯一需要安装的是Rust,如果你还没有安装rustup,可以尝试使用它快速方便的安装Rust.项目设置首先,我们需要使用Cargo创建一个新的Rust项目:$cargonewhelloworld-tonic $cdhelloworld-tonic复制tonic需要rust1.39及以上版本,因为它需要async_await特性的支持。$rustupupdate $rustupcomponentaddrustfmt复制定义HelloWorld服务我们第一步需要做的是使用protocolbu

  • Git 克隆仓库报unable to get local issuer certificate错误解决方法

    问题描述克隆gitlab上的仓库,报错,如下$gitclonehttps://gitlab.xxx.net/qa/casstestmanage.gitCloninginto'casstestmanage'...fatal:unabletoaccess'https://gitlab.xxx.net/qa/casstestmanage.git/':SSLcertificateproblem:unabletogetlocalissuercertificate原因分析这是由于当你通过HTTPS访问Git远程仓库的时候,如果服务器上的SSL证书未经过第三方机构认证,git就会报错。因为未知的没有签署过的证书意味着可能存在很大的风险解决办法设置关闭SSL验证步骤1:$envGIT_SSL_NO_VERIFY=truegitclonehttps://gitlab.xxx.net/qa/casstestmanage.gitCloninginto'casstestmanage'...warning:Youappeartohaveclonedan

  • SpringMVC教程2[处理及响应请求]

    五、基本操作1.响应请求的方式序号响应方式说明1不响应void+@ResponseBody注解2ModelAndView通过setViewName方法3直接指定响应页面返回值为String类型,返回结果指定跳转地址4重定向跳转地址前加redirect:前缀即可5HttpServletRequest和HttpServletResponse形参中声明这两个变量。然后通过相关api跳转1.1ModeAndView /** *查询方法 *@return */ @RequestMapping("/query") publicModelAndViewquery(){ System.out.println("波波烤鸭:query"); ModelAndViewmv=newModelAndView(); mv.setViewName("/index.jsp"); returnmv; }复制1.2返回void返回值为void时,方法中可以不用做任何返回,例如下面代码:@RequestMapping("/te

  • 一种注册表沙箱的思路、实现——研究Reactos中注册表函数的实现4

        今天为了KPI,搞了一天的PPT,搞得恶心想吐。最后还是回到这儿,这儿才是我的净土,可以写写我的研究。    这儿讲一些Reactos中一些明显的错误。(转载请指明出处)    在Reactos的RegQueryInfoKeyW中有段这样的实现if(lpcbMaxSubKeyLen!=NULL) { *lpcbMaxSubKeyLen=FullInfo->MaxNameLen/sizeof(WCHAR)+1; } if(lpcbMaxClassLen!=NULL) { *lpcbMaxClassLen=FullInfo->MaxClassLen/sizeof(WCHAR)+1; } if(lpcbMaxValueNameLen!=NULL) { *lpcbMaxValueNameLen=FullInfo->MaxValueNameLen/sizeof(WCHAR)+1; }复制    这儿存在一个明显的错误,当待查询键不存在子键时,最长子键名长度肯定是0啊,怎么会是1呢?同样的错误出现在最长Class长度和最长项名长度。Reactos源码中对这些长度数据的

  • DeepMind的脑补AI再获新技能:看文字知场景、复杂环境、连续视频……

    夏乙发自凹非寺 量子位出品|公众号QbitAI在教会AI脑补、理解周围的环境之后,还能往什么方向努力?“人工智能梦之队”DeepMind给出了非常多的例子。继DeepMind今年6月在Science上发表论文提出GQN(GenerativeQueryNetwork,生成查询网络)之后,他们相关的研究还在继续。DeepMind今天在Twitter上公开了GQN的一些新扩展、新应用。GQN原本的能力,主要表现为基于几张图像,还原出一个3D场景,并生成这个场景任意视角下的渲染图。当然,作为一项开创性的研究,它所使用的场景,还是比较简单的。如今的这些新进展,将GQN的能力扩展到了连续视频的生成、在MineCraft这种复杂场景中定位、根据文字描述来生成场景等等,甚至还将GQN的训练方法,搬到了更广泛的回归、分类等任务上。我们来分别看一看。用GQN的训练方式搞定其他任务DeepMind认为,GQN创造的训练机制很不错。于是,他们在最新的两项神经过程(NeuralProcesses)研究中,将这种训练机制泛化到了回归、分类等其他小样本预测任务上。这方面的成果,是DeepMind在下周召开的机器学习

  • 《python算法教程》Day11 - 分治法求解平面凸包问题平面凸包问题简介分治法求解思路点与直线的位置判断代码示例

    这是《python算法教程》的第11篇读书笔记,笔记主要内容是使用分治法求解凸包。平面凸包问题简介在一个平面点集中,寻找点集最外层的点,由这些点所构成的凸多边形能将点集中的所有点包围起来。 如下图所示,红色的点能将点集中所有的点包围起来。convexHull.png分治法求解思路按照暴力法的思路(求出所有由点集任意两点的直线,再获取使得点集剩余的点在该直线的一侧的直线)去求解凸包问题,显然算法复杂度达到了n^3,这并不是在时间复杂度上可以接受的算法。 因此,可考虑使用分治法去求解凸包。大体思路如下: 1.找出由横坐标最大、最小的两个点p1p2所组成的直线。用该直线将点集分成上下两set1,set2部分。 2.分别从set1、set2找出与线段p1p2构成的面积最大的三角形的点p3,p4。 3.从set1找出在直线p1p3左侧的点集leftset1、在直线p3p2右侧的点集[图片上传中...(行列式.JPG-bc60bb-1525191974104-0)] rightset1。 4将leftset1,leftset2重复2、3步骤,直至找不到在直线更外侧的点。 5.从set2找出在直线p

  • 2022-10-12:以下go语言代码输出什么?A:1;B:2;C:panic;D:不能编译。package mainimpor

    2022-10-12:以下go语言代码输出什么?A:1;B:2;C:panic;D:不能编译。packagemain import"fmt" funcmain(){ m:=map[string]int{"uno":1} p:=&m["uno"] *p=2 fmt.Println(m["uno"]) }复制答案选D。编译报错invalidoperation:cannottakeaddressofm["uno"](mapindexexpressionoftypeint)。golang里面的map,当通过key获取到value时,这个value是不可寻址的,因为map会进行动态扩容,当进行扩展后,map的value就会进行内存迁移,其地址发生变化,所以无法对这个value进行寻址。

  • 《Entity Framework 6 Recipes》中文翻译系列 (7) -----第二章 实体数据建模基础之拆分实体到多表以及拆分表到多实体

    2-6拆分实体到多表 问题   你有两张或是更多的表,他们共享一样的主键,你想将他们映射到一个单独的实体。 解决方案   让我们用图2-15所示的两张表来演示这种情况。 图2-15,两张表,Prodeuct和ProductWebInfo,拥有共同的主键   按下面的步骤为这两张表建模一个单独实体:   1、在你的项目中,创建一个继承至DbContext的上下文对象EF6RecipesContext;   2、使用代码清单2-8创建一个POCO实体Product;  代码清单2-8:创建一个POCO实体Product 1publicclassProduct{ 2[Key] 3[DatabaseGenerated(DatabaseGeneratedOption.None)] 4publicintSKU{get;set;} 5publicstringDescription{get;set;} 6publicdecimalPrice{get;set;} 7publicstringImageURL{get;set;} 8}复制   3、在EF6RecipesContext中添加类型为DbS

  • wget爬虫

     wget-c-r-np-k-L-p-xdomain

  • 枚举的使用

    枚举的使用 1.0一般怎么使用枚举是为了规范类型如性别、季节。枚举的使用类型如下代码 publicenumGender { 男=1, 女=2 } publicenumGender2 { 男, 女 } publicenumSeason { 春=1, 夏=2, 秋=3, 冬=4 } 复制 1.1测试案例 internalclassProgram { staticvoidMain(string[]args) { Gendergender=Gender.男; Console.WriteLine(gender); gender=Gender.女; Console.WriteLine(gender); Console.WriteLine(gender.GetTypeCode());//回去枚举的code类型 Console.WriteLine(gender.ToString()); Console.WriteLine(((int)gender).ToString()); Seasonseason=Season.春; Console.WriteLine(season); Console.Wri

  • umeditor 上传图片 相对路径的设置和保存

    此篇文章仅献给已实现百度富文本编辑器,想要设置相对路径并保存到数据库,方便以后项目迁移。 使用的版本为1.2.3,适用图片上传中点击以及拖拽功能。 //保存图片相对地址的设置       //1.请修改Uploader.java的getPhysicalPath()方法,设置返回的地址       //2.请修改imageUp.jsp中的相对地址result       //3.请修改image.js中的getAllPic()设置src、_src返回值复制  1、修改后台代码Uploader.java /** *根据传入的虚拟路径获取物理路径 * *@parampath *@return */ privateStringgetPhysicalPath(Stringpath){ //原版:上传文件放在请求路径(百度编辑器)上一级 //StringservletPath

  • javascript Cookie

    cookie是以键值对的形式保存的,即key=value的格式。各个cookie之间一般是以“;”分隔。    JS设置cookie: 假设在A页面中要保存变量username的值("jack")到cookie中,key值为name,则相应的JS代码为:  document.cookie="name="+username;复制 JS读取cookie: 假设cookie中存储的内容为:name=jack;password=123 则在B页面中获取变量username的值的JS代码如下: varusername=document.cookie.split(";")[0].split("=")[1];复制  

  • NO.006-2018.02.11《卜算子&#183;我住长江头》宋代:李之仪

    卜算子·我住长江头_古诗文网(bǔ) 卜算子·我住长江头 宋代:李之仪 我住长江头,君住长江尾。日日思君不见君,共饮长江水。我居住在长江上游,你居住在长江下游。天天想念你却见不到你,共同喝着长江的水。已:完结,停止。 此水几时休,此恨何时已。只愿君心似我心,定不负相思意。长江之水,悠悠东流,不知道什么时候才能休止,自己的相思离别之恨也不知道什么时候才能停歇。只希望你的心思像我的意念一样,就一定不会辜负这互相思念的心意。休:停止。定:此处为衬字。思:想念,思念。 译赏内容整理自网络(或由匿名网友上传),原作者已无法考证,版权归原作者所有。本站免费发布仅供学习参考,其观点不代表本站立场。站务邮箱:service@gushiwen.org     宋词三百首 ,宋词精选 ,婉约 ,长江 ,思念 ,爱情   译文及注释 译文我居住在长江上游,你居住在长江尾底。日日夜夜想

  • SpingBoot框架课

    一、IDEA安装 1.下载 官方下载地址:https://www.jetbrains.com/zh-cn/idea/download/#section=windows 下载专业版(Ultimate版) 2.安装 下面的页面可以全选,其他页面一律默认即可。安装完需要重启电脑。 3.激活 优先下载最新专业版 试用30天:免费 教育邮箱(xxx@xxx.edu.cn)激活:免费 学信网激活:免费 在官网购买激活码:个人专业版1000元左右,可以购买当前版本的永久权限;更新版本需要1000元/年。 去淘宝买激活码:几块-几十元不等。 其他 4.新建项目 选项: Language:Java Buildsystem:Maven JDK:1.8(AmazonCorrettoversion1.8.0_332)会自动安装,无需下载 Addsamplecode:勾选上 5.切换成中文界面 6.切换成白色界面 二、基本概念 JDK、JRE、JVM的关系: JDK:JavaDevelopmentKit,Java开发工具包 JRE:JavaRuntimeEnvironment,Java

  • 16进制数

    0x开头的数代表十六进制数,字母不区分大小写 如: 0x07==>7 0x0000FFF==>4095  

相关推荐

推荐阅读