基本的图像处理和操作——Scipy

1.Scipy

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

1.1图像模糊

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

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

# 添加中文字体支持
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)



figure()

im = array(Image.open('empire.jpg').convert('L'))
im2 = filters.gaussian_filter(im,2)
subplot(1,3,1)
imshow(im2)
axis("off")
title(u'grayGaussianSigma==2', FontProperties=font)

im = array(Image.open('empire.jpg').convert('L'))
im2 = filters.gaussian_filter(im,5)
subplot(1,3,2)
imshow(im2)
axis("off")
title(u'grayGaussianSigma==5', FontProperties=font)

im = array(Image.open('empire.jpg').convert('L'))
im2 = filters.gaussian_filter(im,10)
subplot(1,3,3)
imshow(im2)
axis("off")
title(u'grayGaussianSigma=10', FontProperties=font)

show()

上面gaussian_filter()函数的最后一个参数表示标准差。

上图显示了随着sigma的增加,一幅图像被模糊的程度。sigma越大,处理后的图像细节丢失越多。如果打算模糊一幅彩色图像,只需简单地对每一个颜色通道进行高斯模糊:

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

# 添加中文字体支持
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

figure()


im = array(Image.open('empire.jpg'))
subplot(2,2,1)
imshow(im)
axis("off")
title(u'原图', FontProperties=font)

im2 = zeros(im.shape)
for i in range(3):
    im2[:,:,i] = filters.gaussian_filter(im[:,:,i],2)
im2 = np.uint8(im2)
subplot(2,2,2)
imshow(im2)
axis("off")
title(u'RGB_gaussian_sigma=2', FontProperties=font)

im2 = zeros(im.shape)
for i in range(3):
    im2[:,:,i] = filters.gaussian_filter(im[:,:,i],5)
im2 = np.uint8(im2)
subplot(2,2,3)
imshow(im2)
axis("off")
title(u'RGB_gaussian_sigma=5', FontProperties=font)

im2 = zeros(im.shape)
for i in range(3):
    im2[:,:,i] = filters.gaussian_filter(im[:,:,i],10)
im2 = np.uint8(im2)
subplot(2,2,4)
imshow(im2)
axis("off")
title(u'RGB_gaussian_sigma=10', FontProperties=font)

show()

在上面的代码中,并不总是需要将图像转换为uint8格式,这里只是将像素值用八位来表示。也可以用:

im = array(im2,'uint8')

 

 

 

1.2图像导数 

 

 

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

# 添加中文字体支持
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)


figure()
gray()

im = array(Image.open('empire.jpg').convert('L'))
subplot(1,4,1)
imshow(im)
axis("off")
title(u'原图', FontProperties=font)

#Sobel导数滤波器
imx = zeros(im.shape)
filters.sobel(im,1,imx)
subplot(1,4,2)
imshow(imx)
axis("off")
title(u'x导数图像', FontProperties=font)


imy = zeros(im.shape)
filters.sobel(im,0,imy)
subplot(1,4,3)
imshow(imy)
axis("off")
title(u'y导数图像', FontProperties=font)


magnitude  = sqrt(imx**2+imy**2)

subplot(1,4,4)
imshow(magnitude)
axis("off")
title(u'梯度大小图像', FontProperties=font)

show()

 上面的代码使用 Sobel 滤波器来计算 x 和 y 的方向导数,以及梯度大小。 sobel() 函数的第二个参数表示选择 x 或者 y 方向导数,第三个参数保存输出的变量。下图显示了用 Sobel 滤波器计算出的导数图像。在两个导数图像中,正导数显示为亮的像素,负导数显示为暗的像素。灰色区域表示导数的值接近于零。

 

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

 




figure()
gray()

#******************************************************************************

im = array(Image.open('empire.jpg').convert('L'))
subplot(3,4,1)
imshow(im)
axis("off")
title(u'原图', FontProperties=font)

