使用numpy做影像處理(二)
顏色變換(Colour Transformations)
一個RGB圖像,其中每個點由RGB三通道的值組合為最終顏色,如果將RGB三個通道的值分別對應到XYZ軸上,一個RGB顏色就表示為一個三維空間中的一個點,而對三維空間中的點我們可以做空間變換(即乘一個三維矩陣),通過空間變換,一個顏色就變為另一個顏色(這之間需要做一些歸一化和反歸一的變換)。讓我們嘗試下對一張圖上的所有點(顏色)都做相同的變換,看看會有什麼效果。
def do_normalise(im): return -np.log(1/((1 + im)/257) - 1) def undo_normalise(im): return (1 + 1/(np.exp(-im) + 1) * 257).astype("uint8") def rotation_matrix(theta): """ 3D rotation matrix around the X-axis by angle theta """ return np.c_[ [1,0,0], [0,np.cos(theta),-np.sin(theta)], [0,np.sin(theta),np.cos(theta)] ] im_normed = do_normalise(im) im_rotated = np.einsum("ijk,lk->ijl", im_normed, rotation_matrix(np.pi)) im2 = undo_normalise(im_rotated) plti(im2)
# assert( np.log(np.e) == 1.0) # np.log 即 ln() - 以e為底的對數函數 def do_normalise(im): return -np.log(1/((1 + im)/257) - 1) # 預處理函數 # im中的像素值為 [0, 255] 閉區間, 則 (1+im) 為 [1, 256] # 先做 (1+im)/257 操作將值歸一化到 (0, 1) 開區間內 # 再使用 sigmoid函數 的反函數,效果見sigmod函數圖像 # -np.log(1/((1 + 0)/257) - 1) = -5.5451774444795623 # -np.log(1/((1 + 255)/257) - 1) = 5.5451774444795623 def undo_normalise(im): return (1/(np.exp(-im) + 1) * 257 - 1).astype("uint8") # 預處理函數的反函數 # 即先使用sigmod函數,再將值變換到(0, 257)區間再減1,通過astype保證值位於[0, 255] # 關於 astype("uint8") : # np.array([-1]).astype("uint8") = array([255], dtype=uint8) # np.array([256]).astype("uint8") = array([0], dtype=uint8) def rotation_matrix(theta): """ 3D 旋轉矩陣,圍繞X軸旋轉theta角 """ return np.c_[ [1,0,0], [0,np.cos(theta),-np.sin(theta)], [0,np.sin(theta),np.cos(theta)] ] # np.c_[ ] 將列表中的元素在第二維上拼接起來 # np.c_[[1,2],[3,4],[5,6]] = # array([[1, 3, 5], # [2, 4, 6]]) im_normed = do_normalise(im) im_rotated = np.einsum("ijk,lk->ijl", im_normed, rotation_matrix(np.pi)) # 利用愛因斯坦求和約定做矩陣乘法,實際上是將每個RGB像素點表示的三維空間點繞X軸(即紅色通道軸)旋轉180°。 im2 = undo_normalise(im_rotated) plti(im2)
如果我們不斷旋轉像素的顏色,那就可以做出動態的效果。 我們可以使用matplotlib的FuncAnimation工具為這個轉換設置動畫。
工具的安裝
http://www.imagemagick.org/script/download.php
為了將圖片保存為GIF(matplotlib必須要外部支持才能將動圖保存為gif),我們需要下載imagemagick工具(下載的是ImageMagick-7.0.8-34-Q16-x64-static .exe版本)並安裝。
為了順利使用,還要做點配置。先找到matplotlib配置文件路徑:
import matplotlib print(matplotlib.matplotlib_fname()) # 我的輸出 C:\Anaconda3\lib\site-packages\matplotlib\mpl-data\matplotlibrc #C:\ProgramData\Anaconda3 (一般安裝的路徑)
得到文件路徑後編輯該文件,在末尾添加一行(冒號後面為您的magick.exe工具的安裝路徑)
animation.convert_path: C:\Program Files\ImageMagick-7.0.8-Q16\magick.exe
from matplotlib.animation import FuncAnimation fig, ax = plt.subplots(figsize=(5,8)) def update(i): im_normed = do_normalise(im) im_rotated = np.einsum("ijk,lk->ijl", im_normed, rotation_matrix(i * np.pi/10)) im2 = undo_normalise(im_rotated) ax.imshow(im2) ax.set_title("Angle: {}*pi/10".format(i), fontsize=20) ax.set_axis_off() anim = FuncAnimation(fig, update, frames=np.arange(0, 20), interval=50) anim.save('colour_rotation.gif', dpi=80, writer='imagemagick') plt.close() # <img src="colour_rotation.gif">
from matplotlib.animation import FuncAnimation fig, ax = plt.subplots(figsize=(5,8)) def update(i): im_normed = do_normalise(im) im_rotated = np.einsum("ijk,lk->ijl", im_normed, rotation_matrix(i * np.pi/10)) im2 = undo_normalise(im_rotated) # 在更新函數里根據i來改變旋轉的角度 ax.imshow(im2) ax.set_title("Angle: {}*pi/10".format(i), fontsize=20) ax.set_axis_off() # 將旋轉後的圖繪出 # 以上其餘註釋見前文 anim = FuncAnimation(fig, update, frames=np.arange(0, 20), interval=50) # fig是圖像句柄 # update是更新函數 # frames為幀數列表,將值依次提供給更新函數 # interval表示每幀間隔ms數 anim.save('colour_rotation.gif', dpi=80, writer='imagemagick') plt.close()
熱門評論