Nhận Diện Khuôn Mặt Với Python Và OpenCV

I. Introduction

Nhận dạng mặt người (Face recognition) là một lĩnh vực nghiên cứu của ngành Computer Vision, và cũng được xem là một lĩnh vực nghiên cứu của ngành Biometrics (tương tự như nhận dạng vân tay – Fingerprint recognition, hay nhận dạng mống mắt – Iris recognition). Xét về nguyên tắc chung, nhận dạng mặt có sự tương đồng rất lớn với nhận dạng vân tay và nhận dạng mống mắt, tuy nhiên sự khác biệt nằm ở bước trích chọn đặt trưng (feature extraction) của mỗi lĩnh vực.

Trong khi nhận dạng vân tay và mống mắt đã đạt tới độ chín, tức là có thể áp dụng trên thực tế một cách rộng rãi thì nhận dạng mặt người vẫn còn nhiều thách thức và vẫn là một lĩnh vực nghiên cứu thú vị với nhiều người. So với nhận dạng vân tay và mống mắt, nhận dạng mặt có nguồn dữ liệu phong phú hơn (bạn có thể nhìn thấy mặt người ở bất cứ tấm ảnh, video clip nào liên quan tới con người trên mạng) và ít đòi hỏi sự tương tác có kiểm soát hơn (để thực hiện nhận dạng vân tay hay mống mắt, dữ liệu input lấy từ con người đòi hỏi có sự hợp tác trong môi trường có kiểm soát).

Hiện nay các phương pháp nhận dạng mặt được chia thành nhiều hướng theo các tiêu chí khác nhau: nhận dạng với dữ liệu đầu vào là ảnh tĩnh 2D (still image based FR) là phổ biến nhất, tuy nhiên tương lai có lẽ sẽ là 3D FR (vì việc bố trí nhiều camera 2D sẽ cho dữ liệu 3D và đem lại kết quả tốt hơn, đáng tin cậy hơn), cũng có thể chia thành 2 hướng là: làm với dữ liệu ảnh và làm với dữ liệu video.

Trên thực tế người ta hay chia các phương pháp nhận dạng mặt ra làm 3 loại: phương pháp tiếp cận toàn cục (global, như Eigenfaces-PCA, Fisherfaces-LDA), phương pháp tiếp cận dựa trên các đặc điểm cục bộ (local feature based, như LBP, Gabor wavelets) và phương pháp lai (hybrid, là sự kết hợp của hai phương pháp toàn cục và local feature). Phương pháp dựa trên các đặc điểm cục bộ đã được chứng minh là ưu việt hơn khi làm việc trong các điều kiện không có kiểm soát và có thể nói rằng lịch sử phát triển của nhận dạng mặt (A never ending story) là sự phát triển của các phương pháp trích chọn đặc trưng (feature extractrion methods) được sử dụng trong các hệ thống dựa trên feature based.

Các ứng dụng cụ thể của nhận dạng mặt dựa trên 2 mô hình nhận dạng: identification (xác định danh tính, bài toán 1-N), và verification (xác thực danh tính, bài toán 1-1). Trong bài toán identification, ta cần xác định danh tính của ảnh kiểm tra, còn trong bài toán verification ta cần xác định 2 ảnh có cùng thuộc về một người hay không.

II. Phần mềm nhận dạng khuôn mặt đơn giản với Python và OpenCV

1. Cài đặt

Ở bài viết này mình sẽ sử dụng phương pháp nhận diện khuôn mặt đơn giản Haar-cascade Detection . Đầu tiên chúng ta cần cài đặt Python 2.7 và OpenCV

uc?id=1dnrETW8vGiYZpi7Jn_u3IVrdPqfnf0NA&export=download

uc?id=1i4SB8lO7FouWn7AT8aJbGeWORDk3uZoH&export=download

  • Sau khi cài đặt Python 2.7 và OpenCV ta copy file cv2.pyd từ thư mục \face detection\opencv\build\python\2.7
  • Copy vào thư mục \Python27\Lib\site-packages
  • Cài đặt numpy Vào thư mục \Python27\Scripts chạy lệnh
pip install numpy pip install pillow

