PIL提供了通用的图像处理功能,以及大量的基本图像操作,如图像缩放、裁剪、旋转、颜色转换等。

Matplotlib提供了强大的绘图功能,其下的pylab/pyplot接口包含很多方便用户创建图像的函数。

为了观察和进一步处理图像数据,首先需要加载图像文件,并且为了查看图像数据,我们需要将其绘制出来。

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. # 加载图像
  5. img = Image.open("tmp.jpg")
  6. # 转为数组
  7. img_data = np.array(img)
  8. # 可视化
  9. plt.imshow(img_data)
  10. plt.show()

对于图像,我们常见的操作有调整图像尺寸,旋转图像以及灰度变换

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. img = Image.open("girl.jpg")
  4. plt.figure()
  5. # 子图
  6. plt.subplot(221)
  7. # 原图
  8. plt.imshow(img)
  9. plt.subplot(222)
  10. # 将图像缩放至 256 * 256
  11. plt.imshow(img.resize((256, 256)))
  12. plt.subplot(223)
  13. # 将图像转为灰度图
  14. plt.imshow(img.convert('L'))
  15. plt.subplot(224)
  16. # 旋转图像
  17. plt.imshow(img.rotate(45))
  18. # 保存图像
  19. plt.savefig("tmp.jpg")
  20. plt.show()

效果演示 :

在平常的使用中,绘制图像的轮廓也经常被使用,因为绘制轮廓需要对每个坐标(x, y)的像数值施加同一个阙值,所以需要将图像灰度化

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. img = Image.open("girl.jpg")
  5. gray_img = np.array(img.convert('L'))
  6. plt.figure()
  7. # 绘制图像灰度化
  8. plt.gray()
  9. # 关闭坐标轴
  10. plt.axis('off')
  11. # 绘制灰度图像
  12. plt.contour(gray_img, origin='image')
  13. plt.figure()
  14. # 绘制直方图,flatten()表示将数组展平
  15. plt.hist(gray_img.flatten(), 128)
  16. plt.show()

轮廓图及直方图:

图像的直方图用来表征该图像的像素值的分布情况。用一定数目的小区间来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目。hist()函数用于绘制图像的直方图,其只接受一维数组作为第一个参数输入,其第二个参数用于指定小区间的数目。

有时用户需要和应用进行交互,如在一幅图像中标记一些点。Pylab/pyplot库中的ginput()函数就可以实现交互式标注

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. img = Image.open(r"girl.jpg")
  4. plt.imshow(img)
  5. x = plt.ginput(3)
  6. print("clicked point: ", x)

注:该交互在集成编译环境(pyCharm)中如果不能调出交互窗口则无法进行点击,可以在命令窗口下成功执行。

以上我们通过numpy的array()函数将Image对象转换成了数组,以下将展示如何从数组转换成Image对象

  1. from PIL import Image
  2. import numpy as np
  3. img = Image.open(r"girl.jpg")
  4. img_array = np.array(img)
  5. img = Image.fromarray(img_array)

在图像灰度变换中有一个非常有用的例子就是直方图均衡化。直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。

直方图均衡化的变换函数是图像中像素值的累积分布函数(cumulative distribution function,将像素值的范围映射到目标范围的归一化操作)。

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. def histogram_equalization(img: np, nbr_bins=256):
  5. imhist, bins = np.histogram(img.flatten())
  6. cdf = imhist.cumsum() # 累计分布函数
  7. # 归一化
  8. cdf = 255 * cdf / cdf[-1]
  9. # 使用累积分布函数进行线性插值,计算新的像素值
  10. img2 = np.interp(img.flatten(), bins[:-1], cdf)
  11. return img2.reshape(img.shape), cdf
  12. img = Image.open(r"girl.jpg").convert('L')
  13. img2, cdf = histogram_equalization(np.array(img))
  14. plt.figure()
  15. plt.gray()
  16. # 绘制子图
  17. plt.subplot(232)
  18. # 变换函数
  19. plt.plot(cdf)
  20. plt.subplot(231)
  21. plt.hist(np.array(img).flatten(), 256)
  22. # 关闭坐标轴,对上一个子图有效
  23. plt.axis('off')
  24. plt.subplot(233)
  25. plt.hist(np.array(img2).flatten(), 256)
  26. plt.axis('off')
  27. plt.subplot(234)
  28. plt.imshow(img)
  29. plt.axis('off')
  30. plt.subplot(236)
  31. plt.imshow(img2)
  32. plt.axis('off')
  33. # 保存绘制图像
  34. plt.savefig("tmp.jpg")
  35. plt.show()

处理结果

