You are on page 1of 11

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG

KHOA KĨ THUẬT ĐIỆN TỬ 1


=====o0o=====

BÁO CÁO
BÀI TẬP LỚN

ĐỀ TÀI:

THUẬT TOÁN PHÁT HIỆN KHUÔN MẶT


Giảng viên hướng dẫn : Vũ Hữu Tiến
Môn học : Truyền thông đa phương tiện
Nhóm môn học : 01
Nhóm bài tập lớn : 09
Sinh viên thực hiện : Đào Duy Khánh B18DCDT108
Trần Long Thành B18DCDT236
Phạm Phú Phúc B18DCDT187

HÀ NỘI, 2022

---⁃⁃⁃⁃‹‹‹﴾֍﴿›››⁃⁃⁃⁃---
Phát hiện khuôn mặt là một trong những lĩnh vực mới của xử lý ảnh. Và ngày
nay được sử dụng rộng rãi trong nhiều lĩnh vực của đời sống như nhận dạng
trong lĩnh vực thương mại, hay phát hiện trong lĩnh vực an ninh, hay trong xử lý
video, hình ảnh.

Với sự phát triển không ngừng của khoa học và công nghệ, đặc biệt là với những
chiếc điện thoại thông minh (smartphone) ngày càng hiện đại và được sử dụng
phổ biến trong đời sống con người đã làm cho lượng thông tin thu được bằng
hình ảnh ngày càng tăng. Theo đó, lĩnh vực xử lý ảnh cũng được chú trọng phát
triển, ứng dụng rộng rãi trong đời sống xã hội hiện đại. Không chỉ dừng lại ở
việc chỉnh sửa, tăng chất lượng hình ảnh mà với công nghệ xử lý ảnh hiện nay
chúng ta có thể giải quyết các bài toán nhận dạng chữ viết, nhận dạng dấu vân
tay, nhận dạng khuôn mặt... Một trong những bài toán được nhiều người quan
tâm nhất của lĩnh vực xử lý ảnh hiện nay đó là nhận dạng khuôn mặt (Face
Recognition). Như chúng ta đã biết, khuôn mặt đóng vai trò quan trọng trong
quá trình giao tiếp giữa người với người, nó mang một lượng thông tin giàu có,
chẳng hạn như từ khuôn mặt chúng ta có thể xác định giới tính, tuổi tác, chủng
tộc, trạng thái cảm xúc, đặc biệt là xác định mối quan hệ với đối tượng (có quen
biết hay không). Do đó, bài toán nhận dạng khuôn mặt đóng vai trò quan trọng
trong nhiều lĩnh vực đời sống hằng ngày của con người như các hệ thống
giám sát, quản lý vào ra, tìm kiếm thông tin một người nổi tiếng,...đặc biệt
là an ninh, bảo mật. Có rất nhiều phương pháp nhận dạng khuôn mặt để nâng
cao hiệu suất tuy nhiên dù ít hay nhiều những phương pháp này đang vấp phải
những thử thách về độ sáng, hướng nghiêng, kích thước ảnh, hay ảnh hưởng của
tham số môi trường.
THUẬT TOÁN PHÁT HIỆN KHUÔN MẶT
1. Chức năng app
- Vẽ ra đồ thị điểm ảnh
- Phát hiện khuôn mặt
- Lưu ảnh
- Nhận diện khuôn mặt (đang cập nhật bổ sung)
2. Sơ đồ thuật toán

