Face Preception
開始點另一邊技能樹
人臉辨識 、或視覺辨識是一個有趣的議題與技術:主要是利用可程式化與數學化的方式, 做到人類感知的一種技術。就生物學上來看,人類的臉孔並沒有顯著的差異,一樣都擁有兩個眼睛、 一個鼻子與一個嘴巴,然而人類可以很容易的判斷兩張不同的面孔。另外延伸來看,一個人的細部細節 ,像是變胖變瘦依然可以容易的判斷是相同的兩個人。根據這些條件,人臉辨識會有以下困難的前提:
- 不同間的個體差異不大
- 同一個體會因為角度、光線等因素會有差異,更因時間 (年齡、體重) 有所改變
前者的問題稱之為[類間變化 (inter-class difference)][1]、後者則稱之為[類內變化 $(intra-class difference)][2]。根據順序,人臉辨識需要使用到若干種技術: 人臉檢測 、
圖片預處理
根據膚色判斷的人臉辨識,會因為資料庫資料、環境光線、拍攝角度、背景顏色等因素而容易誤判, 因此我們需要針對原始的圖片先做預處理。為了加速處理的速度,可以將原始圖片轉成 灰階圖片 。 舉例來說,如果要將 RGB 圖片 轉換成一個灰階圖片時會有一個轉換公式 G = aR + bG + cB 來轉換每一個 Pixel ,最簡單的方式是讓 RGB 的三個值取平均,就可以得到一個灰階圖片。 另一種則是先將 RGB 轉換成 YCbCr 圖片 並取其中的 Y 值來決定光線的亮暗程度:
from PIL import Image
from matplotlib import pyplot as plt
img = Image.open('sample.jpg')
gray = Image.new('LA', img.size)
pixel = gray.load()
# simple convert to grayscale by average the RGB pixel
for x in range(img.size[0]):
for y in range(img.size[1]):
pixel[x, y] = sum(img.getpixel((x, y)))/3, 255
plt.imshow(gray)
plt.show()
另一個有效的方式則是 銳化 :他可以凸顯出圖片中不連續的部分,包含顏色、亮度、深淺等。 主要是用來加深影像的邊界並凸顯出圖片的輪廓。一個簡單的 銳化濾鏡 可以用一個 Laplacian mask 來做處理。銳化濾鏡的方法簡單來說就是用一個演算法將改變凸顯出來, 他可以使用一階微分 (概念是取斜率) 來找到變化顯著的部分:
def LineMask(img, pos):
tmp = 0
for x in (-1, 1):
for y in range(-1, 2):
try:
tmp += x * (img[pos[0]+x, pos[1]+y]) * (2 if y == 0 else 1)
except IndexError as e:
pass
for x in range(-1, 2):
for y in (-1, 1):
try:
tmp += y * (img[pos[0]+x, pos[1]+y]) * (2 if x == 0 else 1)
except IndexError as e:
pass
return tmp
抗噪則是一個有效的過濾圖片的方式:一個原始圖片中可能包含了若干雜訊,如果沒有先過濾這些雜訊 ,在後續處理中可能會將這些雜訊凸顯出來而得到預期以外的結果。在銳化的過程中雜訊會被凸顯出來 ,導致使用銳化濾鏡會得到更多的雜訊。可以使用 中值濾波器 (Median Filter) 將雜訊過濾, 排除掉突兀的資料點:
def MedianFilter(img, pos, size=3):
tmp = []
for x in range(-1*size/2, size/2):
for y in range(-1*size/2, size/2):
try:
tmp += [img[pos[0]+x, pos[1]+y]]
except IndexError as e:
pass
tmp = sorted(tmp)
return tmp[len(tmp)/2]
人臉檢測
人臉檢測屬於一種特定情境的物體檢測 (object-class detection) 技術,可以在一張圖片中, 判斷並定位一個或多個人類面孔。