Chúng ta sẽ sử dụng haarcascade_frontalface_default.xml từ \opencv\sources\data\haarcascades Copy vào thư mục của dự án

  • Cài đặt sqlite

uc?id=1yGSgF0gomLJphyli0g2YMrrsAd-8L3WA&export=download

Tạo CSDL FaceBase với bảng People uc?id=1H8c0h20Nxva1ctMAYEqNC67Cr-jx1Sa1&export=download

OK chúng ta đã sẵn sàng .

2. Viết mã nguồn

Ở bài biết này mình sẽ tạo phần mềm nhận diện khuôn mặt bằng 3 bước đơn giản :

  • Bước 1 mình sẽ tạo dataSet dùng để nhận diện
  • Bước 2 mình sẽ tạo dataTraning sử dụng để traning dữ liệu
  • Bước 3 mình sẽ tạo lớp detector dể nhận diện
Kết nối sqlite để tạo/cập nhật record
def insertOrUpdate(Id,Name): conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(Id) cursor=conn.execute(cmd) isRecordExist=0 for row in cursor: isRecordExist=1 if(isRecordExist==1): cmd="UPDATE People SET Name="+str(Name)+"WHERE ID="+str(Id) else: cmd="INSERT INTO People(Id,Name) Values("+str(Id)+","+str(Name)+")" conn.execute(cmd) conn.commit() conn.close()
Mã nguồn dùng camera để chụp hình dữ liệu
id=raw_input('enter your id') name=raw_input('enter your name') insertOrUpdate(id,name) sampleNum=0 while(True): ret, img = cam.read() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = detector.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) #incrementing sample number sampleNum=sampleNum+1 #saving the captured face in the dataset folder cv2.imwrite("dataSet/User."+id +'.'+ str(sampleNum) + ".jpg", gray[y:y+h,x:x+w]) cv2.imshow('frame',img) #wait for 100 miliseconds if cv2.waitKey(100) & 0xFF == ord('q'): break # break if the sample number is morethan 20 elif sampleNum>20: break cam.release() cv2.destroyAllWindows()

Ở đây mình giới hạn ở 20 tấm , dữ liệu ảnh càng phong phú thì độ chính xác càng cao

uc?id=1WY7FnG7ZjMdz1tbrEVQY8xJN4ggRa8FC&export=download

uc?id=1IVtz6vENMe4Lu_xNCKylDOvMCTgBdTx9&export=download

Dữ liệu lưu vào sqlite

uc?id=1s1Qd52YPdwAzP61D6k4p6X7fx5YbD-We&export=download

dataSetCreator đầy đủ :

import cv2 import sqlite3 cam = cv2.VideoCapture(0) detector=cv2.CascadeClassifier('haarcascade_frontalface_default.xml') #insert/update data to sqlite def insertOrUpdate(Id,Name): conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(Id) cursor=conn.execute(cmd) isRecordExist=0 for row in cursor: isRecordExist=1 if(isRecordExist==1): cmd="UPDATE People SET Name="+str(Name)+"WHERE ID="+str(Id) else: cmd="INSERT INTO People(Id,Name) Values("+str(Id)+","+str(Name)+")" conn.execute(cmd) conn.commit() conn.close() id=raw_input('enter your id') name=raw_input('enter your name') insertOrUpdate(id,name) sampleNum=0 while(True): #camera read ret, img = cam.read() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = detector.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) #incrementing sample number sampleNum=sampleNum+1 #saving the captured face in the dataset folder cv2.imwrite("dataSet/User."+id +'.'+ str(sampleNum) + ".jpg", gray[y:y+h,x:x+w]) cv2.imshow('frame',img) #wait for 100 miliseconds if cv2.waitKey(100) & 0xFF == ord('q'): break # break if the sample number is morethan 20 elif sampleNum>20: break cam.release() cv2.destroyAllWindows()

3.Tạo lớp traning dữ liệu

Load đường dẫn và file trong thư mục dataSet

path='dataSet' imagePaths=[os.path.join(path,f) for f in os.listdir(path)]

tách ID từ tên file ảnh

ID=int(os.path.split(imagePath)[-1].split('.')[1])