可见,直方图均衡化的图像的对比度增强了,原先图像灰色区域的斜街变得清晰。

PCA(Principal Component Analysis, 主成分分析)是一个非常有用的降维技巧,它可以在使用尽可能少的维数的前提下,尽可能多地保持训练数据的信息。详细介绍及使用见我的另一篇文章:PCA降维

SciPy是建立在Numpy基础上,用于数值运算的开源工具包。Scipy提供很多高效的操作,可以实现数值积分、优化、统计、信号处理,以及对我们来说最为重要的图像处理功能。

图像的高斯模糊是非常经典的图像卷积例子。本质上,图像模糊就是将(灰度)图像 \(I\) 和一个高斯核进行卷积操作:

\[I_\sigma = I * G_\sigma
\]

其中, \(*\) 表示卷积操作;\(G\) 表示标准差为 \(\sigma\) 的二维高斯核,定义为:

\[G_\sigma = \frac{1}{2\pi \sigma^2} e^{-(x^2+y^2) / 2 \sigma^2}
\]

高斯模糊通常是其他图像处理操作的一部分,比如图像插值操作、兴趣点计算以及其他应用。

Scipy有用来做滤波操作的scipy.ndimage.filters模块。该模块使用快速一维分离的方式来计算卷积。使用方式:

  1. from PIL import Image
  2. import numpy as np
  3. from scipy.ndimage import filters
  4. img = Image.open(r"girl.jpg").convert('L')
  5. img = np.array(img)
  6. img2 = filters.gaussian_filter(img, 2)
  7. img3 = filters.gaussian_filter(img, 5)
  8. img4 = filters.gaussian_filter(img, 10)

绘制结果

上面使用的gaussian_filter()函数中的后一个参数表示标准差 \(\sigma\) ,可见随着 \(\sigma\) 的增加,图像变得越来越模糊。 \(\sigma\) 越大,处理后图像细节丢失越多。如果是打算模糊一幅彩色图像,只需要简单地对每一个颜色通道进行高斯模糊:

  1. from PIL import Image
  2. import numpy as np
  3. from scipy.ndimage import filters
  4. img = Image.open(r"girl.jpg")
  5. img = np.array(img)
  6. img2 = np.zeros(img.shape)
  7. for i in range(img2.shape[2]):
  8. img2[:, :, i] = filters.gaussian_filter(img[:, :, i], 5)
  9. # 将像素值用八位表示
  10. img2 = np.array(img2, 'uint8')

模糊结果:

在很多应用中,图像强度的变化情况是非常重要的,强度的变化可以使用灰度图像的 \(x\) 和 \(y\) 方向导数 \(I_x\) 和 \(I_y\)进行描述

图像的梯度向量为 \(\bigtriangledown I = [I_x, I_y]^T\)。梯度有两个重要属性,一是梯度的大小:

\[| \bigtriangledown I | = \sqrt{I_x^2 + I_y^2}
\]

它描述了图像强度变化的强弱,另一个是图像的角度:

\[\alpha = arctan2(I_x, I_y)
\]

它描述了图像在每个点上强度变化最大的方向。Numpy中的arctan2()函数返回弧度表示的有符号角度,角度的变化区间为 \((-\pi, \pi)\)

可以使用离散近似的方式来计算图像的导数。图像倒数大多数可以通过卷积简单地实现:

\[I_x = I*D_x 和 I_y = I*D_y
\]

对于 \(D_x\) 和 \(D_y\),通常选择Prewitt滤波器:

\[D_x = \left[
\begin{matrix}
-1 & 0 & 1 \\
-1 & 0 & 1 \\
-1 & 0 & 1
\end{matrix}
\right]
\]

\[D_y = \left[
\begin{matrix}
-1 & -1 & -1 \\
0 & 0 & 0 \\
1 & 1 & 1
\end{matrix}
\right]
\]

或者Sobel滤波器

\[D_x = \left[
\begin{matrix}
-1 & 0 & 1 \\
-2 & 0 & 2 \\
-1 & 0 & 1
\end{matrix}
\right]
\]

\[D_y = \left[
\begin{matrix}
-1 & -2 & -1 \\
0 & 0 & 0 \\
1 & 2 & 1
\end{matrix}
\right]
\]

这些导数滤波器可以使用scipy.ndimage.filters模块地标准卷积操作来简单地实现

  1. from PIL import Image
  2. import numpy as np
  3. from scipy.ndimage import filters
  4. img = Image.open(r"girl.jpg").convert('L')
  5. img = np.array(img)
  6. imgx = np.zeros(img.shape)
  7. # Sobel导数滤波器
  8. filters.sobel(img, 1, imgx)
  9. imgy = np.zeros(img.shape)
  10. filters.sobel(img, 0, imgy)
  11. magnitude = np.sqrt(imgx**2+imgy**2)

