使用Julia进行图像处理--使用形态学运算进行图像调整

  • 前言
  • 图像二值化
  • 基本运算
    • 图像侵蚀
      • 使用侵蚀分离物体
      • 准备用于文本识别的图像
    • 图像膨胀
      • 合并几乎连接的对象
      • 突出显示细节
  • 派生操作
    • 图像开运算
    • 图像闭运算
  • 顶帽和低帽操作
    • 调整图像对比度
  • 后记

前言

形态学转换是应用于二进制或灰度图像的简单数学运算。它们用于消除小噪音;缩小,分离或识别对象;并增加对象大小或背景空间。

图像二值化

ImageMorphology软件包的核心部分是灰度图像或二值化图像。二进制图像是指用1或0表示像素的图像。大多数示例都具有以下标准符号:

  1. 0或黑色用作背景
  2. 1或白色用于前景,即对象

使用以下代码通过简单的灰度阈值来创建二进制图像,例如,如果像素值大于0.5,则分配1;如果像素值小于0.5,则分配0。
二进制和灰度图像不是完美的,因为它们可能包含许多缺陷,并且会被噪声或纹理扭曲。形态图像转换旨在通过使用图像的形式和结构来消除这些缺陷。这些操作仅依赖于像素值的相对顺序,而不依赖于它们的数值,它们被广泛用于标识和处理文本,文档以及其他形状,例如线条和框。
以下代码将演示如何创建阈值为0.5的二进制图像。首先加载图像并将简单的数学转换应用于图像的灰度版本:

using Images, ImageView, ImageMorphology
# load an image
img = load("sample-images/bird-3183441_640.jpg");
# convert image to grayscale and binarise the only channel
# 1. 将图像转换为灰度
# 2. 将所有大于0.5的值转换为true,而小于0.5的所有值转换为false
# 3. 通过将1乘以结果数组,它将true和false值转换为1或0
img_binary = 1 * (Gray.(img) .> 0.5);

将转换为二值版本的图像与原始图像放在一起进行对比:

# 使用restrict函数缩放原始图像和二值图像
img = restrict(img)
img_binary = restrict(RGB.(Gray.(img_binary)))
# 使用size标识图像缩放版本的宽度
img_width = size(img, 2)
# 使用填充功能创建新图像,其宽度是原来的两倍
combined_image = fill(RGB4{Float32}(0.,0.,0.), size(img) .* (1, 2))
# 将图像放在一起进行对比
combined_image[:, 1:img_width] = img
combined_image[:, img_width+1:img_width*2] = img_binary
imshow(combined_image)

形态学运算也可以应用于灰度图像。

基本运算

数学形态学是一组与图像的形状或特征有关的非线性运算和技术。图像形态学有两个基本要素:

  1. 二进制或灰度图像
  2. 结构元素

已经讨论了有关图像和配色方案的先决条件,但是结构元素是新的。结构元素通常是一个3x3二值块,可在图像上滑动并更新它。滑动结构元素可以实现两个基本操作:

  1. 图像侵蚀:从对象边界去除像素
  2. 图像膨胀:将像素添加到图像中对象的边界

ImageMorphology包进行的侵蚀和膨胀仅支持3x3结构元素。 3×3正方形是用于形态学运算的最流行的结构元素。较大的结构元素会产生更极端的侵蚀或膨胀效果,通常通过多次重复3x3结构元素运算获得相似的结果。

图像侵蚀

图像侵蚀是数学形态学领域的两个基本运算符之一。侵蚀是缩小图像前景或1值对象的过程。它可以平滑对象边界并去除小物体。
为了了解图像侵蚀的工作方式,首先在包含白噪声的简单图像上进行尝试,然后继续比较将其应用于照片的二值和灰度版本时的结果。

使用侵蚀分离物体

对于此任务,使用如下图片。它具有许多不同的连接图形,并且两侧都添加了噪声:

从加载图像并将其转换为灰度开始:

using Images, ImageView, ImageMorphology
geom_img = load("pictures/geometrical-figures-and-noise.jpg");
geom_img_binary = Gray.(Gray.(geom_img) .> 0.5);#keeps white objects white

接下来,应用erode函数来进行转换:

geom_img_binary_e = erode(geom_img_binary)
imshow(geom_img_binary_e)

