1.4 SciPy

1.4.1 图像模糊

做滤波操作的模块,scipy.ndimage.filters模块

下面是一个有关高斯模糊核的应用,对灰度图像和彩色图像的模糊。

# 1.4.1 图像模糊
# SciPy有用来做滤波操作的scipy.ndimage.filters模块

from PIL import Image
from pylab import *
from numpy import *
from scipy.ndimage import filters

im = array(Image.open("C:/Users/Lenovo/Desktop/picture/call me the queen.jpg").convert('L'))
im2 = filters.gaussian_filter(im, 5)  # 函数最后一个参数表示标准差,越大越模糊
gray()
# 以上是对灰度图像进行模糊
figure(1)
subplot(1, 2, 1)
imshow(im)
subplot(1, 2, 2)
imshow(im2)

# 若对彩色图像进行模糊,只需要对每一个颜色通道进行高斯模糊
im_1 = array(Image.open("C:/Users/Lenovo/Desktop/picture/call me the queen.jpg"))
im_2 = zeros(im_1.shape)
for i in range(3):
    im_2[:,:,i] = filters.gaussian_filter(im_1[:,:,i], 5)
im_2 = uint8(im_2)  # 并不总是要转为uint8格式,也快写成im_2=array(im_2,'uint8')
figure(2)
subplot(1, 2, 1)
imshow(im_1)
subplot(1, 2, 2)
imshow(im_2)

show()

关于该模块更多的内容以及不同参数的选择,请查看 http://docs.scipy.org/doc /scipy/reference/ndimage.html 上SciPy 文档中的scipy.ndimage 部分。

1.4.2 图像导数

图像强度的变化情况。强度的变化情况可以用灰度图像(对于彩色图像,对每个通道分别计算导数)的x方向和y方向导数进行描述

# 1.4.2 图像导数
# 尝试sobel算子和高斯算子

from PIL import Image
from pylab import *
from numpy import *
from scipy.ndimage import filters

im = array(Image.open("C:/Users/Lenovo/Desktop/picture/call me the queen.jpg").convert('L'))
gray()
# Sobel导数滤波器
imx = zeros(im.shape)
filters.sobel(im, 1, imx)

imy = zeros(im.shape)
filters.sobel(im, 0, imy)

magnitude = sqrt(imx**2+imy**2)
# 正导数显示为亮的像素,负导数显示为暗的像素,灰色区域表示导数的值近似为0
figure(1)
subplot(2, 2, 1)
imshow(im)
subplot(2, 2, 2)
imshow(imx)
subplot(2, 2, 3)
imshow(imy)
subplot(2, 2, 4)
imshow(magnitude)
# 该方法的缺陷,滤波器的尺度需随着图像分辨率的变化而变化

# 为了在图像噪声方便更稳健,以及在任意尺度上计算导数,可以使用高斯导数滤波器

# 若对彩色图像进行模糊,只需要对每一个颜色通道进行高斯模糊
sigma = 5  # 标准差
imxx = zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (0, 1), imxx)
imyy = zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (1, 0), imyy)
magnitude_new = sqrt(imxx**2+imyy**2)
figure(2)
subplot(2, 2, 1)
imshow(im)
subplot(2, 2, 2)
imshow(imxx)
subplot(2, 2, 3)
imshow(imyy)
subplot(2, 2, 4)
imshow(magnitude_new)
show()

1.4.3 形态学:对象计数

形态学(或数学形态学)是度量和分析基本形状的图像处理方法的基本框架与集合。scipy.ndimage中的morphology模块可以实现形态学操作,measurement模块可以实现二值图像的计数和度量功能。

# 1.4.3 形态学:对象计数
from PIL import Image
from pylab import *
from numpy import *
from scipy.ndimage import measurements,morphology

# 载入图像,然后使用阈值化操作,以保证处理的图像为二值图像
im = array(Image.open("houses.png").convert('L'))
gray()  # 自行添加的代码,显示为灰度图像
figure(1), imshow(im)
im = 1*(im < 128)
# 通过和1相乘,脚本将布尔数组转换成二进制表示。
figure(2), imshow(im)