a, Nguyên lý hoạt động: Bộ phân loại Haar Cascade của OpenCV hoạt động
trên phương pháp tiếp cận cửa sổ trượt . Trong phương pháp này, một cửa sổ
(kích thước mặc định 20 x 20 pixel) được trượt trên hình ảnh (từng hàng) để tìm
các đặc điểm trên khuôn mặt. Sau mỗi lần lặp, hình ảnh được thu nhỏ (thay đổi
kích thước) theo một yếu tố nhất định (được xác định bởi tham số ' scaleFactor
'). Kết quả đầu ra của mỗi lần lặp được lưu trữ và thao tác trượt được lặp lại trên
hình ảnh nhỏ hơn, đã thay đổi kích thước. Có thể có kết quả dương tính giả
trong các lần lặp đầu tiên sẽ được thảo luận chi tiết hơn ở phần sau của bài viết
này. Quá trình thu nhỏ và mở rộng cửa sổ này tiếp tục cho đến khi hình ảnh quá
nhỏ so với cửa sổ trượt. Giá trị của scaleFactor càng nhỏ thì độ chính xác càng
lớn và chi phí tính toán càng cao.
b, Dò biên (Phương pháp canny):

● Giảm nhiễu: Làm mờ ảnh, giảm nhiễu dùng bộ lọc Gaussian kích thước
5x5. Kích thước 5x5 thường hoạt động tốt cho giải thuật Canny. Dĩ nhiên bạn
cũng có thể thay đổi kích thước của bộ lọc làm mờ cho phù hợp. Tham khảo bài
viết: 
● Tính Gradient và hướng gradient: ta dùng bộ lọc Sobel X và Sobel Y
(3x3) để tính được ảnh đạo hàm Gx và Gy. Tham khảo bài viết giải thích về
gradient. Sau đó, ta tiếp tục tính ảnh Gradient và góc của Gradient theo công
thức. Ảnh đạo hàm Gx và Gy là ma trận (ví dụ: 640x640), thì kết quả tính ảnh
đạo hàm Edge Gradient cũng là một ma trận (640x640), mỗi pixel trên ma trận
này thể hiện độ lớn của biến đổi mức sáng ở vị trí tương ứng trên ảnh gốc.
Tương tự, ma trận Angle cũng có cùng kích thước (640x640), mỗi pixel trên
Angle thể hiện góc, hay nói cách khác là hướng của cạnh. Ví dụ dễ hiểu, nếu
góc gradient là 0 độ, thì cạnh của ta trên ảnh sẽ là một đường thẳng đứng (tức
tạo góc 90 độ so với trục hoành) (vuông góc hướng gradient). Khi tính toán,
giá trị hướng gradient sẽ nằm trong đoạn [-180, 180] độ, ta không giữ nguyên
các góc này mà gom các giá trị này về 4 bin đại diện cho 4 hướng: hướng ngang
(0 độ), hướng chéo bên phải (45 độ), hướng dọc (90 độ) và hướng chéo trái (135
độ).

● Non-maximum Suppression (viết tắt NMS): loại bỏ các pixel ở vị trí


không phải cực đại toàn cục. Ở bước này, ta dùng một filter 3x3 lần lượt chạy
qua các pixel trên ảnh gradient. Trong quá trình lọc, ta xem xét xem độ lớn
gradient của pixel trung tâm có phải là cực đại (lớn nhất trong cục bộ - local
maximum) so với các gradient ở các pixel xung quanh. Nếu là cực đại, ta sẽ ghi
nhận sẽ giữ pixel đó lại. Còn nếu pixel tại đó không phải là cực đại lân cận, ta sẽ
set độ lớn gradient của nó về zero. Ta chỉ so sánh pixel trung tâm với 2 pixel lân
cận theo hướng gradient. Ví dụ: nếu hướng gradient đang là 0 độ, ta sẽ so pixel
trung tâm với pixel liền trái và liền phải nó. Trường hợp khác nếu hướng
gradient là 45 độ, ta sẽ so sánh với 2 pixel hàng xóm là góc trên bên phải và góc
dưới bên trái của pixel trung tâm. Tương tự cho 2 trường hợp hướng gradient
còn lại. Kết thúc bước này ta được một mặt nạ nhị phân

● Lọc ngưỡng: ta sẽ xét các pixel dương trên mặt nạ nhị phân kết quả của
bước trước. Nếu giá trị gradient vượt ngưỡng max_val thì pixel đó chắc chắn là
cạnh. Các pixel có độ lớn gradient nhỏ hơn ngưỡng min_val sẽ bị loại bỏ. Còn
các pixel nằm trong khoảng 2 ngưỡng trên sẽ được xem xét rằng nó có nằm liền
kề với những pixel được cho là "chắc chắn là cạnh" hay không. Nếu liền kề thì
ta giữ, còn không liền kề bất cứ pixel cạnh nào thì ta loại. Sau bước này ta có thể
áp dụng thêm bước hậu xử lý loại bỏ nhiễu (tức những pixel cạnh rời rạc hay
cạnh ngắn) nếu muốn. 
c, Làm mịn ảnh (Bộ lọc Bilateral):

cv.bilateralFilter() : Là bộ lọc hiệu quả cao trong công việc loại bỏ nhiễu mà vẫn
giữ lại được các đường viền (cạnh) trong ảnh.

Như theo chúng ta đã biết, bộ lọc Gauss quyết định giá trị một điểm ảnh bằng
cách lấy trung bình thap hàm Gauss các giá trị điểm ảnh xung quanh điểm đó.
Hàm trọng số Gauss chỉ phụ thuộc vào khoảng cách trong không gian so với
trung tâm điểm ảnh, không quan tâm đến sự tương quan giữa mức xám của điểm
trung tâm với các điểm xung quanh đó. Nó cũng không quan tâm rằng điểm ảnh
trung tâm có nằm tại một đường biên trong ảnh không, vì thế làm nhòe đi các
đường biên trong ảnh.

Bộ lọc Bilater cũng sử dụng một bộ lọc Gauss với khoảng cách đến điểm trung
tâm, đảm bảo chỉ có các điểm ở gần vào giá trị điểm trung tâm. Tuy vậy nó sử
dụng thêm một hàm Gauss cho mức xám , đảm bảo chỉ các điểm ảnh có mức
xám tương đồng với điểm ảnh trung tâm tham gia vào quá trình làm mịn. Vì thế
bộ lọc mức xám rất rõ ràng hơn. Hơn nữa, thay vì hoạt động trên các kênh màu
một cách riêng lẻ như bộ lọc trung bình hay bộ lọc Gauss, bộ lọc Bilater có thể
thi hành việc đo đạc màu sắc có chủ đích trong không gian màu CIE – Lab, làm
mượt màu và bảo toàn các biên theo hướng phù hợp hơn với nhận thức con
người.

d, Code Python

from tkinter import *

from tkinter.ttk import *

from tkinter import messagebox

import tkinter

import cv2

import PIL.Image, PIL.ImageTk

from time import sleep

from threading import Thread

import utils

cap = cv2.VideoCapture(0)

window = Tk()

window.title("Face Detection OpenCV")

video = cv2.VideoCapture(0)

canvas_w = video.get(cv2.CAP_PROP_FRAME_WIDTH)

canvas_h = video.get(cv2.CAP_PROP_FRAME_HEIGHT)

canvas = Canvas(window, width = canvas_w, height= canvas_h , bg=


"white")

canvas.pack()

bw = 0
def handleBW():

global bw

bw = 1 - bw

def saveImg():

ret, frame = video.read()

if bw!=0:

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

frame = utils.FaceRec(frame)

utils.WriteFace(frame)

button = Button(window,text = "Black & White", command=handleBW)

button.pack(side=RIGHT)

buttonSave = Button(window,text = "Save", command=saveImg)

buttonSave.pack(side=LEFT, pady=5)

photo = None

count = 0

#nhan dien khuon mat(dang cap nhat)

def send_to_server():

sleep(5)

return

def update_frame():

global canvas, photo, bw, count

# Doc tu camera

ret, frame = video.read()

# Ressize
frame = cv2.resize(frame, dsize=None, fx=1, fy=1)

# Chuyen he mau

if bw==0:

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

else:

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

frame = utils.FaceRec(frame)

# Convert hanh image TK

photo = PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(frame))