以下结果图像将显示在屏幕上。能够看到噪音大大减少并且对象分离得到改善:

一次运行侵蚀功能并不能完全消除噪音,它使对象保持连接。运行erode函数数次查看结果:

geom_img_binary_e = erode(erode(geom_img_binary_e))
geom_img_binary_e = erode(erode(geom_img_binary_e))
imshow(geom_img_binary_e)

准备用于文本识别的图像

将图像侵蚀应用于真实照片,将车牌上的字母和数字与其余内容分开:

首先加载图像,然后创建一个二进制版本,然后多次应用erode函数并比较结果:

using Images, ImageView, ImageMorphology
carplate_img = load("pictures/caribbean-2726429_640.jpg")
carplate_img_binary = Gray.(Gray.(carplate_img) .< 0.5);
# converts black objects to white and vice-versa
carplate_img_binary_e = erode(carplate_img_binary)
imshow(carplate_img_binary)
carplate_img_binary_e = erode(erode(carplate_img_binary_e))
imshow(carplate_img_binary_e)

三次侵蚀图像的结果。图像上没有其他文字,并且车牌清晰。可以用于文本识别任务:

图像膨胀

膨胀是形态学领域中的另一个基本操作。图像膨胀是逐渐扩大前景像素区域的边界或1值对象的大小的过程。因此,前景像素的区域会增大尺寸,平滑对象边界并封闭对象之间的孔和间隙。

合并几乎连接的对象

同样使用在使用侵蚀分离物体部分中使用的图片。它具有许多不同的连接图形,并且两侧都添加了噪声:

首先删除几何对象之间的间隙和孔,并使用以下代码比较一次运行膨胀函数一次和三次的情况:

using Images, ImageView, ImageMorphology
geom_img = load("pictures/geometrical-figures-and-noise.jpg");
geom_img_binary = Gray.(1 * Gray.(geom_img) .> 0.5);
geom_img_binary_d = dilate(geom_img_binary)
imshow(geom_img_binary_d)
geom_img_binary_d = dilate(dilate(geom_img_binary_d))
imshow(geom_img_binary_d)

可以看到三次膨胀后图形之间的重叠增加了很多,并且右侧的噪点变成了单个对象。

突出显示细节

尝试将膨胀函数应用于带有车牌的图像。如果侵蚀功能已将车牌字母和数字分开,则膨胀将扩展每个对象的边界:

using Images, ImageView, ImageMorphology
carplate_img = load("pictures/caribbean-2726429_640.jpg")
carplate_img_binary = Gray.(Gray.(carplate_img) .< 0.5)
carplate_img_binary_d = dilate(carplate_img_binary)
imshow(carplate_img_binary_d)

派生操作

开运算和闭运算是形态学的另外两个主要运算符。它们都源自基本操作-侵蚀和扩张。它们同样通常用于二进制或灰度图像。
从技术角度来看,可以通过以下方式描述开运算和闭运算:

  1. 开运算:这是侵蚀后再膨胀
  2. 闭运算:这是膨胀后再侵蚀

侵蚀不是膨胀的逆过程。通常,侵蚀和膨胀交替进行会产生与原始图像不同的图像,并且偶然会产生相同的结果。
与基本形态运算符一样,确切的运算由结构元素确定,该元素在Julia中固定为3x3的块。

图像开运算

图像开运算在某种程度上可与侵蚀相媲美。它被用于去除边缘的前景像素。但是,总的来说,它不如侵蚀有效。
图像开运算的目标是保持前景区域具有与结构元素相似的形状或可以完全包含结构元素,同时消除前景像素的所有其他区域。
为了说明它在实际中是如何工作的,使用几何图形,并观察开运算与侵蚀的不同之处,将opening函数应用于上一张图片:

using Images, ImageView, ImageMorphology
geom_img = load("pictures/geometrical-figures-and-noise.jpg");
geom_img_binary = Gray.(1 * Gray.(geom_img) .> 0.5);
geom_img_binary_o = opening(geom_img_binary)
imshow(geom_img_binary_e)

比较打开和侵蚀功能所产生的结果,开运算保持大对象不变,同时消除了小点,而侵蚀减少了所有对象的大小。

图像闭运算

