1.CK+動態表情庫介紹
The Extended Cohn-Kanade Dataset(CK+)
這個數據庫是在 Cohn-Kanade Dataset 的基礎上擴展來的,發布於2010年。這個數據庫比起JAFFE 要大的多。而且也可以免費獲取,包含表情的label和Action Units 的label。
這個數據庫包括123個subjects, 593 個 image sequence,每個image sequence的最后一張 Frame 都有action units 的label,而在這593個image sequence中,有327個sequence 有 emotion的 label。這個數據庫是人臉表情識別中比較流行的一個數據庫,很多文章都會用到這個數據做測試。
In this Phase there are 4 zipped up files. They relate to:
下載數據庫后有以下四個文件
1) The Images (cohn-kanade-images.zip) - there are 593 sequences across 123 subjects which are FACS coded at the peak frame. All sequences are from the neutral face to the peak expression.
2) The Landmarks (Landmarks.zip) - All sequences are AAM tracked with 68points landmarks for each image.
3) The FACS coded files (FACS_labels.zip) - for each sequence (593) there is only 1 FACS file, which is the last frame (the peak frame). Each line of the file corresponds to a specific AU and then the intensity. An example is given below.
4) The Emotion coded files (Emotion_labels.zip) - ONLY 327 of the 593 sequences have emotion sequences. This is because these are the only ones the fit the prototypic definition. Like the FACS files, there is only 1 Emotion file for each sequence which is the last frame (the peak frame). There should be only one entry and the number will range from 0-7 (i.e. 0=neutral, 1=anger, 2=contempt, 3=disgust, 4=fear, 5=happy, 6=sadness, 7=surprise). N.B there is only 327 files- IF THERE IS NO FILE IT MEANS THAT THERE IS NO EMOTION LABEL (sorry to be explicit but this will avoid confusion).
The Images (cohn-kanade-images.zip)圖片庫中包含了從平靜到表情表現峰值的圖片,實際使用中建議使用比較明顯的圖片,並進行相應的預處理。
Emotion_labels.zip標簽壓縮包中
0-中性
1-憤怒
2-蔑視
3-厭惡
4-恐懼
5-高興
6-悲傷
7-驚訝
2.特征點分析
因為我們自己建立的表情庫是用RealSense攝像頭采集的,我們想驗證我們的識別方法在在CK+庫上的識別效果,所以需要做的是對CK庫進行特征點提取。
在提取之前我們先要分析CK庫中特征點的ID,這樣方便我們找到RealSense中對應的點。
選擇CK庫中的一張圖片,讀數據,將標記點在圖片中畫出來。
1 def drawLandmarkPoint(img,color): 2 draw = ImageDraw.Draw(img) 3 myfont = ImageFont.truetype("C:\\WINDOWS\\Fonts\\SIMYOU.TTF", 10) 4 5 file_txt = open("S035_003_00000001_landmarks.txt", "a+") 6 lines = file_txt.readlines() 7 t=1 #特征點標號 8 for line in lines: 9 line_object=line.split(" ") 10 x=float(line_object[3]) #原始數據是科學記數法,這里轉換成浮點型 11 y=float(line_object[-1]) 12 print x,y 13 #draw.ellipse((0, 0, 200, 200), fill="red", outline="red") 14 draw.text((x,y), bytes(t), font=myfont, fill=color) 15 t+=1 16 file_txt.close()
CK庫中的標記點共有68個。
3.特征點轉換CK_to_RealSense
可以看出特征點的順序和RealSense是不一樣的。相比RealSense的78個標記點,CK+中只有68個,且CK庫中有幾個點RealSense中沒有,所以,我們最后存下來的點在66個。
轉化之后主要缺失的點是眉毛下眉的2x3=6個點,左右眼睛2x2=4個點。
多出的2個點是鼻子2側,CK有5個,RealSense只有3個。所以最后保存了66個點。
在程序里面建立元祖,標注轉化的對應關系。
依次是,左眉,右眉,左眼,右眼,鼻子,外嘴唇,內嘴唇,臉輪廓
1 #將ck點轉換成realsense的點 r:ck 共66個點。 2 CK_to_RealSense={0:22,1:21,2:20,3:19,4:18, 3 5:23,6:24,7:25,8:26,9:27, 4 10:10,11:39,12:38,14:37,16:42,17:41, 5 18:43,19:44,20:45,22:46,24:47,25:48, 6 26:28,27:29,28:30,29:31,30:32,31:34,32:36, 7 33:49,34:50,35:51,36:52,37:53,38:54,39:55,40:56,41:57,42:58,43:59,44:60, 8 45:61,46:62,47:63,48:64,49:65,50:66,51:67,52:68, 9 53:1,54:2,55:3,56:4,57:5,58:6,59:7,60:8,61:9,62:10,63:11,64:12,65:13,66:14,67:15,68:16,69:17 10 } 11 RealSenseID=[0,1,2,3,4, 12 5,6,7,8,9, 13 10,11,12,14,16,17, 14 18,19,20,22,24,25, 15 26,27,28,29,30,31,32, 16 33,34,35,36,37,38,39,40,41,42,43,44, 17 45,46,47,48,49,50,51,52, 18 53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69 19 ]
4.進行處理
CK+庫中的動態表情是通過動態序列來展示的,所以一個表情會有多張圖片,需要的是將一個表情的多張圖片進行處理,提取特征點信息,然后存到一個txt中,表現出動態的變化。
所以open操作的模式要寫成
fCK_image = open(CKDataDir, "a"),可以多次寫入,這樣對同一個目錄下多個圖片的數據寫入一個文件。
1 def readFile(filepath): 2 f1 = open(filepath, "r") 3 nowDir = os.path.split(filepath)[0] #獲取路徑中的父文件夾路徑 4 fileName = os.path.split(filepath)[1] #獲取路徑中文件名 5 #對新生成的文件進行命名的過程 6 CKDataDir = os.path.join(nowDir, "CKData.txt") 7 8 fCK_image = open(CKDataDir, "a") 9 fCK_image.write(os.path.splitext(fileName)[0]+"\t") 10 11 lines = f1.readlines() 12 for n in range(0,66): 13 #for n in range(1, lines_count+1): 14 line = lines[CK_to_RealSense[RealSenseID[n]]-1] 15 line_object = line.split(' ') 16 17 id=RealSenseID[n] 18 if n==63: 19 time=4 20 image_x = float(line_object[3]) 21 image_y = float(line_object[-1]) 22 pointData = bytes(id) + "\t" + bytes(image_x) + "\t" + bytes(image_y) +"\t" 23 fCK_image.write(pointData) 24 print pointData 25 26 fCK_image.write("\n") 27 f1.close() 28 fCK_image.close() 29 30 global picturecount 31 picturecount+=1
5.遞歸批量處理數據
對CK庫中,標記點的文件夾進行遞歸操作。
需要注意的是,打開文件操作的時候,需要在路徑前面加上字符r。
eachFile(r"E:\RealSense\CK+\Landmarks_track")
因為在過程中存在這樣的路徑,里面有\0,程序會認為是這個字符串結束了,然后運行不下去。
E:\RealSense\CK+\Landmarks\S010\001\S010_001_00000001_landmarks.txt
1 def eachFile(filepath): 2 global emotioncount 3 4 pathDir = os.listdir(filepath) #獲取當前路徑下的文件名,返回List 5 for s in pathDir: 6 newDir=os.path.join(filepath,s) #將文件命加入到當前文件路徑后面 7 if os.path.isfile(newDir) : #如果是文件 8 if os.path.splitext(newDir)[1]==".txt": #判斷是否是txt 9 readFile(newDir) #讀文件 10 pass 11 else: 12 eachFile(newDir) #如果不是文件,遞歸這個文件夾的路徑 13 emotioncount += 1
最后的將處理的圖片數量和表情個數打印輸出。