2.1. 項目簡介
人臉識別是基於人的臉部特徵信息進行身份識別的一種圖像識別技術。使用0PenCV 進行人臉識別的過程如下。
(1) 針對每個識別對象收集大量的人臉圖傣作爲樣本。
(2) 將樣本送給識別器進行學習,在訓練完成之後得到一個人臉數據模型。
(3) 利用這個模型對新的人臉圖像進行身份識別,預測人臉的所有者。
簡單地說就是收集訓練數據、訓練識別器、識別目標對象3個步驟,其工作過程如原書圖33_1所示。
使用OpenCV提供的人臉檢測分類器,能夠做到檢測圖像中的人臉並定位目標區域。如果想識別圖像中的人臉是誰的,還需要訓練專門的人臉識別器。這也不難,功能強大的0penCV提供簡單易用的人臉識別接口,編程者不需要深人瞭解人臉識別理論知識,就可以輕鬆編寫出人臉識別程序。
本節將介紹對“鋼鐵俠”和“蜘蛛俠“進行人臉識別。
2.2. 準備工作
- 安裝依賴模塊 opencv-contrib
opencv-contrib是OpenCV的擴展模塊,在進行人臉識別時要用到 OpenCv 的識別器,有他提供。在python中,需要安裝opencv-contrib-python庫。
在julia中,用Conda安裝opencv-contrib時會提示該包不存在,其實在julia中用Conda安裝OpenCV庫時,已經包含了這個擴展包。
2.準備項目目錄和數據
在本地磁盤上建立一個名爲“face-recogniz”的文件夾作爲項目目錄,用於存放本項目的數據、源程序、圖像等文件,然後從原書“資源包/第 33 課”文件夾中把兩個文件夾(testing和training) 以及一個人臉特徵文件 (lbpcascade_frontalface_improved.xml) 複製到 “face-recogniz”文件夾中。
training 文件夾中提供了用於訓練識別器使用的圖像文件,testing文件夾中提供了進行人臉識別測試時使用的圖像文件。
2.3. 收集訓練數據
在這個項目中,巳經準備好了用於訓練人臉識別器的人臉圖像文件。也可以通過互聯網搜索一些自己感興趣的人臉圖像作爲訓練數據,然後將其存放在 testing 文件夾中的一個子文件夾內即可。每一個人的人臉圖像文件放在一個單獨的文件夾中。
此外,在使用攝像頭的人臉識別項目中,可 以通過攝像頭採集人臉圖作爲訓練數據。
2.4. 訓練識別器
在收集人臉圖像的工作完成後,就可以開始編寫程序訓練人臉識別器。如原書圖 33-2 所示,這是使用0PEnCV 的 FaceRecognizer 進行人臉識別器的訓練並生成數據模型的過程。
- 編程實現:
新建一個空白源文件,以face_training.jl作爲文件名保存到“face-recogniz”項目文件夾中 ,然後編寫程序進行人臉識別器的訓練,具體過程如下。
(1) 導人cv2、numpy和os模塊。
using PyCall cv2=pyimport("cv2") numpy=pyimport("numpy") os=pyimport("os")
說明:在這個程序中需要使用python的os模塊讀取磁盤目錄和文件列表。事實上julia中內置函數readdir()讀取磁盤目錄和文件也極爲方便,這裏只是偷懶,直接採用原來python的代碼。
(2) 創建訓練識別器時使用的標籤(整數 id 值)列表和人臉圖像列表,及創建人臉檢測器和人臉識別器的實。
#創建人臉檢測器和識別器 labels, faces = [], [] file = "lbpcascade_frontalface_improved.xml" face_cascade = cv2.CascadeClassifier(file) recognizer = cv2.face.LBPHFaceRecognizer_create()
(3) 編寫detect_face()函數, 用於從圖像中檢測人臉並返回人臉區域。
function detect_face(image) #'''檢測人臉區域''' gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.2, 5, minSize=(20, 20)) if (length(faces) == 0) return nothing end (x, y, w, h) = faces[1,:] return gray[y:y+w, x:x+h] end
說明: 調用 detectMultiScale()方法能夠檢測並返回圖像的多個人臉區域,這裏只使用其中的一個作爲detect_face() 函數的返回值。原書python代碼是這樣的。
(x, y, w, h) = faces[0]
但是julia的數組是列主數組,如果用faces[1]只能返回數組的第一個元素,因此這裏改爲這樣:
(x, y, w, h) = faces[1,:]
(4) 編寫 read_face()函數於讀取訓練識別器使用的圖像文件,並將檢測出的人臉圖像數據和id加人到faces列表和labels列表中 。
1 function read_face(label, images_path) 2 #'''讀取人臉圖像''' 3 println("trainning:", label, images_path) 4 files = os.listdir(images_path) 5 for file in files 6 if startswith(file,'.') 7 continue 8 end 9 #從文件中讀取圖像 10 image = cv2.imread(images_path * "/" * file) 11 #檢測圖像中的人臉區域 12 face = detect_face(image) 13 14 if face !==nothing 15 ce = cv2.resize(face, (256, 256)) 16 #faces.append(face) 17 #labels.append(label) 18 push!(faces,face) 19 push!(labels,label) 20 end 21 end 22 end
說明: 在 faces 和 labels 這兩個列表中的元素一一對應 ,即人臉圖像和 id要匹配。
(5) 訓練人臉識別器,生成人臉特 徵模型數據文件。這裏使用蜘蛛俠和鋼鐵俠的圖像進行訓練。
#讀取人臉圖像 read_face(1, "training/spider_man/") read_face(2, "training/iron_man/") #訓練人臉識別器 recognizer.train(faces, numpy.array(labels)) #保存人臉特徵數據 recognizer.save("trainner.yml")
說明:人臉識別器的train()將讀取的人臉圖像生成特徵數據,第1個參數是圖像列表,第2個參數是標籤(整數的 id 值)數組,需要用 numpy.array()方法將列表(List)類型轉換爲 numpy 的數紐。 人臉識別器的save()方法將生成的人臉特徵模型數據保存到一個文件中。
至此訓練人臉識別器的程序編寫完畢。運行程序,將會讀取 training 文件夾中的人臉圖像,然後調用人臉識別器的 train()方法進行訓練,最終在項 目目錄下生成一個人臉特徵模型的數據文件trainner.yml。
2.5. 人臉檢測與識別
在訓練好識別器之後,使用生成的人臉特徵模型文件trainner.yml 就可以對testing目錄下的人臉圖像進行測試,看看是否能夠識別出圖像中的人臉是誰的。如原書圖33-3所示,這是使用訓練好的人臉識別器對圖像中的人臉進行身份識別的過程。
- 編程實現
新建一個空白源文件,以face_detection.jl作爲文件名保存到“face-recogniz”項目文件夾中 ,然後編寫程序對測試圖像進行人臉識別,具體過程如下。
(1) 導人CV2 庫。
cv2=pyimport("cv2")
(2) 創建一個元組,存放人臉所有者的名字。 其中,第一個元素不使用。
names = ("None", "Spider Man", "Iron Man")
(3) 創建人臉檢測器和識別。
file = "lbpcascade_frontalface_improved.xml" face_cascade = cv2.CascadeClassifier(file) recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("trainner.yml")
說明:通過人臉識別器的read()方法,讀取人臉特徵模型數據文件 trainner. yml。
(4) 從文件中讀取用於測試的人臉圖像
#讀取測試的人臉圖像 test_img = cv2.imread("testing/test1.jpg") gray_img = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray_img, 1.2, 5)
(5) 在循環結構中對檢測出的一組人臉圖像進行預測。取出人臉圖像改變大小。
#Julia數組是列主數組,而cv需要行主數組。 #反轉維度,然後使用PyReverseDims數組 rimg = permutedims(test_img, ndims(test_img):-1:1) pyimg = PyReverseDims(rimg) #對檢測出的每一個人臉圖像進行測試 for i in 1:size(faces,1) (x,y,w,h)=faces[i,:] face = gray_img[y:y+w, x:x+h] face = cv2.resize(face, (256, 256)) …… end
(6) 使用前面訓練的人臉識別器預測圖像中的人臉所有者。
#使用人臉識別器預測圖像 label, confidence = recognizer.predict(face) confidence = 100 - confidence ……
說明:LBPHFaceRecognizer 預測產生0~100 的評分,低於50是可靠的,高於80是不可靠的。這裏把評分轉換一下,以符合正常的閱讀習慣。
(7) 當信任度大於50時,標註出圖像中的人臉所有者
#取最大值 if label > 0 && confidence > 50 cv2.rectangle(pyimg, (x, y), (x+w, y+h), (255, 0, 0), 2) text =@sprintf("%s:%d", names[label], confidence) print(text) font = cv2.FONT_HERSHEY_PLAIN cv2.putText(pyimg, text, (x, y), font, 2.5, (0, 255, 0), 2) end
(8) 所有人臉處理完畢,顯示到窗口。
#顯示圖像並等待 cv2.namedWindow("Image", cv2.WINDOW_NORMAL) cv2.imshow("Image", pyimg) cv2.waitKey(0) cv2.destroyAllWindows()
至此,人臉識別程序編寫完畢。運行程序,對同時含有蜘蛛俠和鋼鐵俠的圖像進行預測。從結果來看,能夠正確識別出蜘蛛俠和鋼鐵俠,如下圖所示:
源碼下載:https://files.cnblogs.com/files/zjzkiss/face-recogniz.zip