NumPy 高級(jí)索引和數(shù)組概念
調(diào)整圖像尺寸
# 這個(gè)代碼用于調(diào)整圖像尺寸
# 來源:NumPy Cookbook 2e Ch2.3
import scipy.misc
import matplotlib.pyplot as plt
import numpy as np
# 將 Lena 圖像加載到數(shù)組中
lena = scipy.misc.lena()
# 圖像寬高
LENA_X = 512
LENA_Y = 512
# 檢查圖像的寬高
np.testing.assert_equal((LENA_Y, LENA_X), lena.shape)
# 設(shè)置調(diào)整系數(shù)舟陆,水平 3桥胞,豎直 2
yfactor = 2
xfactor = 3
# 調(diào)整圖像尺寸,水平(沿軸 1)拉伸 3 倍,豎直(沿軸 0 )拉伸兩倍
resized = lena.repeat(yfactor, axis=0)
.repeat(xfactor, axis=1)
# 檢查調(diào)整后數(shù)組
np.testing.assert_equal((yfactor * LENA_Y, xfactor * LENA_Y), resized.shape)
# 繪制原圖像(兩行一列的第一個(gè)位置)
plt.subplot(211)
plt.title("Lena")
plt.axis("off")
plt.imshow(lena)
# 繪制調(diào)整后圖像(兩行一列的第二個(gè)位置)
plt.subplot(212)
plt.title("Resized")
plt.axis("off")
plt.imshow(resized)
plt.show()
創(chuàng)建視圖及副本
# 來源:NumPy Cookbook 2e Ch2.4
import scipy.misc
import matplotlib.pyplot as plt
# 加載 Lena 圖像
lena = scipy.misc.lena()
# copy 創(chuàng)建副本昙沦,Python 對(duì)象復(fù)制,內(nèi)部?jī)?nèi)存復(fù)制
acopy = lena.copy()
# view 創(chuàng)建視圖,Python 對(duì)象復(fù)制,內(nèi)部?jī)?nèi)存共享
aview = lena.view()
# 繪制 Lena 圖像(左上角)
plt.subplot(221)
plt.imshow(lena)
# 繪制副本(右上角)
plt.subplot(222)
plt.imshow(acopy)
# 繪制視圖(左下角)
plt.subplot(223)
plt.imshow(aview)
# 將副本所有元素清零
# 由于數(shù)組的數(shù)據(jù)保存在內(nèi)部?jī)?nèi)存中
# 副本不受影響常空,視圖(以及引用)會(huì)跟著變化
aview.flat = 0
# 繪制修改后的視圖(右下角)
plt.subplot(224)
plt.imshow(aview)
翻轉(zhuǎn)圖像
# 來源:NumPy Cookbook 2e Ch2.5
import scipy.misc
import matplotlib.pyplot as plt
# 加載 Lena 圖像
lena = scipy.misc.lena()
# 繪制 Lena 圖像(左上角)
plt.subplot(221)
plt.title('Original')
plt.axis('off')
plt.imshow(lena)
# 繪制翻轉(zhuǎn)后的圖像(右上角)
# Python 的 [::-1] 用于翻轉(zhuǎn)序列
# 這里翻轉(zhuǎn)了第二個(gè)維度,也就是水平翻轉(zhuǎn)
plt.subplot(222)
plt.title('Flipped')
plt.axis('off')
plt.imshow(lena[:,::-1])
# 繪制切片后的圖像(左下角)
# 取圖像的左半部分和上半部分
plt.subplot(223)
plt.title('Sliced')
plt.axis('off') plt.imshow(lena[:lena.shape[0]/2,:lena.shape[1]/2])
# 添加掩碼盖溺,將偶數(shù)元素變?yōu)?0
# 布爾數(shù)組可用作索引
mask = lena % 2 == 0
masked_lena = lena.copy()
masked_lena[mask] = 0
# 繪制添加掩碼后的圖像(右下角)
plt.subplot(224)
plt.title('Masked')
plt.axis('off')
plt.imshow(masked_lena)
plt.show()
花式索引
# 這個(gè)代碼通過將數(shù)組對(duì)角線上的元素設(shè)為 0 漓糙,來展示花式索引
# 花式索引就是使用數(shù)組作為索引來索引另一個(gè)數(shù)組
# 來源:NumPy Cookbook 2e Ch2.6
import scipy.misc
import matplotlib.pyplot as plt
# 加載 Lena 圖像
# Load the Lena array
lena = scipy.misc.lena()
# 取圖片的寬和高
height = lena.shape[0]
width = lena.shape[1]
# 使用花式索引將對(duì)角線上的元素設(shè)為 0
# x 為 0 ~ width - 1 的數(shù)組
# y 為 0 ~ height - 1 的數(shù)組
lena[range(height), range(width)] = 0
# 將副對(duì)角線上元素也設(shè)為 0
# x 為 width - 1 ~ 0 的數(shù)組
# y 為 0 ~ height - 1 的數(shù)組
lena[range(height), range(width - 1, -1, -1)] = 0
# 畫出帶對(duì)角線的 Lena 圖像
plt.imshow(lena)
plt.show()
將位置列表用于索引
# 這個(gè)代碼的目的就是把 Lena 圖像弄花
# 來源:NumPy Cookbook 2e Ch2.7
import scipy.misc
import matplotlib.pyplot as plt
import numpy as np
# 加載 Lena 圖像
lena = scipy.misc.lena()
# 取圖像寬高
height = lena.shape[0]
width = lena.shape[1]
def shuffle_indices(size):
'''
生成 0 ~ size - 1 的數(shù)組并打亂
'''
arr = np.arange(size)
np.random.shuffle(arr)
return arr
# 生成 x 隨機(jī)索引和 y 隨機(jī)索引
xindices = shuffle_indices(width)
np.testing.assert_equal(len(xindices), width)
yindices = shuffle_indices(height) np.testing.assert_equal(len(yindices), height)
# 畫出打亂后的圖像
# ix_ 函數(shù)將 yindices 轉(zhuǎn)置,xindices 不變
# 結(jié)果是一個(gè) height x 1 的數(shù)組和一個(gè) 1 x width 的數(shù)組
# 用于索引時(shí)烘嘱,都會(huì)擴(kuò)展為 height x width 的數(shù)組
plt.imshow(lena[np.ix_(yindices, xindices)])
plt.show()
布爾索引
# 來源:NumPy Cookbook 2e Ch2.8
import scipy.misc
import matplotlib.pyplot as plt
import numpy as np
# 加載 Lena 圖像
lena = scipy.misc.lena()
# 取大小為 size 的數(shù)組
# 4 的倍數(shù)的下標(biāo)為 True昆禽,其余為 False
def get_indices(size):
arr = np.arange(size)
return arr % 4 == 0
# 繪制 Lena
# 對(duì)角線上每四個(gè)元素將一個(gè)元素清零
lena1 = lena.copy()
yindices = get_indices(lena.shape[0])
xindices = get_indices(lena.shape[1])
lena1[yindices, xindices] = 0
plt.subplot(211)
plt.imshow(lena1)
lena2 = lena.copy()
# 最大值 1/4 ~ 3/4 之間的元素清零
# 這里用到了數(shù)組廣播
lena2[(lena > lena.max()/4) & (lena < 3 * lena.max()/4)] = 0
plt.subplot(212)
plt.imshow(lena2)
plt.show()
分離數(shù)獨(dú)的九宮格
# 來源:NumPy Cookbook 2e Ch2.9
import numpy as np
# 數(shù)獨(dú)是個(gè) 9x9 的二維數(shù)組
# 包含 9 個(gè) 3x3 的九宮格
sudoku = np.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],
[8, 7, 9, 6, 5, 1, 2, 3, 4],
[4, 2, 1, 3, 9, 8, 6, 7, 5],
[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]
])
# 要將其變成 3x3x3x3 的四維數(shù)組
# 但不能直接 reshape,因?yàn)檫@樣會(huì)把一行變成一個(gè)九宮格
shape = (3, 3, 3, 3)
# 大行之間隔 27 個(gè)元素蝇庭,大列之間隔 3 個(gè)元素
# 小行之間隔 9 個(gè)元素为狸,小列之間隔 1 個(gè)元素
strides = sudoku.itemsize * np.array([27, 3, 9, 1])
squares = np.lib.stride_tricks.as_strided(sudoku, shape=shape, strides=strides)
print(squares)
'''
[[[[2 8 7] [9 5 4] [6 1 3]]
[[1 6 5] [7 3 2] [8 4 9]]
[[9 4 3] [1 6 8] [7 5 2]]]
[[[8 7 9] [4 2 1] [3 6 5]]
[[6 5 1] [3 9 8] [4 2 7]]
[[2 3 4] [6 7 5] [8 9 1]]]
[[[1 9 8] [5 4 2] [7 3 6]]
[[5 7 3] [9 1 6] [2 8 4]]
[[4 2 6] [3 8 7] [5 1 9]]]]
'''
數(shù)組廣播
# 來源:NumPy Cookbook 2e Ch2.10
import scipy.io.wavfile
import matplotlib.pyplot as plt
import urllib2
import numpy as np
# 下載音頻文件
response = urllib2.urlopen('http://www.thesoundarchive.com/austinpowers/smashingbaby.wav')
print(response.info())
# 將文件寫到磁盤
WAV_FILE = 'smashingbaby.wav'
filehandle = open(WAV_FILE, 'w')
filehandle.write(response.read())
filehandle.close()
# 使用 SciPy 讀取音頻文件
sample_rate, data = scipy.io.wavfile.read(WAV_FILE)
print("Data type", data.dtype, "Shape", data.shape)
# ('Data type', dtype('uint8'), 'Shape', (43584L,))
# 繪制原始音頻文件(上方)
# y 值是數(shù)據(jù),x 值是數(shù)據(jù)的下標(biāo)
plt.subplot(2, 1, 1)
plt.title("Original")
plt.plot(data)
# 使音頻更安靜
# 數(shù)組廣播的意思是遗契,兩個(gè)數(shù)組進(jìn)行運(yùn)算時(shí)
# 較小尺寸的數(shù)組會(huì)擴(kuò)展自身辐棒,與較大數(shù)組對(duì)齊
# 如果數(shù)組與標(biāo)量運(yùn)算,那么將標(biāo)量與數(shù)組的每個(gè)元素運(yùn)算
# 所以這里數(shù)組的每個(gè)元素都 x 0.2
# 具體規(guī)則請(qǐng)見官方文檔
newdata = data * 0.2
newdata = newdata.astype(np.uint8)
print("Data type", newdata.dtype, "Shape", newdata.shape)
# ('Data type', dtype('uint8'), 'Shape', (43584L,))
# 保存更安靜的音頻
scipy.io.wavfile.write("quiet.wav", sample_rate, newdata)
# 繪制更安靜的音頻文件(下方)
plt.subplot(2, 1, 2)
plt.title("Quiet")
plt.plot(newdata)
plt.show()