Scipy图像处理

本文主要用到的图像处理的方法:

  • plt.imread()
  • plt.imshow()
  • misc.imread()
  • misc.save()
  • scio.savemat()
  • misc.imrotate()
  • misc.imresize()
  • misc.imfilter()
  • scipy.ndimage图片处理

二维图像处理

使用scipy.fftpack模块来计算快速傅里叶变换,速度比传统傅里叶变换快,是对之前算法的改进。

灰度图片是二维数据,处理使用的是fftpack的二维转变方法。

  1. import numpy as np
  2. import pandas as pd
  3. from pandas import Series, DataFrame
  4. import matplotlib.pyplot as plt
  5. %matplotlib inline
  6. # 处理傅里叶变换的函数
  7. from scipy.fftpack import ifft2, fft2, ifft, fft

numpy也提供了fft/ifft函数,但是执行效率没有scipy的高

这里引入一个概念,时域和频域:

时域:是真实世界,是惟一实际存在的域。因为我们的经历都是在时域中发展和验证的,已经习惯于事件按时间的先后顺序地发生。而评估数字产品的性能时,通常在时域中进行分析,因为产品的性能最终就是在时域中测量的。

频域:它不是真实的,而是一个数学构造。时域是惟一客观存在的域,而频域是一个遵循特定规则的数学范畴,正弦波是频域中唯一存在的波形。

对于二维图片的处理主要分为以下几个步骤:

  1. 首先是加载图片,使用imread()方法,加载出来的灰度图像数据,是一个二维数组,没有rgb颜色数据,每个像素点用一个数来表示,就是这个像素点的灰度
  2. 将时域空间的图片数据,映射到频域空间,得到的是一组复数的二维数组
  3. 将频域空间的图片数据,进行滤波操作
  4. 再将频域空间滤波完成的数据,转换回时域空间
  5. 获取二维数组数据中的实数部分,使用imshow()方法展示图像
  1. # 读取灰度图片
  2. moon = plt.imread('moonlanding.png')
  3. # 展示图片使用imshow()方法,传入一个cmap属性来添加各种风格
  4. plt.imshow(moon, cmap='gray')

获取到数据是一组float32类型的0~1之间的浮点数

  1. # 将读取的图片数据,映射到频域空间
  2. fft_moon = fft2(moon)
  3. # 获取的是一组复数数据,用j来表示虚数部分

实现过滤操作使用了一个方法where(),它接收三个参数:

  • condition:过滤条件
  • x:满足过滤条件,填充的值
  • y:不满足过滤条件,填充的值
  1. filted_fft_moon = np.where(np.abs(fft_moon) > 1e4, 0, fft_moon)
  1. # 再把滤波完成的数据转化回时域空间
  2. ifft_moon = ifft2(filted_fft_moon)

转换完的数据依然是一个复数数组,我们需要取实数部分,才能实现对它的展示

  1. # 对复数数组取数值的实数部分
  2. real_moon = np.real(ifft_moon)
  3. # 展示
  4. plt.imshow(real_moon, cmap="gray")

三维图像的处理

三维图像就是一个使用三维数组数据存储的图像,除了灰度二维之外,还存有颜色的rgb数据。

这里处理三维图像,使用了python的图像处理模块PIL,在python中,进行图像处理一般都会用到这个库,pillow模块也是根据PIL模块编写的。

三维图像的处理与二维图像处理的步骤,大致相同。

  1. # 引入PIL模块中的Image方法来处理彩色图像
  2. from PIL import Image
  1. # 读取图片,读取到的数据依然是一个图片
  2. img = Image.open("th.jpg")

将图片数据,转化为数组形式需要经过两步:

  1. 图片数据转化为字节数据
  2. 将字节数据,转化为一维数组

这个数组既是我们需要处理的数据

  1. # 将图片数据转化为字节
  2. # tobytes(): Return image as a bytes object.
  3. b_img = img.tobytes()
  4. # 将字节,转化为数组数据
  5. # np.frombuffer(): 将缓冲区的数据解释为一维数组
  6. img_data = np.frombuffer(b_img, dtype=np.uint8)

至此,我们完成了图片数据的预处理,得到了需要转换过滤的数组数据,下面是数据的转换和过滤。和上文中二维图像的处理相同

  1. # 将时域数据映射为频域数据
  2. fft_img = fft(img)
  3. # 将频域数据进行过滤处理
  4. filted_fft_img = np.where(np.abs(fft_img) < 1e2, 0, fft_img)
  5. # 将处理过后的频域数据转换回时域数据
  6. ifft_img = ifft(filted_fft_img)
  1. # 然后取数据的实数部分,并用uint8编码
  2. data_to_show = np.uint8(np.real(ifft_img))

最后,将数组的数据加载为缓冲区的图片缓冲

  1. img_to_show = Image.frombytes(mode=img.mode, size=img.size, data=data_to_show)