sobel()函数的第二个参数选择 \(x\) 或 \(y\) 方向的导数,第三个参数保存输出变量。在图像中,正导数显示为亮的像素,负导数显示为暗的像素,灰色区域表示导数的值接近零。

上面计算图像导数的方法存在缺陷:在该方法中,滤波器的尺度需要随着图像分辨率的变化而变化(?)。为了在图像噪声方面更稳健,以及在任意尺度上计算导数,我们可以使用高斯导数滤波器:

\[I_x = I * G_{\sigma x} 和 I_y = I*G_{\sigma y}
\]

其中,\(G_{\sigma x}\) 和\(G_{\sigma y}\)表示\(G_\sigma\) 在 \(x\) 和 \(y\) 方向上的导数,\(G_\sigma\) 表示标准差为 \(\sigma\) 的高斯函数。以下给出使用样例:

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. from scipy.ndimage import filters
  5. img = Image.open(r"girl.jpg").convert('L')
  6. img = np.array(img)
  7. sigma = 2
  8. imgx = np.zeros(img.shape)
  9. imgy = np.zeros(img.shape)
  10. filters.gaussian_filter(img, (sigma, sigma), (0, 1), imgx)
  11. filters.gaussian_filter(img, (sigma, sigma), (1, 0), imgy)
  12. magnitude = np.sqrt(imgx**2+imgy**2)

结果演示:

在对图像进行处理时,去噪也是很重要的一环。图像去噪是在去除图像噪声的同时,尽可能地保留图像细节和结构地处理技术,以下给出使用ROF去噪模型地Demo:

  1. from PIL import Image
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. from scipy.ndimage import filters
  5. def de_noise(img, U_init, tolerance=0.1, tau=0.125, tv_weight=100):
  6. U = U_init
  7. Px = Py = img
  8. error = 1
  9. while error > tolerance:
  10. Uold = U
  11. # 变量U梯度的x分量
  12. gradUx = np.roll(U, -1, axis=1)-U
  13. # 变量U梯度的y分量
  14. gradUy = np.roll(U, -1, axis=0)-U
  15. # 更新对偶变量
  16. PxNew = Px + (tau/tv_weight)*gradUx
  17. PyNew = Py + (tau/tv_weight)*gradUy
  18. NormNew = np.maximum(1, np.sqrt(PxNew**2+PyNew**2))
  19. # 更新x,y分量
  20. Px = PxNew / NormNew
  21. Py = PyNew / NormNew
  22. # 更新原始变量
  23. RxPx = np.roll(Px, 1, axis=1) # 将x分量向x轴正方向平移
  24. RyPy = np.roll(Py, 1, axis=0) # 将y分量向y轴正方向平移
  25. DivP = (Px - RxPx) + (Py - RyPy) # 对偶域散度
  26. U = img + tv_weight * DivP
  27. error = np.linalg.norm(U - Uold)/np.sqrt(img.shape[0] * img.shape[1])
  28. return U, img-U
  29. if __name__ == '__main__':
  30. im = np.zeros((500, 500))
  31. im[100:400,100:400] = 128
  32. im[200:300, 200:300] = 255
  33. im = im + 30 * np.random.standard_normal((500, 500))
  34. U, T = de_noise(im, im)
  35. G = filters.gaussian_filter(im, 10)
  36. plt.figure()
  37. plt.gray()
  38. plt.subplot(221).set_title("Original image")
  39. plt.axis('off')
  40. plt.imshow(im)
  41. plt.subplot(222).set_title("Gauss blurred image")
  42. plt.axis('off')
  43. plt.imshow(G)
  44. plt.subplot(223).set_title("ROF")
  45. plt.axis('off')
  46. plt.imshow(U)
  47. plt.savefig('tmp.jpg')
  48. plt.show()

结果演示

ROF去噪后的图像保留了边缘和图像的结构信息,同时模糊了“噪声”。

np.roll()函数可以循环滚动元素,np.linalg.norm()用于衡量两个数组间的差异。

之后有空将补充图像去噪

参考书籍

Python计算机视觉

