使用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()


0 條回復   |  直到 2019-3-17 | 439 次瀏覽




熱門評論


登入後才可發表內容