可以使用的颜色映射参数

Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r, BuGn, BuGn_r, BuPu, BuPu_r, CMRmap, CMRmap_r, Dark2, Dark2_r, GnBu, GnBu_r, Greens, Greens_r, Greys, Greys_r, OrRd, OrRd_r, Oranges, Oranges_r, PRGn, PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r, Pastel2, Pastel2_r, PiYG, PiYG_r, PuBu, PuBuGn, PuBuGn_r, PuBu_r, PuOr, PuOr_r, PuRd, PuRd_r, Purples, Purples_r, RdBu, RdBu_r, RdGy, RdGy_r, RdPu, RdPu_r, RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, Reds, Reds_r, Set1, Set1_r, Set2, Set2_r, Set3, Set3_r, Spectral, Spectral_r, Vega10, Vega10_r, Vega20, Vega20_r, Vega20b, Vega20b_r, Vega20c, Vega20c_r, Wistia, Wistia_r, YlGn, YlGnBu, YlGnBu_r, YlGn_r, YlOrBr, YlOrBr_r, YlOrRd, YlOrRd_r, afmhot, afmhot_r, autumn, autumn_r, binary, binary_r, bone, bone_r, brg, brg_r, bwr, bwr_r, cool, cool_r, coolwarm, coolwarm_r, copper, copper_r, cubehelix, cubehelix_r, flag, flag_r, gist_earth, gist_earth_r, gist_gray, gist_gray_r, gist_heat, gist_heat_r, gist_ncar, gist_ncar_r, gist_rainbow, gist_rainbow_r, gist_stern, gist_stern_r, gist_yarg, gist_yarg_r, gnuplot, gnuplot2, gnuplot2_r, gnuplot_r, gray, gray_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r, jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, ocean, ocean_r, pink, pink_r, plasma, plasma_r, prism, prism_r, rainbow, rainbow_r, seismic, seismic_r, spectral, spectral_r, spring, spring_r, summer, summer_r, tab10, tab10_r, tab20, tab20_r, tab20b, tab20b_r, tab20c, tab20c_r, terrain, terrain_r, viridis, viridis_r, winter, winter_r

图片灰度处理

所谓的图片灰度处理,就是把彩色图片数据中,第三维表示rgb颜色的数据,转换成表示灰度的数据。主要通过几个方式:

  1. 取最大值|最小值
  2. 取平均值
  3. 使用权重
  1. # 读取图片数据
  2. img = plt.imread('th.jpg')
  3. # 取最大值,实现灰度处理
  4. plt.imshow(img.max(axis=2), cmap='gray')
  5. # 取平均值,实现灰度处理
  6. plt.imshow(img.mean(axis=2), cmap='gray')
  7. # 使用权重,实现灰度处理
  8. plt.imshow(np.dot(img, np.array([0.5, 0.3, 0.2])), cmap='gray')

dot(a, b, out=None)方法,是数组的点承方法,相当于05Scipy - 图1,接收三个参数,两个数组,和一个输出格式

数值积分,求解圆周率

求解圆周率

integrate

对函数05Scipy - 图2进行积分

  1. # 使用linspace生成一个等差数列,用来绘制图像上的点
  2. x = np.linspace(-1,1,num=100)
  3. # 使用lambda匿名函数来定义需要绘制的函数
  4. f = lambda x: (1-x**2)**0.5
  5. # 定义y为函数的调用,也是我们需要绘制的图形
  6. y = f(x)

为了便于理解,我们将这个函数的图形绘制出来,然后再求解其积分。

这是一个半圆,y取正负,可以绘制成一个圆,更加直观

使用plt进行图像的绘制,再新的笔记中详解。

  1. # 生成画布
  2. plt.figure(figsize=(4,4))
  3. # 定义画图方向
  4. plt.axis("equal")
  5. # 绘制图形
  6. plt.plot(x, y)
  7. plt.plot(x, -y)

使用scipy.integrate进行积分,调用quad()方法

  1. from scipy.integrate import quad

quad()方法接收三个参数:

  1. 参数 1 接收不规则曲线的表达式
  2. 参数 2、3 接收不规则曲线的左右边界

有两个返回值:

  1. 不规则图形的面积
  2. 积分求解的偏差
  1. # 用area和err来接收这两个参数
  2. area, err = quad(f, -1, 1)
  1. # 圆周率就是面积的二倍
  2. area*2

Scipy文件输入/输出

import scipy.io as io

随机生成数组,使用scipy中的io.savemat()保存

文件格式是.mat,标准的二进制文件

