引言

本文是使用python进行图像基本处理系列的第三部分,在本人之前的文章里介绍了一些非常基本的图像分析操作,见文章《使用Numpy和Opencv完成图像的基本数据分析Part I》和《使用Numpy和Opencv完成图像的基本数据分析 Part II》,下面我们将继续介绍一些有关图像处理的好玩内容。

本文介绍的内容基本反映了我本人学习的图像处理课程中的内容,并不会加入任何工程项目中的图像处理内容,本文目的是尝试实现一些基本图像处理技术的基础知识,出于这个原因,本文继续使用 SciKit-Image,numpy数据包执行大多数的操作,此外,还会时不时的使用其他类型的工具库,比如图像处理中常用的OpenCV等:

本系列分为三个部分,分别为part I、part II以及part III。刚开始想把这个系列分成两个部分,但由于内容丰富且各种处理操作获得的结果是令人着迷,因此不得不把它分成三个部分。系列所有的源代码地址:GitHub-Image-Processing-Python。

在上一篇文章中,我们已经完成了以下一些基本操作。为了跟上今天的内容,回顾一下之前的基本操作:

  • 导入图像并观察其属性
  • 拆分图层
  • 灰度处理
  • 对像素值使用逻辑运算符
  • 使用逻辑运算符进行掩码

现在开始本节的内容:

强度变换|Intensity Transformation

首先导入一张图像作为开始:

%matplotlibinlineimport imageio
import matplotlib.pyplot as plt
import warnings
import matplotlib.cbook
warnings.filterwarnings("ignore",category=matplotlib.cbook.mplDeprecation)pic=imageio.imread('img/parrot.jpg')plt.figure(figsize=(6,6))
plt.imshow(pic);
plt.axis('off');

图像底片|Image Negative

强度变换函数在数学上定义为:

S = T(r)

其中r是输入图像的像素,S是输出图像的像素,T是一个转换函数,它将r的每个像素值映射到s中对应的像素值。
负变换,即恒等变换的逆。在负变换中,输入图像的每个像素值从L-1中减去并映射到输出图像上。
在这种情况下,完成以下转换:

S =(L-1)-r

因此,每个像素值都减去255。这样的操作导致的结果是,较亮的像素变暗,较暗的图像变亮,类似于图像底片。

negative =255- pic # neg = (L-1) - imgplt.figure(figsize= (6,6))
plt.imshow(negative);
plt.axis('off');

对数变换|Log transformation

对数转换可以通过以下公式定义:

s = c *log(r + 1)

其中s和r是输出和输入图像的像素值,c是常数。输入图像的每个像素值都会加1,之后再进行对数操作,这是因为如果图像中的像素值为0时,log(0)的结果等于无穷大。因此,为了避免这种情况的发生,输入图像中的每个像素值都加1,使最小像素值至少为1。

在对数变换过程中,与较高像素值相比,图像中的低像素被扩展。较高的像素值在对数变换中被压缩,这导致图像增强。

对数变换中的c值调整了我们想要的增强程度:

%matplotlibinlineimport imageio
import numpyasnp
import matplotlib.pyplotaspltpic=imageio.imread('img/parrot.jpg')
gray=lambdargb:np.dot(rgb[...,:3],[0.299,0.587,0.114])
gray=gray(pic)'''
log transform
-> s = c*log(1+r)So, we calculate constant c to estimate s
-> c = (L-1)/log(1+|I_max|)'''max_=np.max(gray)def log_transform():
return(255/np.log(1+max_))*np.log(1+gray)plt.figure(figsize=(5,5))
plt.imshow(log_transform(),cmap=plt.get_cmap(name='gray'))
plt.axis('off');

伽马校正| Gamma Correction

伽马校正,或通常简称为伽玛,是用于对视频或静止图像系统中的亮度或三刺激值进行编码和解码的非线性操作,伽玛校正也称为幂律变换。首先,图像的像素值大小范围必须从0~255被缩放至0~1.0。然后,通过应用以下等式获得伽马校正后的输出图像:

Vo = Vi ^(1 / G)