基本图像操作和处理(python)的更多相关文章

  1. Python用Pillow(PIL)进行简单的图像操作

    Python用Pillow(PIL)进行简单的图像操作 颜色与RGBA值 计算机通常将图像表示为RGB值,或者再加上alpha值(通透度,透明度),称为RGBA值.在Pillow中,RGBA的值表示为 ...

  2. python进阶—OpenCV之常用图像操作函数说明(转)

    文章目录cv2.thresholdcv2.bitwise_andcv2.bitwise_orcv2.bitwise_notcv2.inRangecv2.resizecv2.adaptiveThresh ...

  3. 2014 年10个最佳的PHP图像操作库

    2014 年10个最佳的PHP图像操作库   Thomas Boutell 以及众多的开发者创造了以GD图形库闻名的一个图形软件库,用于动态的图形计算. GD提供了对于诸如C, Perl, Pytho ...

  4. 2014 年10个最佳的PHP图像操作库--留着有用

    Thomas Boutell 以及众多的开发者创造了以GD图形库闻名的一个图形软件库,用于动态的图形计算. GD提供了对于诸如C, Perl, Python, PHP, OCaml等等诸多编程语言的支 ...

  5. 10个最佳的PHP图像操作库

    Thomas Boutell 以及众多的开发者创造了以GD图形库闻名的一个图形软件库,用于动态的图形计算. GD提供了对于诸如C, Perl, Python, PHP, OCaml等等诸多编程语言的支 ...

  6. 学习笔记TF015:加载图像、图像格式、图像操作、颜色

    TensorFlow支持JPG.PNG图像格式,RGB.RGBA颜色空间.图像用与图像尺寸相同(height*width*chnanel)张量表示.通道表示为包含每个通道颜色数量标量秩1张量.图像所有 ...

  7. Tensorflow图像操作

    图像操作 图像基本概念 在图像数字化表示当中,分为黑白和彩色两种.在数字化表示图片的时候,有三个因素.分别是图片的长.图片的宽.图片的颜色通道数.那么黑白图片的颜色通道数为1,它只需要一个数字就可以表 ...

  8. TensorFlowIO操作(三)------图像操作

    图像操作 图像基本概念 在图像数字化表示当中,分为黑白和彩色两种.在数字化表示图片的时候,有三个因素.分别是图片的长.图片的宽.图片的颜色通道数.那么黑白图片的颜色通道数为1,它只需要一个数字就可以表 ...

  9. PDF各种骚操作如何用python实现

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: wLsq PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

随机推荐

  1. 一个项目中:只能存在一个 WebMvcConfigurationSupport (静态文件失效之坑)

    一个项目中:只能存在一个 WebMvcConfigurationSupport 在一个项目中WebMvcConfigurationSupport只能存在一个,多个的时候,只有一个会生效. 静态文件访问 ...

  2. SQLServer2000同步复制技术实现步骤

    SQLServer2000同步复制技术实现步骤 一. 预备工作 1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户 --管理工具 --计算 ...

  3. 100天搞定机器学习|Day15 朴素贝叶斯

    Day15,开始学习朴素贝叶斯,先了解一下贝爷,以示敬意. 托马斯·贝叶斯 (Thomas Bayes),英国神学家.数学家.数理统计学家和哲学家,1702年出生于英国伦敦,做过神甫:1742年成为英 ...

  4. webpack4核心模块tapable源码解析

    _ 阅读目录 一:理解Sync类型的钩子 1. SyncHook.js 2. SyncBailHook.js 3. SyncWaterfallHook.js 4. SyncLoopHook.js 二: ...

  5. Qt基于sqlite数据库的管理小软件

    闲来无事,写了一个基于sqlite的数据库管理小软件. 先上图 中心思想就是: 创建一个数据库 然后每一个分组对应一个数据表 然后遍历该数据表.将名字以treewidgetItem显示出来.添加删除实 ...

  6. 【Kubernetes 系列一】Kubernetes 概述

    以下内容还可以通过 Google Slide 查看:https://docs.google.com/presentation/d/1eYP4bkVBojI_e6PqdpxIf0hvWO-JwAf-fy ...

  7. jQuery学习和知识点总结归纳

    jQuery目前在Web前端开发所占的比重越来越高,在我们jQuery学习和开发的过程中都会去使用.jQuery帮我们解决了浏览器之间JS一些不兼容的地方和简化了原生JS对DOM的操作.下面把PHP程 ...

  8. 【原创实践】U大师启动安装windows XP

    1:使用U大师3.0版制作启动U盘,拷贝windows xp或者win7的原版安装iso(zh-hans_windows_xp_professional_with_service_pack_3_x86 ...

  9. 利用tensorboard可视化checkpoint模型文件参数分布

    写在前面: 上周微调一个文本检测模型seglink,将特征提取层进行冻结,只训练分类回归层,然而查看tensorboard发现里面有histogram显示模型各个参数分布,看了目前这个训练模型参数分布 ...

  10. 【0806 | Day 9】三张图带你了解数据类型分类和Python深浅拷贝

    一.数据类型分类 二.Python深浅拷贝