# Show

canvas.create_image(0,0, image = photo, anchor=tkinter.NW)

count = count +1

if count%10==0:

#send_to_server()

thread = Thread(target=send_to_server)

thread.start()

window.after(15, update_frame)

update_frame()

window.mainloop()
e, Demo:
LỜI CÁM ƠN

Đầu tiên, em xin gửi lời cảm ơn chân thành nhất đến Học Viện Công nghệ
Bưu chính Viễn thông đã đưa môn học Truyền thông đa phương tiện vào trong
chương trình giảng dạy của nhà trường. Đặc biệt, em xin gửi lời cảm ơn đến
thầy Vũ Hữu Tiến là giảng viên bộ môn Truyền thông đa phương tiện, giảng
dạy và truyền cho bọn em những kiến thức đáng quý trong suốt quá trình học
vừa qua. Trong thời gian tham dự lớp học của thầy em đã tiếp thu được những
kiến thức quý báu, bổ ích, học tập và làm việc theo tác phong nghiêm túc, có
hiệu quả trong học tập. Đây thực là một điều đáng quý trong suốt quá trình học
tập và sau này khi đi làm của em.
Bộ môn Truyền thông đa phương tiện là môn học rất thú vị, vô cùng tốt
và gắn liền với nhu cầu thực tiễn của mỗi sinh viên. Do thời gian học tập và tìm
hiểu còn có hạn, vì vậy bài báo cáo của chúng em khó tránh khỏi những thiếu
sót và nhiều chỗ chưa chuẩn xác, kính mong thầy và các bạn xem xét và góp ý
giúp bài báo cáo của chúng em được hoàn thiện hơn.
Em xin chân thành cảm ơn!
Hà Nội, ngày 4 tháng 5 năm 2022
Sinh viên thực hiện
Đào Duy Khánh
Trần Long Thành
Phạm Phú Phúc

You might also like