scio()方法的参数:

  • file_name:要保存的图片的文件名
  • mdic:传入保存的mat文件的字典数据
  • appendmat:布尔值,是否添加may后缀,默认添加,
  • format:字符串,’5’或’4’,分别表示MATLAB5以上到7.2,或4一下版本的mat文件
  • long_field_names:布尔值,为True时兼容MATLAB7.6以上,文件名最长63个字节
  • oned_as:’row’或’column’,保存为横向或纵向向量
  1. import scipy.io as scio

借用上文中加载的img图像信息,示例图像保存方法

  1. scio.savemat(file_name="img", mdict={"data": img})

使用io.loadmat()读取数据,读取到的数据是一个字典,图片信息存储再data键的值里面

  1. plt.imshow(scio.loadmat("img.mat")["data"])

读写图片使用scipy中misc.imread()/imsave()

  1. import scipy.misc as misc
  1. # 读取图片
  2. mm = misc.imread("th.jpg")
  1. # 保存图片
  2. misc.imsave("mm.jpg", mm)

misc的imrotate(旋转)、imresize(缩放)、imfilter(过滤)操作

  1. # 旋转
  2. plt.imshow(misc.imrotate(mm, angle=30))

缩放函数imrotate()接收的参数:

  • arr:需要进行缩放的图片数据,是一个nparray
  • size:缩放大小

    • int:百分比
    • float:比例
    • tuple:按照元组里面的整数进行缩放
  • interp:插值方法,(‘nearest’最近, ‘lanczos’兰索斯算法, ‘bilinear’双线性插值,’bicubic’立方 or ‘cubic’平方)
  • mode:字符串,保存的模式

返回缩放之后的数组数据。

  1. plt.imshow(misc.imresize(mm, 0.3))

imfilter()图像数据过滤,过滤方式ftype ‘blur’模糊, ‘contour’轮廓, ‘detail’细节, ‘edge_enhance’边缘增强, ‘edge_enhance_more’边缘增强提高,’emboss’浮雕, ‘find_edges’边界, ‘smooth’平滑, ‘smooth_more’平滑提高, ‘sharpen’锐化.

  1. plt.imshow(misc.imfilter(mm, "find_edges"))

使用scipy.ndimage图片处理

  1. from scipy import ndimage

使用scipy.misc.face(gray=True)获取图片,使用ndimage移动坐标、旋转图片、切割图片、缩放图片

face()方法描述:Get a 1024 x 768, color image of a raccoon face.获取一个浣熊的脸

  1. # misc.face(gray=True)是一个预加载图片
  2. plt.imshow(misc.face(gray=True), cmap="gray")
  1. face = misc.face(gray=True)
  • shift移动坐标
  1. # float表示延两个轴要移动的像素个数
  2. # 列表 表示分别沿着不同的轴移动
  3. plt.imshow(ndimage.shift(face, [50, 80], mode="mirror"))
  • rotate旋转图片
  1. plt.imshow(ndimage.rotate(face, angle=90), cmap="gray")
  • zoom缩放图片
  1. # float 表示沿着两个轴的压缩比例
  2. # 列表表示沿着两个轴以不同比例缩放
  3. plt.imshow(ndimage.zoom(face, zoom=5), cmap="gray")

使用切片切割图片

  1. plt.imshow(face, cmap="gray")
  1. # 切割图片
  2. data = face[70:700, 650:780]
  3. plt.imshow(data, cmap="gray")

图片进行过滤

添加噪声,对噪声图片使用ndimage中的高斯滤波、中值滤波、signal中维纳滤波进行处理

使图片变清楚

加载图片,使用灰色图片misc.face()添加噪声

  1. # 生成噪声数据,因为图片数据是用uint8 彩色数据来存储的,所以噪声数据也要定义成uint8格式
  2. # 并且,噪声数据应该和图片切片数据的形状相同
  3. noise_data = np.uint8(np.random.randint(0,250,size=data.shape)*0.2).reshape(130*630)
  4. # 获取噪声数据的索引
  5. random_index = np.random.randint(0,noise_data.size, 1000)
  6. # 根据图片数据的形状,重捏噪声数据形状
  7. noise = noise_data.reshape(data.shape)
  8. # 将噪声数据添加到图片数据中
  9. data += noise
  10. # 展示添加噪声之后的图片
  11. plt.imshow(data, cmap="gray")

gaussian高斯滤波参数sigma:高斯核的标准偏差

  1. plt.imshow(ndimage.gaussian_filter(data, sigma=2), cmap="gray")

median中值滤波参数size:给出在每个元素上从输入数组中取出的形状位置,定义过滤器功能的输入

signal维纳滤波参数mysize:滤镜尺寸的标量

  1. import scipy.signal as signal
  1. # size数值越大模糊效果越明显
  2. plt.imshow(signal.wiener(data, mysize=10), cmap="gray")
  3. moon = plt.imread("moonlanding.png")
  4. plt.imshow(signal.wiener(moon, mysize=10), cmap="gray")