iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 2
0
自我挑戰組

資工的日常(碩)系列 第 2

計算機視覺 - Photometric stereo(二)

今天是code的部分。先講資料的樣子,之後再補github檔案

資料長相:
光源向量:
[[ 38. 235. 2360.]
[ 98. 65. 2480.]
[ 202. 225. 2240.]
[ 252. 115. 2310.]
[ 8. 45. 2270.]
[ 22. 295. 2230.]]
(6, 3)
?_i 光源單位向量:
[[0.0160204 0.09907353 0.99495115]
[0.03947178 0.02618026 0.99887766]
[0.08936803 0.0995436 0.99101182]
[0.10831495 0.04942944 0.992887 ]
[0.00352351 0.01981977 0.99979736]
[0.0097798 0.1311382 0.99131586]]
(6, 3)

Code以及解釋:
前置作業,計算光源

Import 套件
import numpy as np
import cv2

讀圖,bunny或teapot
# 讀取圖檔 teapot or bunny
path = "./bunny/"

IMG1 = cv2.imread(path + 'pic1.bmp')
IMG2 = cv2.imread(path + 'pic2.bmp')
IMG3 = cv2.imread(path + 'pic3.bmp')
IMG4 = cv2.imread(path + 'pic4.bmp')
IMG5 = cv2.imread(path + 'pic5.bmp')
IMG6 = cv2.imread(path + 'pic6.bmp')

讀光源位置,計算單位光源向量
# 光源位置
S_lst = []
with open(path + '新增文字文件.txt', 'r', encoding='utf8') as shadow_file:
    for x in shadow_file.readlines():
        temp = x[7:-2].split(',')
        temp = [float(i) for i in temp]
        S_lst.append(temp)
S_lst = np.array(S_lst)
print("光源向量:\n",S_lst)
print(S_lst.shape)

# 光源單位向量
lst_light = []
for i in S_lst:
    lst_light.append(i/np.linalg.norm(i))
S_lst = np.array(lst_light)
print("?_i 光源單位向量:\n", S_lst)
print(S_lst.shape)

計算Albedo和法向量Normal(Orientation)


# 120*120 OR 114*196
albedo_lst = np.zeros(IMG1.shape)
N_lst = np.zeros(IMG1.shape)

for x in range(IMG1.shape[0]) :
    for y in range(IMG1.shape[1]) :
        I = np.array([
            IMG1[x][y],
            IMG2[x][y],
            IMG3[x][y],
            IMG4[x][y],
            IMG5[x][y],
            IMG6[x][y]
        ])
        # kn->N shadow_inverse*[In]
        N = np.dot(np.dot(np.linalg.inv(np.dot(S_lst.T, S_lst)), S_lst.T), I)        
        G = N.T # 因為先多轉一次去計算,後面要再轉回來
        
        # 算Normal n = N/|N|
        G_gray = G[0]*0.0722+G[1]*0.7152+G[2]*0.2126
        Gnorm = np.linalg.norm(G_gray)
        # Normal是0,Aldedo就是0
        if Gnorm==0:
            continue
        N_lst[x][y] = G_gray/Gnorm
        
        # 算Albedo |N|
        rho = np.linalg.norm(G, axis=1)
        albedo_lst[x][y] = rho
# 控制在0到255間               
N_lst = ((N_lst*0.5 + 0.5)*255).astype(np.uint8)
albedo_lst = (albedo_lst/np.max(albedo_lst)*255).astype(np.uint8)



# 顯示圖片
cv2.imshow('Albedo', albedo_lst)

# 顯示圖片
cv2.imshow('Normal', N_lst)

# 按下任意鍵則關閉所有視窗
cv2.waitKey(0)
cv2.destroyAllWindows()

# 寫入不同圖檔格式
cv2.imwrite(path + 'Albedo.png', albedo_lst)
cv2.imwrite(path + 'Normal.png', N_lst)


上一篇
計算機視覺 - Photometric stereo(一)
系列文
資工的日常(碩)2

尚未有邦友留言

立即登入留言