其中Vi是我们的输入图像,G是设置的伽玛值,然后将输出图像Vo缩放回0-255范围。

对于伽马值而言,G <1有时被称为编码伽玛,并且利用该压缩幂律非线性进行编码的过程被称为伽马压缩; Gamma值小于1会将图像移向光谱的较暗端。

相反,伽马值G> 1被称为解码伽马,并且膨胀幂律非线性的应用被称为伽马展开。Gamma值大于1将使图像显得更亮。将伽玛值设置为G = 1时对输入图像没有影响:

import imageio
import matplotlib.pyplotasplt# Gamma encoding
pic=image io.imread('img/parrot.jpg')
gamma=2.2# Gamma < 1 ~ Dark ; Gamma > 1 ~ Brightgamma_correction=((pic/255)**(1/gamma))
plt.figure(figsize=(5,5))
plt.imshow(gamma_correction)
plt.axis('off');

伽马校正的原因|Reason for Gamma Correction

我们应用伽马校正的原因是,由于我们的眼睛感知颜色和亮度这一过程与数码相机中的传感器的工作原理不同。当数码相机上的传感器获得两倍的光子量时,信号会加倍。但是,我们人类的眼睛的工作原理与这不同,当我们的眼睛感知两倍的光量时,视野中只有一小部分显得更亮。

因此,数码相机在亮度之间具有线性关系,而我们人类的眼睛具有非线性关系。为了解释这种关系,我们应用伽玛校正。

还有一些其他的线性变换函数,比如:

  • 对比度拉伸(Contrast Stretching)
  • 强度切片(Intensity-Level Slicing)
  • 位平面切片(Bit-Plane Slicing)

卷积|Convolution

在上一篇文章中,对卷积操作作了简要讨论。当计算机看到图像时,它看到不是一整幅图像,它的眼里看到的只是一个像素值数组。假设读取一个32X32大小的彩色图像,根据图像的分辨率和大小,计算机它将看到一个32 x 32 x 3维的数字数组,其中3表示RGB值或三通道。

假设现在我们有一个PNG格式的彩色图像,它的大小是480 x 480。将其读入后,其表示数组将是480 x 480 x 3维。数组中的所有的每个数字值范围都在0到255之间,它描述的是那个点的像素强度。

就像我们刚才提到的那样,假设输入图像是一个32 x 32 x 3的像素值数组,解释卷积的最佳方法是想象一个闪烁在图像左上方的手电筒。假设手电筒照射区域大小为3 x 3。

现在,让我们假设这个手电筒滑过输入图像的所有区域。在机器学习术语中,这个手电筒被称为过滤器(filter)或内核(kernel),或者有时被称为权重(weights) 或  掩模(mask),它所照射的区域称为 感受野(receptive field)。

现在,此过滤器也是一个数字数组,数组中的数字称为权重或参数,在这里要着重注意一点,此过滤器的深度必须与输入图像的深度相同,即通道数相同,因此此过滤器的尺寸为3 x 3 x 3。

图像内核 或过滤器是一个小矩阵,用于应用我们可能在Photoshop或Gimp中找到的效果,例如模糊、锐化、轮廓或浮雕等。此外,它们还被用于在机器学习中进行图像特征提取(CNN),这是一种用于确定图像最重要部分的技术。更多相关信息,请查看Gimp关于使用Image kernel的文档,我们可以该文档中找到最常见的内核列表  。

现在,让我们将过滤器放在图像的左上角。当滤波器围绕输入图像滑动或卷积时,它将滤波器中的值乘以图像的原始像素值(也称为计算元素乘法)。这些乘法操作最后都会求和,所以卷积操作后只得到一个数字值。请记住,此数字仅代表过滤器位于图像的左上角。

现在,我们对输入图像上的每个位置重复此过程,移动过滤器使其与图像矩阵的每个像素值进行卷积操作,这个过程需要设置移动步幅,依此类推,完成整幅图像的卷积操作。输入图中的每个唯一位置都会生成一个数字。步幅的取值一般为1,也可以取其它大小的值,但我们关心的是它是否适合输入图像。