# 形态学开操作更好地分离各个对象,在不同对象间有一些小的连接
im_open = morphology.binary_opening(im, ones((9, 5)), iterations=2)
# 参数2指定一个数组结构元素,表示以一个像素为中心时,使用哪些相邻像素
# 这里y方向上使用9个像素(上面4 个像素、像素本身、下面4 个像素),x上5个像素


labels, nbr_objects = measurements.label(im_open)
# 寻找单个物体,并且按照它们属于哪个对象将整数标签给像素赋值
print('Number of objects:', nbr_objects)
figure(3), imshow(im_open)

1.4.4 一些有用的SciPy模块

该模块中含有一些用于输入和输出的实用模块。如io和misc

1.读写.mat文件

data = scipy.io.loadmat('test.mat')
# data对象包含一个字典,字典中的键对应于保存在原始.mat文件中的变量名

# 写入.mat文件中
# 创建一个字典,将需要保存的所有变量加入字典中
data = {}
data['x'] = x
scipy.io.savemat('test.mat',data)

2.以图像形式保存数组

将数组直接保存为图像文件非常有用。imsave函数可以从scipy.misc模块载入。可以使用下面的命令:

from scipy.misc import imsave
imsave('test.jpg',im)
# 将数组im保存到jpg文件中

此外,scipy.misc模块包含著名的Lena测试图像,

lena = scipy.misc.lena() # 返回一个512×512的灰度图像数组

1.5 高级示例:图像去噪

图像去噪是在去除图像噪声的同时,尽可能地保留图像细节和结构的处理技术。

该书中提到ROF(Rudin-Osher-Fatemi)去噪模型,具有很好的性质:使处理后的图片更平滑,同时保持图像边缘和结构信息。

# 1.5 高级示例:图像去噪
from pylab import *
from numpy import *
from numpy import  random
from scipy.ndimage import filters
from imageio import imwrite


def denoise(im, U_init, tolerance=0.1, tau=0.125, tv_weight=100):
    """ 使用A. Chambolle(2005)在公式(11)中的计算步骤实现Rudin-Osher-Fatemi(ROF)去噪模型
    输入:含有噪声的输入图像(灰度图像)、U 的初始值、TV 正则项权值、步长、停业条件
    输出:去噪和去除纹理后的图像、纹理残留"""
    m, n = im.shape  # 噪声图像的大小
    # 初始化
    U = U_init
    Px = im # 对偶域的x 分量
    Py = im # 对偶域的y 分量
    error = 1

    while (error>tolerance):
        Uold = U
        # 原始变量的梯度
        GradUx = roll(U, -1, axis=1)-U  # 变量U 梯度的x 分量
        # roll()函数是在一个坐标轴上,循环滚动数组中的元素值,可以
        # 方便的计算邻域元素的差异
        GradUy = roll(U, -1, axis=0)-U  # 变量U 梯度的y 分量
        # 更新对偶变量
        PxNew = Px + (tau/tv_weight)*GradUx
        PyNew = Py + (tau/tv_weight)*GradUy
        NormNew = maximum(1,sqrt(PxNew**2+PyNew**2))

        Px = PxNew/NormNew # 更新x 分量(对偶)
        Py = PyNew/NormNew # 更新y 分量(对偶)
        # 更新原始变量
        RxPx = roll(Px,1,axis=1)  # 对x 分量进行向右x 轴平移
        RyPy = roll(Py,1,axis=0)  # 对y 分量进行向右y 轴平移

        DivP = (Px-RxPx)+(Py-RyPy) # 对偶域的散度
        U = im + tv_weight*DivP # 更新原始变量
        # 更新误差
        error = linalg.norm(U-Uold)/sqrt(n*m)
        # linalg.norm函数可以衡量两个数组间(如U和Uold)的差异
    return U,im-U # 去噪后的图像和纹理残余


# 使用噪声创建合成图像
im = zeros((500, 500))
im[100:400, 100:400] = 128
im[200:300, 200:300] = 255
im = im + 30*random.standard_normal((500, 500))

U, T = denoise(im, im)
G = filters.gaussian_filter(im, 10)


# 保存生成结果

imwrite('synth_denoise.png',U)
imwrite('synth_gaussian.png',G)

结果上ROF算法是好于高斯滤波的。

你可能感兴趣的:(1.4 SciPy)