sigma = 3 #标准差

imx = zeros(im.shape)
filters.gaussian_filter(im,(sigma,sigma),(0,1),imx)
subplot(3,4,2)
imshow(imx)
axis("off")
title(u'x导数sigma3', FontProperties=font)

imy = zeros(im.shape)
filters.gaussian_filter(im,(sigma,sigma),(1,0),imy)
subplot(3,4,3)
imshow(imy)
axis("off")
title(u'y导数sigma3', FontProperties=font)

magnitude  = sqrt(imx**2+imy**2)
subplot(3,4,4)
imshow(magnitude)
axis("off")
title(u'梯度大小sigma3', FontProperties=font)







#******************************************************************************
im = array(Image.open('empire.jpg').convert('L'))
subplot(3,4,5)
imshow(im)
axis("off")
title(u'原图', FontProperties=font)


sigma = 5 #标准差

imx = zeros(im.shape)
filters.gaussian_filter(im,(sigma,sigma),(0,1),imx)
subplot(3,4,6)
imshow(imx)
axis("off")
title(u'x导数sigma5', FontProperties=font)

imy = zeros(im.shape)
filters.gaussian_filter(im,(sigma,sigma),(1,0),imy)
subplot(3,4,7)
imshow(imy)
axis("off")
title(u'y导数sigma5', FontProperties=font)

magnitude  = sqrt(imx**2+imy**2)
subplot(3,4,8)
imshow(magnitude)
axis("off")
title(u'梯度大小sigma5', FontProperties=font)



#******************************************************************************
im = array(Image.open('empire.jpg').convert('L'))
subplot(3,4,9)
imshow(im)
axis("off")
title(u'原图', FontProperties=font)

sigma = 10 #标准差

imx = zeros(im.shape)
filters.gaussian_filter(im,(sigma,sigma),(0,1),imx)
subplot(3,4,10)
imshow(imx)
axis("off")
title(u'x导数sigma10', FontProperties=font)

imy = zeros(im.shape)
filters.gaussian_filter(im,(sigma,sigma),(1,0),imy)
subplot(3,4,11)
imshow(imy)
axis("off")
title(u'y导数sigma10', FontProperties=font)

magnitude  = sqrt(imx**2+imy**2)
subplot(3,4,12)
imshow(magnitude)
axis("off")
title(u'梯度大小sigma10', FontProperties=font)


show()

该函数的第三个参数指定对每个方向计算哪种类型的导数,第二个参数为使用的标准差。你可以查看相应文档了解详情。

 

1.3形态学:对象计数 

       形态学(或数学形态学)是度量和分析基本形状的图像处理方法的基本框架与集合。形态学通常用于处理二值图像,但是也能够用于灰度图像。二值图像是指图像的每个像素只能取两个值,通常是 0 和 1。二值图像通常是,在计算物体的数目,或者度量其大小时,对一幅图像进行阈值化后的结果。你可以从 http://en.wikipedia.org/wiki/Mathematical_morphology 大体了解形态学及其处理图像的方式。
       scipy.ndimage 中 的 morphology 模 块 可 以 实 现 形 态 学 操 作。 你 可 以 使 用 scipy.ndimage 中的 measurements 模块来实现二值图像的计数和度量功能。下面通过一个简单的例子介绍如何使用它们。
       考虑在下图 里的二值图像,计算该图像中的对象个数可以通过下面的脚本实现:
               from scipy.ndimage import measurements,morphology
               # 载入图像,然后使用阈值化操作,以保证处理的图像为二值图像
               im = array(Image.open('houses.png').convert('L'))
               im = 1*(im<128)
               labels, nbr_objects = measurements.label(im)
               print "Number of objects:", nbr_objects
      上面的脚本首先载入该图像,通过阈值化方式来确保该图像是二值图像。通过和 1相乘,脚本将布尔数组转换成二进制表示。然后,我们使用 label() 函数寻找单个的物体,并且按照它们属于哪个对象将整数标签给像素赋值。图 1-12b 是 labels 数组的图像。图像的灰度值表示对象的标签。可以看到,在一些对象之间有一些小的连接。进行二进制开(binary open)操作,我们可以将其移除:
                # 形态学开操作更好地分离各个对象
                im_open = morphology.binary_opening(im,ones((9,5)),iterations=2)
                labels_open, nbr_objects_open = measurements.label(im_open)
                 print "Number of objects:", nbr_objects_open
       binary_opening() 函数的第二个参数指定一个数组结构元素。该数组表示以一个像素为中心时,使用哪些相邻像素。在这种情况下,我们在 y 方向上使用 9 个像素(上面 4 个像素、像素本身、下面 4 个像素),在 x 方向上使用 5 个像素。你可以指定任意数组为结构元素,数组中的非零元素决定使用哪些相邻像素。参数iterations 决定执行该操作的次数。你可以尝试使用不同的迭代次数 iterations 值,看一下对象的数目如何变化。