Convert ảnh và add vào mảng faces cùng với ID đối với bàn toán classfication ở đây thì Feature là ảnh còn Label chính là id người dùng

faceImg=Image.open(imagePath).convert('L'); faceNp=np.array(faceImg,'uint8') faces.append(faceNp)

Traning và lưu vào file

recognizer.train(faces,np.array(Ids)) recognizer.save('recognizer/trainningData.yml')

uc?id=1XoRkRJ365UIOURJFPbxCxEsCHY_H_GiP&export=download

Traning code đầy đủ :

import cv2,os import numpy as np from PIL import Image recognizer = cv2.face.LBPHFaceRecognizer_create() path='dataSet' def getImagesAndLabels(path): #get the path of all the files in the folder imagePaths=[os.path.join(path,f) for f in os.listdir(path)] faces=[] IDs=[] for imagePath in imagePaths: faceImg=Image.open(imagePath).convert('L'); faceNp=np.array(faceImg,'uint8') #split to get ID of the image ID=int(os.path.split(imagePath)[-1].split('.')[1]) faces.append(faceNp) print ID IDs.append(ID) cv2.imshow("traning",faceNp) cv2.waitKey(10) return IDs, faces Ids,faces=getImagesAndLabels(path) #trainning recognizer.train(faces,np.array(Ids)) recognizer.save('recognizer/trainningData.yml') cv2.destroyAllWindows()

4.Lớp detector nhận diện khuôn mặt đã traning

Lấy thông tin user từ Database

#get data from sqlite by ID def getProfile(id): conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(id) cursor=conn.execute(cmd) profile=None for row in cursor: profile=row conn.close() return profile

Sử dụng camera để nhận diện :

ret,img=cam.read(); gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) faces=faceDetect.detectMultiScale(gray,1.3,5);

Hiển thị thông tin User bằng text

for(x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) id,conf=rec.predict(gray[y:y+h,x:x+w]) profile=getProfile(id) if(profile!=None): cv2.putText(img, "Name: " + str(profile[1]), (x,y+h+30), fontface, fontscale, fontcolor ,2) cv2.putText(img, "Age: " + str(profile[2]), (x,y+h+60), fontface, fontscale, fontcolor ,2) cv2.putText(img, "Gender: " + str(profile[3]), (x,y+h+90), fontface, fontscale, fontcolor ,2)

Tèn tén ten .

uc?id=19_w6XAbTBdxbkqzM2_PJZo_mqr42KK67&export=download

Full code detector

import cv2 import numpy as np from PIL import Image import pickle import sqlite3 faceDetect=cv2.CascadeClassifier('haarcascade_frontalface_default.xml'); cam=cv2.VideoCapture(0); rec=cv2.face.LBPHFaceRecognizer_create(); rec.read("recognizer\\trainningData.yml") id=0 #set text style fontface = cv2.FONT_HERSHEY_SIMPLEX fontscale = 1 fontcolor = (203,23,252) #get data from sqlite by ID def getProfile(id): conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(id) cursor=conn.execute(cmd) profile=None for row in cursor: profile=row conn.close( return profile while(True): #camera read ret,img=cam.read(); gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) faces=faceDetect.detectMultiScale(gray,1.3,5); for(x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) id,conf=rec.predict(gray[y:y+h,x:x+w]) profile=getProfile(id) #set text to window if(profile!=None): #cv2.PutText(cv2.fromarray(img),str(id),(x+y+h),font,(0,0,255),2); cv2.putText(img, "Name: " + str(profile[1]), (x,y+h+30), fontface, fontscale, fontcolor ,2) cv2.putText(img, "Age: " + str(profile[2]), (x,y+h+60), fontface, fontscale, fontcolor ,2) cv2.putText(img, "Gender: " + str(profile[3]), (x,y+h+90), fontface, fontscale, fontcolor ,2) cv2.imshow('Face',img) if cv2.waitKey(1)==ord('q'): break; cam.release() cv2.destroyAllWindows()

Hết ! Cảm ơn các bạn đã quan tâm và theo dõi.

III.Tham khảo

Codacus Viblo

Từ khóa » Nhận Diện Python