图像闭运算是扩张后侵蚀。与开运算类似,它是从侵蚀和膨胀的基本过程创建的,同样,它可以应用于二进制和灰度图像。
闭运算符的结果与膨胀非常相似,但有一些例外。它主要侧重于消除背景色孔,同时又不破坏目标对象的原始边界形状。
与图像开运算类似,使用具有几何图形的图像并调整代码以执行闭运算操作:

using Images, ImageView, ImageMorphology
geom_img = load("pictures/geometrical-figures-and-noise.jpg");
geom_img_binary = Gray.(Gray.(geom_img) .> 0.5);
geom_img_binary_c = closing(geom_img_binary)
imshow(geom_img_binary_c)

如果将显示的图像与膨胀的结果进行比较,会看到大物体的尺寸没有增大,背景的一小部分变为白色。

顶帽和低帽操作

当对从图像中获取一些小细节感兴趣时,可以利用 JuliaMorphology软件包的tophat和bothat运算符专注于检索此类细节。
顶帽操作用于增强深色背景上感兴趣的明亮物体。它通过从原始图像中减去运行开运算函数的结果来变换图像。它包含源图像的那些元素,这些元素小于结构元素并且比其相邻元素明亮。
另一方面,低帽操作则相反。也就是说,它用于增强明亮背景上感兴趣的深色物体。低帽操作运算符返回的图像是从图像的形态封闭运算后的图像中减去原始图像的结果。结果包含的对象或元素小于结构元素,并且比其周围环境暗。
Julia使用以下代码在具有几何图形的图像上执行两个滤波器,从而实现了tophat和bothat函数:

using Images, ImageView, ImageMorphology
# apply tophat and bothat to an image
geom_img = load("pictures/geometrical-figures-and-noise.jpg");
geom_img_gray = Gray.(geom_img);
geom_img_th = tophat(geom_img_gray)
geom_img_bh = bothat(geom_img_gray)
# create a preview
geom_img_new = zeros(ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}}, size(geom_img_gray) .* (1, 2));
geom_img_new_center = Int(size(geom_img_gray, 2))
geom_img_new[:, 1:geom_img_new_center] = geom_img_th
geom_img_new[:, geom_img_new_center:end - 1] = geom_img_bh
geom_img_new[:, geom_img_new_center] = 1
imshow(Gray.(geom_img_new))

从以下结果中可以看到,tophat函数抑制了所有大对象,只保留了原始图像的小细节:

调整图像对比度

通过将原始图像添加到经过顶帽过滤的图像中,然后减去经过低帽过滤的图像,可以在灰度图像上调整图像对比度:

using Images, ImageView, ImageMorphology
minmax = scaleminmax(Gray, 0, 1) # limit values on a scale from 0 to 1
# adjust image contrast
img = load("pictures/custom_image_name.jpg");
img_gray = Gray.(img);
img_new = minmax.(img_gray + tophat(img_gray) - bothat(img_gray))
# adjust image contrast
# merge the original image with adjusted for preview
img_center = Int(size(img_gray, 2) / 2)
img_gray[:, img_center:end] = img_new[:, img_center:end]
img_gray[:, img_center] .= 0
imshow(img_gray)

在前面的代码中,首先定义了minmax函数,该函数将像素值限制在0到1的范围内。除了加载图像并将其转换为灰度外,还实现了负责调整对比度的代码部分。
有时,使用tophat和bothat函数的100%值会产生巨大影响,并使图像失真。使用从0到1的比例乘数来最小化tophat和bothat函数的影响,从而解决了失真问题。
在左侧看到原始版本,在右侧看到调整后的版本。从这张照片可以看出,右侧细节的质量有了明显的改善:

img = load("pictures/custom_image_name.jpg");
img_gray = Gray.(img);
img_new = minmax.(img_gray + tophat(img_gray) * 0.5 - bothat(img_gray) * 0.5)
img_center = Int(size(img_gray, 2) / 4)
img_gray[:, img_center:end] = img_new[:, img_center:end]
img_gray[:, img_center] = 0
imshow(img_gray)

后记

Enjoy coding.