from scipy.ndimage import measurements,morphology
from pylab import *
from PIL import Image

# 添加中文字体支持
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)


figure()
gray()
#载入图像,然后使用阈值化操作,以保证处理的图像为二值图像
im = array(Image.open("airplane.png").convert("L"))
subplot(2,2,1)
imshow(im)
axis("off")
title(u"原图",FontProperties=font)
im = 1*(im<128)

labels,nbr_objects = measurements.label(im)
print(u"Number of objects:",nbr_objects)
subplot(2,2,2)
imshow(labels)
axis("off")
title(u"标记后的图",FontProperties=font)

#形态学开操作更好地分离各个对象
im_open = morphology.binary_opening(im,ones((9,5)),iterations=2)
subplot(2,2,3)
imshow(im_open)
axis("off")
title(u"开运算后的图",FontProperties=font)

labels_open,nbr_objects_open = measurements.label(im_open)
print("Number of objects:",nbr_objects_open)
subplot(2,2,4)
imshow(labels_open)
axis("off")
title(u"开运算后标记的图",FontProperties=font)

show()

1.4一些有用的Scipy模块

SciPy 中包含一些用于输入和输出的实用模块。下面介绍其中两个模块: io 和 misc 。

 

1.4.1读写.mat文件

如果你有一些数据,或者在网上下载到一些有趣的数据集,这些数据以 Matlab的 .mat 文件格式存储,那么可以使用 scipy.io 模块进行读取。
                                 data = scipy.io.loadmat('test.mat')
上面代码中, data 对象包含一个字典,字典中的键对应于保存在原始 .mat 文件中的变量名。由于这些变量是数组格式的,因此可以很方便地保存到 .mat 文件中。你仅需创建一个字典(其中要包含你想要保存的所有变量),然后使用 savemat() 函数:
                                data = {}
                                data['x'] = x
                                scipy.io.savemat('test.mat',data)
因为上面的脚本保存的是数组 x,所以当读入到 Matlab 中时,变量的名字仍为 x。关于 scipy.io 模块的更多内容,请参见在线文档 http://docs.scipy.org/doc/scipy/reference/io.html。

 


1.4.2.以图像形式保存数组


       因为我们需要对图像进行操作,并且需要使用数组对象来做运算,所以将数组直接保存为图像文件非常有用。本书中的很多图像都是这样的创建的。imsave() 函数可以从 scipy.misc 模块中载入。要将数组 im 保存到文件中,可以使用下面的命令:
                             from scipy.misc import imsave
                              imsave('test.jpg',im)
scipy.misc 模块同样包含了著名的 Lena 测试图像:
                             lena = scipy.misc.lena()
该脚本返回一个 512×512 的灰度图像数组。

 

参考博客:https://blog.csdn.net/u013327188/article/details/105527954/

代码运行涉及到的图片:

             empire.jpg

 

                          airplane.png

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值