过滤器滑过输入图像上的所有位置后,我们会发现,我们剩下的是一个30 x 30 x 1的数组,我们将其称为激活图 或特征图。将3 x 3过滤器可以放在32 x 32输入图像上,可以得到30 x 30大小的阵列,原因是有300个不同的位置,这900个数字映射到30 x 30阵列。我们可以通过以下方式计算卷积图像后图像的大小:

  • 卷积:(N-F)/ S + 1

其中N和F分别代表输入图像大小和卷积核大小,S代表步幅或步长。因此,对于上述情况,输出图像的大小将是

  • 32-31 + 1 = 30

假设我们有一个3x3滤波器,在5x5大小的矩阵上进行卷积,根据等式,我们应该得到一个3x3矩阵,现在让我们看一下:

此外,我们实际上使用的过滤器不止一个,过滤器的数量自己设定,假设过滤器的数量设置为n,则我们的输出将是28x28xn大小(其中n是特征图的数量  )。

通过使用更多的过滤器,我们能够更好地保留空间维度信息。

然而,对于图像矩阵边界上的像素,卷积核的一些元素移动时会出现在图像矩阵之外,因此不具有来自图像矩阵的任何对应元素。在这种情况下,我们可以消除这些位置的卷积运算,最终输出矩阵大小将会小于输入图像,或者我们可以对输入图像矩阵进行填充(padding),以保证输出图像大小维度不变。

为了保持本系列的简洁而保持内容的完整性,本文提供了全部的资源链接,在其中更详细地解释了有关内容。

下面,让我们首先将一些自定义卷积核个数的窗口应用于图像中,这可以通过平均每个像素值与附近的像素值来处理图像:

%%time
import numpy as np
import imageio
import matplotlib.pyplot as plt
from scipy.signal import convolve2ddef Convolution(image, kernel):
conv_bucket= []
for d in range(image.ndim):
conv_channel= convolve2d(image[:,:,d], kernel, mode="same", boundary="symm")
conv_bucket.append(conv_channel)
returnnp.stack(conv_bucket, axis=2).astype("uint8")kernel_sizes= [9,15,30,60]
fig, axs=plt.subplots(nrows=1, ncols=len(kernel_sizes), figsize=(15,15));pic =imageio.imread('img:/parrot.jpg')for k, ax in zip(kernel_sizes, axs):kernel =np.ones((k,k))kernel /=np.sum(kernel)
ax.imshow(Convolution(pic, kernel));
ax.set_title("Convolved By Kernel: {}".format(k));
ax.set_axis_off();
Wall time: 43.5 s

更多内容可以在此查看,其中已经深入讨论了各种类型的内核,并展示了它们之间的差异。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