使用Julia进行图像处理--使用形态学运算进行图像调整相关推荐

  1. 使用色彩追踪和形态学运算得到图像中感兴趣区域

    色彩追踪简介:在RGB图像中,我们感兴趣的部分往往具有趋于一致的颜色,我们想得到感兴趣部分时,可以考虑先找到特定颜色的区域.比如说有一张风景照,我们对蓝天白云(其它部分不是蓝色)感兴趣,我们考虑使用色 ...

  2. 图像形态学运算之图像开闭运算 含python实现

    如果您觉得本文不错,帮忙点赞哦! 一. 图像形态学处理 -- 膨胀和腐蚀 图解图像腐蚀和膨胀 ↑ 二. 开运算与闭运算: 开运算:先腐蚀后膨胀,能够消除图像区域外的小白点(噪声). 闭运算:先膨胀后腐 ...

  3. 用形态学运算变换图像

    数学形态学用于分析和处理离散图像,它定义了一系列的运算,用预定义的形状元素探测图像,从而实现图像的转换. 1.形态学滤波器腐蚀和膨胀图像 结构元素定义为像素的组合,在对应的像素上定义一个原点(锚点). ...

  4. [Python图像处理] 十.形态学之图像顶帽运算和黑帽运算

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  5. [Python图像处理] 九.形态学之图像开运算、闭运算、梯度运算

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  6. 数字图像处理(13): 形态学处理——图像开运算与图像闭运算

    目录 1 图像开运算(先腐蚀,后膨胀) 1.1 基本原理 1.2 代码示例 2 图像闭运算(先膨胀,后腐蚀) 2.1 基本原理 2.2 代码示例 3 图像梯度运算(膨胀 - 腐蚀) 3.1 基本原理 ...

  7. 数字图像处理:第八章 形态学运算

    第八章 形态学运算 目录 引言 基本概念 开运算和闭运算 击中击不中变换HMT(Hit-Miss Transform) 边界和骨架(Boundary and Skeleton) 作业 1.引言 形态学 ...

  8. Skimage图像处理教程5)形态学运算

    上一讲中已经介绍了如何介绍开闭,膨胀腐蚀,白顶帽黑顶帽运算等内容,这一讲主要介绍如何用python的skimage做其他的形态学运算,如去除小区域,提取图像骨架, # 移除小的区域 skimage.m ...

  9. Python图像处理:形态学操作

    来源:DeepHub IMBA本文约1400字,建议阅读5分钟 形态学的操作主要是去除影响图像形状和信息的噪声.形态学运算在图像分割中非常有用,可以得到无噪声的二值图像. 形态学方法 当图像经过预处理 ...

最新文章

  1. 《信息安全技术健康医疗数据安全指南》国家标准
  2. MySQL分库分表使用Snowflake全局ID生成器(3rd)
  3. 【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting)
  4. Lesson 13.4 Dead ReLU Problem与学习率优化
  5. Orange Business Services 助力汽车制造商宝沃构建数字化基础架构
  6. php考察新人的题目,PHP面试指南2020-sql考察题
  7. 为什么说流处理即未来?
  8. Java判断100到200之间所有的素数,并且输出这些素数
  9. Function的常用属性和方法
  10. 2018CCPC网络赛
  11. ASM 转自三思笔记
  12. w ndoWs8pE模式下载,windows pe官方版下载_windows pe v8.2 - Win7旗舰版
  13. 物联网行业系列深度报告 附下载
  14. 程序员木讷?我反手就是一串代码把姑娘撩到幸福地流泪
  15. thingworx- 用户组
  16. 懈寄生---走出软件作坊:三五个人十来条枪 如何成为开发正规军(十四)
  17. 计算机表格中如何计算数据透视表,Excel表格中在数据透视表中添加计算字段的方法...
  18. NIST数字测试套件使用说明
  19. python复制excel模板并保留表格样式
  20. cf-tool 简易使用教程

热门文章

  1. How to pronounce symbols on keyboard
  2. sql 中 case when 语法
  3. SUS安装配置简明图解攻略
  4. 102. 二叉树的层次遍历
  5. BZOJ.3261.最大异或和(可持久化Trie)
  6. 小米路由通过SSH添加静态路由表之后无法跳转的问题
  7. 《Linux命令行与shell脚本编程大全 第3版》
  8. java.util.HashMap
  9. angularjs中的单选框绑定数据注意事项
  10. sdut2355Binary Search Heap Construction