第二章.高级索引和数组概念
NumPy以高效率的数组著称.这节我们将以图像处理为例展示高级的索引技巧.(摘自原文)
一.安装SciPy
SciPy是一个和NumPy密切相关的Python科学计算库.
$sudo apt-get install python-scipy
或者
$sudo easy_install scipy
二.安装PIL
PIL是Python的图像库.
$sudo apt-get install python-imaging
或者
$sudo easy_install PIL
三.调整图像大小
本节将把SciPy库中的一个实例图像Lena(一张人物图像,因为历史原因图像处理中经常会用到她的肖像)加载到数组中,本节不是讲讨论图像处理,我们只是将图像数据作为输入.我们将用repeat()函数调整该图像的大小.
具体步骤:
1.加载图像Lena到数组中
SciPy中有一个lena函数,可以用该函数把图像Lena加载到NumPy数组中.
lena=scipy.misc.lena()
SciPy的0.1之后的版本从勾重构了部分代码,现在的正确代码为:
lena=scipy.lena()
2.检查数组的形状
numpy.testing.assert_equal((LENA_X,LENA_Y),lena.shape)
LENA_X和LENA_Y是自己手动设置的图像的规格
3.调整数组Lena的大小
使用repeat()函数数组调整Lena的大小.需要分别在X,Y方向给出个调整系数.
resized=lena.repeat(yfactor,axis=0).repeeat(x.factor,axis=1)
xfactor和yfactor是自己手动设置的
4.绘制数组对应的图像
我么将把原始图像和调整后的图像,分别花画到一格网格内的两个子图中,第一个子图中绘制数组Lena.
matplotlib.pyplot.subplot(211)
matplotlib.pyplot.imshow(lena)
Matplotlib中的subplot函数来创建子图.这个函数以一个3位数的整数作为参数,最高位数字代表行数,第二个数字代表列数,做后一个数字代表子图的位置索引号(从1开始编号),imshow函数用来显示图像,show函数用来显示最终结果.
绘制调整后的图像
matplotlib.pyplot.subplot(212)
matplotlib.pyplot.imshow(resized)
matplotlib.pyplot.show()最终显示结果如下图:
四.创建视图和副本
上面例子里我们是在与一个共享的数组视图打交道,还是获得了数组数据的一格副本.下面我们将用著名的图像Lena创建一个数组,复制该数组,创建一个视图,最后再修改这个视图.
具体步骤:
1.创建数组Lena的一个副本和视图:
acopy=lena.copy()
aview=lena.view()
2.利用flat迭代器,把视图中所有的值清零
aview.flat=0
最终得到的是一副图像显示的是Lena的肖像,其他几副图像被完全删减掉了,如下图:
五.翻转图像
作为一个演示我们将对SciPy库中的图像Lena进行翻转操作,还会绘制一些遮罩效果.
具体步骤:
1.绘制翻转后的图像
使用如下代码,沿纵轴方向对数组Lena进行翻转操作:
matplotlib.pyplot.imshow(lena[:,::-1])
2.绘制图像的一部分
把图像的一部分切割出来并进行显示,如下代码实际上是把图像Lena左上角的四分之一选取并显示出来了:
matplotlib.pyplot.imshow(lena[:lena.shape[0]/2:lena,shape[1]/2])
3.对图像应用遮罩的效果
找到数组Lena中所有的偶数并把他们置零:
mask=lena%2==0
masked_lena=lena.copy()
masked_lena[mask]=0
生成的图像如下:
六.高级索引
本节将使用高级索引技术,把图像Lena对角线位置上的数值置零,其效果是在图像上会两条交叉的蓝对角线.
具体步骤:
1.把第一条对角线位置上的数值置零
lena[range(xmax),range(ymax)]=0
2.把另一条对角线上的数值置零
lena[range(xmax-1,-1,-1),range(ymax)]=0
最终的到图像如下:
七.位置列表索引
这节我们使用ix_()函数,把图像Lena打乱.ix_()函数能利用多个序列生成一个网状结构.
具体步骤:
1.把数组的索引随机排列
def shuflle_indices(size):
arr=numpy.arange(size)
numpy.random.shuffle(arr)
return arr
2. 用随机重排后的索引画出数组
matplotlib.pyplot.imshow(lena[numpy.ix_(xindices,yindices)])
生成图像如下:
八.布尔型索引
布尔型索引就是基于布尔数组的索引,属于高级索引技术的发范畴.
具体步骤:
1.在图像上添加点状对角线
def get_indices(size):
arr=numpy.arange(size)
return arr%4==0
2.把指定范围内的数值置零
把数组中大小介于最大值的四分之一和最大值的四分之三之间的数值置零
lena2[(lena>lena.max()/4)&(lena<3*lena.max()/4)]=0
最终得到两幅新的图像:
九.数独游戏中的跨度技巧
NumPy的ndarray类中有一个跨度属性域,实现为一个数组,在遍历数组时,用跨度来指明每一个维度上的步进值是多少个字节.我们将巧妙的运用跨度技巧,把数独划分为3X3的九宫格形式.
具体步骤:
1.定义数独谜题数组
sudoku=numpy.array([
[2,8,7,1,6,5,9,4,3],
[9,5,4,7,3,2,1,6,8],
[6,1,3,8,4,9,7,5,2],
[3,6,5,4,2,7,8,9,1],
[1,9,8,5,7,3,4,2,6],
[5,4,2,9,1,6,3,8,7],
[7,3,6,2,8,4,5,1,9]
])
2.计算跨度
strides=audoku.itemsize*numpy.array([27,3,9,1])
3.划分九宫格
squares=numpy.lib.stride_strickes.as_stridsd(suduoku,shape=shape,strides=strides)
这样就能把各个宫格分别打印出来
十.用广播机制扩散数组
你也许不了解广播机制这个术语,就已经把它应用到数组运算过程中了,简而言之,NumPy总是试图完成运算,即便运算对象的形状并不匹配.本节中,我们将把一个数组和一个标量相乘,标量会被"扩展"为和数组对象相同的形状,然后与之相乘.我们将加载一个声音文件,然后为他创建一个音量减小的新版本.
具体步骤:
1.读取一个WAV文件
SciPy有一个wavefile模块,用来加载声音数据或生成WVA文件,read()函数返回一个包含声音数据的数组和采样率.
sample_rate,data=scipy.wavfile.read(WAV_FILE)
2.画出原始WAV数据
matplotlib.pyplot.subplot(2,1,1)
matplotlib.pyplot.title('xpimage')
matplotlib.pyplot..plot(data)
3.创建一个新的数组
我们用NumPy创建一个音量减小的声音样本,其实就是把原始声音数据数组与一个常数相乘,生成一个数值减小的新数组,广播机制的魔力就体现在这里.
newdata=data*0.5
newdata=newdata.astype(numpy.uint8)
4.生成新的WAV文件.
scipy.io.wavfile.write("newxp.wav",sample_rate,newdata)
5.画出新的WAV数据.
matplotlib.pyplot.subplot(2,1,2)
matplotlib.pyplot.title("Quite")
matplotlib.pyplot.plot(newdata)
matplotlib.pyplot.show()
最终结果如下图:
本节到此结束,Good Luck!