使用Numpy和Opencv完成图像的基本数据分析(Part III)相关推荐

  1. 使用Numpy和Opencv完成图像的基本数据分析(Part II)

    摘要: 使用Numpy和Opencv完成图像的基本数据分析后续部分,主要包含逻辑运算符操作.掩膜以及卫星图像数据分析等操作 在上一节中,主要是介绍了图像的基本知识以及OpenCV的基本操作,具体内容参 ...

  2. Python 对图像进行base64编码及解码读取为numpy、opencv、matplot需要的格式

    Python 对图像进行base64编码及解码读取为numpy.opencv.matplot需要的格式 1. 效果图 2. 源码 参考 这篇博客将介绍Python如何对图像进行base64编解码及读取 ...

  3. 使用Numpy和Opencv完成基本图像的数据分析(Part I)

    云栖君导读: 随着科技的进步,使用Python包访问数字图像的内部变得更容易理解其属性和性质,掌握对数字图像处理的能力显得十分有必要. 对于深度学习而言,很多任务都是与数字图形处理打交道.这类任务的数 ...

  4. Python,OpenCV骨架化图像并显示(skeletonize)

    Python,OpenCV骨架化图像并显示(skeletonize) 1. 效果图 2. 源码 参考: 1. 效果图 自己画一张图,原图 VS 骨架效果图如下: opencv logo原图 VS 骨架 ...

  5. 使用Python,OpenCV制作图像Mask——截取ROIs及构建透明的叠加层

    使用Python,OpenCV制作图像Mask--截取ROIs及构建透明的叠加层 1. 效果图 2. 源码 参考 这篇博客将介绍如何使用OpenCV制作Mask图像掩码.使用位运算和图像掩码允许我们只 ...

  6. 使用Python,OpenCV实现图像和实时视频流中的人脸模糊和马赛克

    使用Python,OpenCV实现图像和实时视频流中的人脸模糊和人脸马赛克 1. 效果图 2. 原理 2.1 什么是人脸模糊,如何将其用于人脸匿名化? 2.2 执行人脸模糊/匿名化的步骤 3. 源码 ...

  7. 使用Python和OpenCV检测图像中的条形码

    使用Python和OpenCV检测图像中的条形码 1. 效果图 2. 算法的步骤 3. 源码 参考 这篇博客将介绍使用计算机视觉和图像处理技术进行条形码检测的必要步骤,并演示使用Python编程语言和 ...

  8. 使用Python,OpenCV查找图像中的最亮点

    Python,OpenCV找出图像中的最亮点 1. 原理 2. 优化 3. 效果图 4. 源码 参考 这篇博客将向您展示如何使用Python和OpenCV查找图像中的最亮点,以及应用单行预处理代码-- ...

  9. 使用Python,OpenCV计算图像直方图(cv2.calcHist)

    使用Python,OpenCV计算图像直方图(cv2.calcHist 1. 效果图 2. 原理 2.1 什么是图像直方图? 2.2 计算直方图 2.3 可视化蒙版区域 3. 源码 参考 这篇博客将介 ...

最新文章

  1. 有没有哪些数学猜想是验证到很大的数以后才发现是错的?
  2. .NET简谈组件程序设计之(详解NetRemoting结构)
  3. Spring @Bean and @Configuration
  4. Linux的Nginx报错emerg unknown directive stub_status in
  5. mnist手写数字识别_手写数字识别
  6. 利用正则表达式截取特定字符中间字符
  7. div中定义局部变量_中高级前端必须要了解的--JS中的内存管理
  8. matlab读取excel里的数据并用imagesc画图
  9. 重拾数月前做的微信红包小项目
  10. 单招软件职业技能测试,高职单招职业技能测试,这些知识你都了解吗?
  11. 西门子系列PLC教学视频资源1——S7-200和S7-200smart
  12. photoshop 插件_适用于Web设计人员的10+个免费Photoshop插件
  13. java存根_如何在JUnit和Java中使用存根?
  14. 盛大开业!三星生活家电体验馆正式入驻红星美凯龙
  15. 3大基础模型,搞掂互联网产品分析
  16. 优化算法选择:SGD、SGDM、NAG、Adam、AdaGrad、RMSProp、Nadam
  17. 1100 校庆 (25 分)
  18. 如何保证API不被别人恶意调用(彩蛋)
  19. 制作U-Boot的SD启动卡
  20. 9月2日最新易启秀源码3GB大小700套模版

热门文章

  1. python列表元素之和_python实现计算列表元素之和
  2. 【学习笔记】MOOC 数学文化赏析 笔记【补档】
  3. 安卓软件错误log_Android编程实现捕获程序异常退出时的错误log信息功能详解
  4. java 注解 target_详解JDK 5 Annotation 注解之@Target的用法
  5. java编程实现素数环_结对编程(JAVA实现)
  6. mysql基准性能测试标准_mysql性能测试与优化——(一),基准测试套件
  7. html彩色背景指令,HTML_第四章 颜色背景的CSS,本 章 C S S 的 主 - phpStudy...
  8. mysql 查看当前数据库编码方式_MySQL查看与修改当前数据库编码的方法
  9. mysql union null_mysql – 删除SQL中的SQL JOIN和UNION操作符中的NULL值
  10. pyqt 取鼠标处文字_爱剪辑:炫彩的动态标题文字特效,这招让视频片头LOGO更酷炫...