You are on page 1of 23

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN ĐIỆN TỬ - VIỄN THÔNG

BÁO CÁO BTL NNLT


Đề tài:
Ước lượng BMI của người dựa trên ảnh khuôn mặt
Sinh viên thực hiện:
Hoàng Mai Phương 20193060
Lại Thị Huyền Thương 20193128
Mai Thị Quỳnh Anh 20192685
Đinh Thị Quỳnh 20193073

Giáo viên HD:


Cô Trần Thị Thanh Hải
Báo cáo bài tập lớn NNLT Nhóm 6

LỜI NÓI ĐẦU

Ngày nay, khoa học công nghệ ngày càng phát triển, cùng với đó các cảm biến ảnh,
xử lí ảnh ngày càng trở nên đa dạng. Việc sử dụng hình ảnh khuôn mặt không chỉ sử
dụng trong xác thực, định danh mà còn có thể hướng đến các ứng dụng khác về sức
khỏe như xác định chỉ số BMI, ứng dụng vào y học. Đề tài này chúng em chọn hướng
đến ước lượng chỉ số BMI từ hình ảnh khuôn mặt thông qua việc xây dựng một mô hình
hồi quy tuyến tính.

Bài báo cáo được hoàn thành nhằm mục đích tìm hiểu, củng cố và trang bị cho bản
thân kiến thức về ngôn ngữ lập trình C++ với thư viện opencv. Qua đó vận dụng những
kiến thức thu thập được để có thể vận dụng làm bài tập, ứng dụng vào dự án được đề ra.

Xin chân thành cảm ơn cô Trần Thị Thanh Hải đã tạo môi trường giúp chúng em có
thể làm project này cũng như trang bị kiến thức, tài liệu cho chúng em!

1
Báo cáo bài tập lớn NNLT Nhóm 6

MỤC LỤC
LỜI NÓI ĐẦU...........................................................................................................................1
DANH MỤC HÌNH ẢNH.........................................................................................................3
DANH MỤC KÝ HIỆU VÀ CHỮ VIẾT TẮT.......................................................................4
Đóng góp của từng thành viên.................................................................................................5
CHƯƠNG 1. LÝ THUYẾT CHUNG......................................................................................5

1.1 Chỉ số BMI........................................................................................................................5

1.2 Môi trường lập trình.........................................................................................................6


1.2.1 Ngôn ngữ lập trình C++...........................................................................................6
1.2.2 Thư viện OpenCV....................................................................................................6

1.3 Xử lí cơ sở dữ liệu.............................................................................................................6
1.3.1 Tính toán đặc trưng histogram RGB........................................................................7
1.3.2 Tính toán đặc trưng HOG.........................................................................................7

1.4 Thuật toán hồi qui đa tuyến tính (linear regression)......................................................9


1.4.1 Hồi qui tuyến tính bằng đại số...............................................................................10
1.4.2 Hồi qui đa tuyến tính bằng sử dụng Gradient desent.............................................11

1.5 Đánh giá sai số ước lượng..............................................................................................12


CHƯƠNG 2. THỰC HÀNH..................................................................................................13

2.1 Các bước thưc hiện.........................................................................................................13


2.1.1 Dữ liệu đầu vào......................................................................................................13
2.1.2 Đọc ảnh và dữ liệu..................................................................................................13
2.1.3 Tính toán một vector biểu diễn ảnh........................................................................14
2.1.4 Biểu diễn các dữ liệu ảnh như đã thu thập bằng vector đặc trưng biểu diễn..........15
2.1.5 Cài đặt thuật toán hồi qui đa tuyến tính(Multiple linear regression) để tìm mô hình
dự toán BMI của một khuôn mặt từ ảnh.........................................................................15
2.1.6 . Chương trình tính toán.........................................................................................16
2.1.7 Thực hiện đánh giá với tối thiểu 10 người mới không có trong CSDL đã thu, và
đánh giá sai số ước lượng................................................................................................17

2.2 Kết quả và nhận xét.........................................................................................................18


KẾT LUẬN..............................................................................................................................19
PHỤ LỤC.................................................................................................................................20

2
Báo cáo bài tập lớn NNLT Nhóm 6
TÀI LIỆU THAM KHẢO.....................................................................................................20

DANH MỤC HÌNH ẢNH

Hình 1. 1 Chỉ số BMI.......................................................................................................5


Hình 1. 2. Môi trường lập trình........................................................................................6
Hình 1. 3. Ví dụ về histogram RGB.................................................................................7
Hình 1. 4. Đặc trưng HOG của ảnh..................................................................................8
Hình 1. 5. Sơ đồ tính toán HOG.......................................................................................8
Hình 1. 6. Vote hướng vào cell.........................................................................................9
Hình 1. 7. Ước tính cân nặng dựa vào chiều cao............................................................10
Hình 1. 8. Hàm mất mát phụ thuộc vào số lần lặp lại.....................................................12

Hình 2. 2. Kết quả ước lượng.........................................................................................18

3
Báo cáo bài tập lớn NNLT Nhóm 6
DANH MỤC KÝ HIỆU VÀ CHỮ VIẾT TẮT

BMI Body mass Index


RGB Red Green Blue
HOG Histogram of Oriented Gradient
CSDL Cơ sở dữ liệu

4
Báo cáo bài tập lớn NNLT Nhóm 6

Đóng góp của từng thành viên

Để phát huy ưu thế của từng thành viên đồng thời để các thành viên đều hiểu được chương
trình, phát huy tối đa lợi thế làm việc nhóm, chúng em có bảng phân chia nhiệm vụ như
sau:

Người thực hiện Nhiệm vụ Người kiểm tra


Mai Thị Quỳnh Anh Chuẩn bị CSDL, code, Làm báo cáo. Cả nhóm
Hoàng Mai Phương Chuẩn bị CSDL, code, Làm báo cáo. Cả nhóm
Đinh Thị Quỳnh Chuẩn bị CSDL, code, Làm Slide. Cả nhóm
Lại Thị Huyền Thương Chuẩn bị CSDL, code, Làm Slide. Cả nhóm

CHƯƠNG 1. LÝ THUYẾT CHUNG

1.1 Chỉ số BMI


BMI (Body mass Index) là chỉ số được tính từ chiều cao và cân nặng, là một chỉ số đáng
tin cậy về sự mập ốm của một người. BMI không đo lường trực tiếp mỡ của cơ thể nhưng
các nghiên cứu đã chứng minh rằng BMI tương quan với đo mỡ trực tiếp như ở Hình 1. 1
Chỉ số BMI. BMI là phương pháp không tốn kém và dễ thực hiện để tầm soát vấn đề sức
khoẻ. Tính chỉ số BMI là một phương pháp tốt nhất để đánh giá thừa cân và béo phì cho
một quần thể dân chúng. Để tính chỉ số BMI, người ta chỉ yêu cầu đo chiều cao và cân
nặng, không tốn kém và dễ thực hiện. Sử dụng chỉ số BMI cho phép người ta so sánh tình
trạng cân nặng của họ với quần thể nói chung.

Và như đề án project này thì cũng đã thể hiện được mục đích của nó. Thông qua hình
ảnh về khuôn mặt một người, chúng em đi ước tính chỉ số BMI của người đó thông qua
hồi quy tuyến tính sử dụng thư viện OpenCV lập trình ngôn ngữ C++.

5
Báo cáo bài tập lớn NNLT Nhóm 6

Hình 1. 1 Chỉ số BMI

1.2 Môi trường lập trình

1.2.1 Ngôn ngữ lập trình C++


C++ là một loại ngôn ngữ lập trình bậc trung (middle-level). Đây là ngôn ngữ lập
trình đa năng được tạo ra bởi Bjarne Stroustrup như một phần mở rộng của ngôn ngữ
lập trình C, hoặc "C với các lớp Class", Ngôn ngữ đã được mở rộng đáng kể theo thời
gian và C ++ hiện đại có các tính năng: lập trình tổng quát, lập trình hướng đối tượng,
lập trình thủ tục, ngôn ngữ đa mẫu hình tự do có kiểu tĩnh, dữ liệu trừu tượng, và lập
trình đa hình, ngoài ra còn có thêm các tính năng, công cụ để thao tác với bộ nhớ cấp
thấp.

1.2.2 Thư viện OpenCV


OpenCV được thiết kế một cách tối ưu, sử dụng tối đa sức mạnh của các dòng chip
đa lõi… để thực hiện các phép tính toán trong thời gian thực, nghĩa là tốc độ đáp ứng
của nó có thể đủ nhanh cho các ứng dụng thông thường. OpenCV là thư viện được thiết
kế để chạy trên nhiều nền tảng khác nhau (cross-patform), nghĩa là nó có thể chạy trên
hệ điều hành Window, Linux, Mac, iOS … Việc sử dụng thư viện OpenCV tuân theo
các quy định về sử dụng phần mềm mã nguồn mở BSD do đó bạn có thể sử dụng thư
viện này một cách miễn phí cho cả mục đích phi thương mại lẫn thương mại.

Việc chọn môi trường lập trình ảnh hưởng rất nhiều đến quá trình làm, thực hiện dự
án, và từ những mặt lợi ích đã nêu thì chúng em đã dùng ngôn ngữ C++ với thư viện
Opencv trên Visual Studio (Hình 1. 2. Môi trường lập trình).

6
Báo cáo bài tập lớn NNLT Nhóm 6

Hình 1. 2. Môi trường lập trình

1.3 Xử lí cơ sở dữ liệu
Để thực hiện đề án này thì trước tiên ta phải xử lí ảnh. Trước tiên ta phải đọc ảnh,
từ dữ liệu ảnh đầu vào là ảnh ta thu được 1 ma trận Mat của ảnh đó. Trong OpenCV
với giao diện C++, tất cả các kiểu dữ liệu ảnh, ma trận đều được lưu dưới dạng
cv::Mat. Hàm imread sẽ đọc ảnh đầu vào và lưu vào biến.

Sau đó, ta tính toán ra vector đặc trưng của ảnh để ước tính BMI. Bằng cách sử
dụng các phương pháp rút trích đặc trưng ảnh ta sẽ thu được vector đặc trưng của ảnh.
Nói một cách khác đó chính là bạn mã hóa hình ảnh thành một vector, và vector này
mang những đặc trưng (các số thực) đại diện cho ảnh đó. Một vector biểu diễn ảnh có
thể tính toán đặc trưng histogram RGB của ảnh, histogram of gradient (HOG), đặc trưng
sift.. và có thể sử dụng các hàm của OpenCV. Trước tiên chúng ta đi tìm hiểu về một số
tính toán để ra vector dặc trưng.

1.3.1 Tính toán đặc trưng histogram RGB


Histogram được gọi là biểu đồ sắc độ. Biểu đồ sắc độ là đồ thị thể hiện thông tin độ
sáng của điểm ảnh (Pixel) tạo nên bức ảnh. Đặc trưng histogram RGB của ảnh chính là
biểu đồ về sự phân bố màu “Đỏ, xanh lá, xanh da trời” của ảnh đó. Và khi thực hiện
chương trình tính toán đặc trung này, ảnh được biểu diễn về một vector.

7
Báo cáo bài tập lớn NNLT Nhóm 6

Hình 1. 3. Ví dụ về histogram RGB

Từ một ảnh đầu vào ta thu được biểu đồ thể hiện màu ảnh như ở Hình 1. 3. Ví dụ về
histogram RGBNhưng do đây là biểu đồ về màu ảnh nên khi chụp ở độ sáng, phông nền
khác nhau cũng ảnh hưởng khá nhiều đến kết uqar thu được và khi ước tính có thể sẽ sai
số lớn. Vì vậy nhóm chúng em sẽ thực hiện biểu diễn vector đặc trưng của ảnh dựa vào
HOG.

1.3.2 Tính toán đặc trưng HOG


Pháp rút trích đặc trưng hình ảnh HOG xuất bản ở hội nghị CVPR 2005 được đề xuất
bởi tác giả là Dalal và Triggs. HOG là viết tắt của Histogram of Oriented Gradient - một
loại “feature descriptor”. Mục đích của “featura descriptor” là trừu tượng hóa đối tượng
bằng cách trích xuất ra những đặc trưng của đối tượng đó và bỏ đi những thông tin
không hữu ích. Vì vậy, HOG được sử dụng chủ yếu để mô tả hình dạng và sự xuất hiện
của một đối tượng trong ảnh.

Bản chất của phương pháp HOG là sử dụng thông tin về sự phân bố của các cường
độ gradient (intensity gradient) hoặc của hướng biên (edge directins) để mô tả các đối
tượng cục bộ trong ảnh. Các toán tử HOG được cài đặt bằng cách chia nhỏ một bức ảnh
thành các vùng con, được gọi là “tế bào” (cells) và với mỗi cell, ta sẽ tính toán một
histogram về các hướng của gradients cho các điểm nằm trong cell. Ghép các histogram
lại với nhau ta sẽ có một biểu diễn cho bức ảnh ban đầu. Để tăng cường hiệu năng nhận
dạng, các histogram cục bộ có thể được chuẩn hóa về độ tương phản bằng cách tính một
ngưỡng cường độ trong một vùng lớn hơn cell, gọi là các khối (blocks) và sử dụng giá
trị ngưỡng đó để chuẩn hóa tất cả các cell trong khối. Kết quả sau bước chuẩn hóa sẽ là
một vector đặc trưng có tính bất biến cao hơn đối với các thay đổi về điều kiện ánh sáng
như trong Hình 1. 4. Đặc trưng HOG của ảnh

8
Báo cáo bài tập lớn NNLT Nhóm 6

Hình 1. 4. Đặc trưng HOG của ảnh

Với mỗi hình ảnh đầu vào kích thước 64x128, chia thành các block 16x16 chồng
nhau, sẽ có 7 block ngang và 15 block dọc, nên sẽ có 7x15 = 105 blocks. Mỗi block
gồm 4 cell. Khi áp dụng biểu đồ 9-bin cho mỗi cell, mỗi block sẽ được đại diện bởi một
vector có kích thước 36x1. Vì vậy, khi nối tất cả các vector trong một block lại với
nhau, ta sẽ thu được vector đặc trưng HOG của ảnh có kích thước 105x36x1 = 3780x1.

Hình 1. 5. Sơ đồ tính toán HOG

Theo như sơ đồ tính toán HOG (Hình 1. 5. Sơ đồ tính toán HOG) ta gồm các bước làm
sau:

 Chuẩn hóa mức sáng và màu sắc của ảnh: việc dùng ảnh màu và các chuẩn hóa trên ảnh
cho kết quả tốt hơn.
 Tính gradient của ảnh.
 Vote hướng vào cell (histogram): Ở bước 2, ta đã tính được ảnh gradient theo trục x (dx)
và gradient theo trục y (dy). Và ta tính góc và biên độ tương ứng của từng pixel đang
xét như Hình 1. 6. Vote hướng vào cell

9
Báo cáo bài tập lớn NNLT Nhóm 6

Hình 1. 6. Vote hướng vào cell

 Chuẩn hóa theo block: Vì hiện tại mỗi cell đang mang trong mình histogram trên vùng
ảnh 8x8, các thông tin này mang tính chất cục bộ. Vì vậy tác giả đã đưa ra nhiều cách
chuẩn hóa khác nhau dựa trên các khối (block) chồng lấn (overlap) nhau.
 Trích vector đặc trưng của các block đã chuẩn hóa cho ảnh 64x128.

Sau khi đã tính toán vector đặc trưng của ảnh, ta biểu diễn vector này cho từng ảnh
trong cơ sở dữ liệu tương ứng với các chỉ số BMI của nó, một CSDL sẽ có 1 vector đặc
trung và 1 chỉ số BMI tương ứng.

1.4 Thuật toán hồi qui đa tuyến tính (linear regression)


Để có thể liên hệ giữa ảnh (mặt người cần xác định BMI) và BMI ta sử dụng thuật
toán hồi qui đa tuyến tính (linear regression), đây là một thuật toán Supervised learning.

Mục tiêu của giải thuật hồi quy tuyến tính là dự đoán giá trị của một hoặc nhiều
biến mục tiêu liên tục (continuous target variable) y dựa trên một ma trận đầu vào ma
trận x. Linear hay tuyến tính hiểu một cách đơn giản là thẳng, phẳng. Trong không gian
hai chiều, một hàm số được gọi là tuyến tính nếu đồ thị của nó có dạng một đường
thẳng. Trong không gian ba chiều, một hàm số được goi là tuyến tính nếu đồ thị của nó
có dạng một mặt phẳng. Trong không gian nhiều hơn 3 chiều, khái niệm mặt phẳng
không còn phù hợp nữa, thay vào đó, một khái niệm khác ra đời được gọi là siêu mặt
phẳng (hyperplane).

1.4.1 Hồi qui tuyến tính bằng đại số


Về cơ bản thì ta sẽ có một tập huấn luyện chứa các cặp (X (i), Y(i)) tương ứng và
nhiệm vụ của ta là phải tìm giá trị ŷ tương ứng với một đầu vào x mới. Để làm điều này
ta cần tìm được quan hệ giữa x và y để từ đó đưa ra được dự đoán. Hay nói cách trừu
tượng hơn là ta cần vẽ được một đường quan hệ thể hiện mối quan hệ trong tập dữ liệu.

Y = Xω = ŷ (1. 1)

10
Báo cáo bài tập lớn NNLT Nhóm 6
Trong đó:

[] [ ] []
y1 ω1
1 … x1 k
y ω
Y= 2 , X= ⋮ ⋱ ⋮ , ω= 2
⋮ ⋮
1 … x nk
yn ωk

Y là giá trị thực của output (dựa trên số liệu thống kê chúng ta có trong tập training
data), trong khi ŷ là giá trị mà mô hình Linear Regression dự đoán được. Nhìn chung, Y
và ŷ là hai giá trị khác nhau do có sai số mô hình, tuy nhiên, chúng ta mong muốn rằng
sự khác nhau này rất nhỏ. Chúng ta cần đi xác định hệ số ω.

Hình 1. 7. Ước tính cân nặng dựa vào chiều cao

Ví dụ khi ta ước tính cân nặng dựa vào chiều cao như trên Hình 1. 7. Ước tính cân
nặng dựa vào chiều caoCác chấm đỏ là dữ liệu đầu vào (cơ sở dữu liêu) gồm chiều cao
và cân nặng, đường màu xạnh chính là đường sau khi ước tính, tính được ω và biễn diễn
y = ω.x, ta thấy các chấm đỏ gần với các đường xanh vậy là kết quả của việc ước tính
khá sát với thực

Với dữ liệu vào ma trận X (vector biểu diễn ảnh) và ma trận Y (chỉ số BMI) ta sẽ
tính được ma trận β.

ω = Y.X-1 (1. 2)

Như công thức = Y.X-1 (1. 2) thì sẽ tính được ma trận β


dựa vào ma trận nghịch đảo của X và Y. Nhưng khi det(X)=0 thì việc tính này không
khả thi, và ta sẽ có công thức nghiệm:

ω = (XT.X)-1.XT.Y (1. 3)

Như vậy từ đây ta đã xác định được ma trận ω và với dữ liệu mới (vector hog của ảnh
khác CSDL) ta sẽ thu được giá trị y (chỉ số BMI).

11
Báo cáo bài tập lớn NNLT Nhóm 6
Nhưng điều gì xảy ra nếu (X T.X) không thể đảo ngược (số ít hoặc suy biến). Đến đây,
vì để xác định một cách chính xác, nhóm chúng em sử dụng một phương pháp khác để
xác định các hệ số mà không phải tính nghịch đảo ma trận. Đó là phương pháp sử dụng
Gradient desent.

1.4.2 Hồi qui đa tuyến tính bằng sử dụng Gradient desent


Giả thuyết hàm đa tuyến tính n biến có dạng:
ŷ=ω0 +ω 1 x 1+ ω2 x2 +... … .+ω n x n

hay ŷ=x . ω với : x = [1 ; x 1; x 2; ….. ; x n] , w =[w0 ; w 1 ; w 2 ; ..... ; w n ]T

1.4.2.1. Hàm mất mát

Hàm mất mát của thuật toán có dạng: (trong đó: m là số lượng giá trị đúng. )

Nhiệm vụ của chúng ta là tìm vector w sao cho hàm mất mát J(w) nhỏ nhất. Giờ cần
một thuật toán để tìm giá trị nhỏ nhất của hàm J. Đó chính là gradient descent.

1.4.2.2. Thuật toán Gradient descent

∂ J ( ω)
Dựa vào đạo hàm theo từng biến của hàm mất mát, ta sẽ xác định w i=w i−α ∂ w
i

m
α
Với hàm mất mát dạng như trên, ta có: ω i=ω i− ∑
m i=1
( x (i) ω− y (i) ) x (ji)

với α là tốc độ học – learning rate để thay đổi giá trị ω i;

x (ji ) là giá trị hàng thứ i cột j của ma trận X

12
Báo cáo bài tập lớn NNLT Nhóm 6
Với các giá trị w tìm được, chúng ta tính giá trị hàm mất mát. Lặp lại điều này đến

khi hàm mất mát đủ nhỏ, từ đó chúng ta xác định được ma trận w và hàm ŷ=x . ω.

Việc số lần lặp lại ảnh hưởng đến giá trị hàm mất mát rất nhiều, lặp lại cang nhiều thì

độ chính xác càng cao (Hình 1. 8. Hàm mất mát phụ thuộc vào số lần lặp lại ), nhưng

lặp lại nhiều ảnh hưởng tới tốc dộ xử lí của chương trình cũng như bộ nhớ khi thực hiện

chương trình.

Hình 1. 8. Hàm mất mát phụ thuộc vào số lần lặp lại

Hình 1. 8. Hàm mất mát phụ thuộc vào số lần lặp lại ta thấy, số lần lặp lại từ 0 – 1000
có sự thay đổi rất lớn đến hàm mất mát, độ chính xác cao hơn và càng tăng số lần lặp thì
hàm mất mát càng gần với 0.

1.5 Đánh giá sai số ước lượng


Như đã trình bày ở trên thì việc ước lượng như vậy vẫn còn sai số, nên phải xác định
được sai số của phép ước lượng này. Ta sẽ có đầu vào là ma trận X và ma trận ω tính
được ở trên và sẽ thu được y (chỉ số BMI thực thế) cần tính rồi so sánh với giá trị ŷ (chỉ
số BMI ước lượng).

Chúng ta mong muốn rằng sự sai khác e giữa giá trị thực y và ŷ giá trị dự đoán là nhỏ
nhất. Nói cách khác, chúng ta muốn giá trị sau đây càng nhỏ càng tốt:

1 e2 = 1 1
( y − ŷ) = (y – x.ω) (1. 8)
2 2

2 2 2

13
Báo cáo bài tập lớn NNLT Nhóm 6
Sau khi tính được sai số của bài toán, ta sẽ tiến hành đánh giá về độ chính xác khi
ước lượng BMI thông qua khuôn mặt dựa vào chỉ số sai số.

CHƯƠNG 2. THỰC HÀNH

Sau khi tìm hiểu qua về lý thuyết chung, chúng ta sẽ thự hành tìm hiểu về đề tài này.

2.1 Các bước thưc hiện

2.1.1 Dữ liệu đầu vào


Để tính chính xác cao hơn thì dữ liệu đầu vào gồm 20 người, mỗi người 7 ảnh: Ảnh
có độ phân giải (640x480) 3 kênh màu được chụp theo các góc như sau: -60o, -30o, 0o,
30o, 60o theo phương ngang và 2 ảnh ngẩng và cúi một góc khoảng 30o theo phương
thẳng đứng. Số lượng ảnh: 20x7 = 140 ảnh, tương ứng với chiều cao và cân nặng của
người đó. Trong đó, mỗi người được đánh số bởi mã số, họ tên, và được lưu một số ảnh
khuôn mặt được chụp theo các góc nhìn khác nhau. Dữ liệu được lưu vào trong một thư
mục, thư mục này chứa các thư mục con, mỗi thư mục con có tên là tên của người,
trong đó có chứa các file ảnh khuôn mặt của người đó. Để thuận tiện cho việc tính toán
thì chúng em xử lí chỉ số BMI = cân nặng/(chiều cao * chiều cao).

2.1.2 Đọc ảnh và dữ liệu


Sử dụng hàm ‘imread()’ trong thư viện OpenCV để thực hiện đọc 1 ảnh. Để thuận
tiện tính toán, chúng em lưu các thư mục chứa ảnh và các tệp chứa dữ liệu chỉ số BMI
tương ứng vào các thư mục riêng biệt

// Doc tat ca cac anh


// Dau vao có noi luu cac anh sau doc (img)
// Dia chi Folder de doc anh
vector<Mat> readImgs(vector <Mat> img, string src_path)
{
vector <cv::String> fileNames;
glob(src_path, fileNames, true);
//luu duong dan toi file vao fileNames
for (auto file : fileNames
{
img.push_back(imread(file));//Lưu ảnh đã đọc vào một vector
}
return img;

14
Báo cáo bài tập lớn NNLT Nhóm 6
}
Đồng thời khi đọc ảnh xong cũng đọc luôn giá trị BMI của người có trong CSDL và
lưu vào 1 vector, thứ tự BMI trong vetor này sẽ tương ứng thứ tự với ảnh trong vector
đọc ảnh. Trong CSDL, ảnh của một người chụp theo các góc khác nhau cùng chứa trong
một thư mục con, các ảnh sẽ được gán cùng một giá trị BMI. Vì thế, để thuận tiện, hàm
đọc và lấy giá trị BMI (get _Y) có biến “inter” để lấy cùng một giá trị BMI “inter” lần
của các ảnh trong cùng một thư mục con.

// Doc du lieu BMI trong file txt


// Dau vao la dia chi luu can doc: src_path
// Vector luu cac chi so BMI: get_Y
// Gia tri BMI day cho bao nhieu anh: repeat
template<typename T>
vector<T> get_Y(string src_path, vector<T> get_Y, int inter) {
int i = 0;
string pattern = "*.txt"; // Dinh dang file can doc
vector <cv::String> fileNames; // Vector luu dia chi cac file BMI se doc
glob(src_path + pattern, fileNames, true); // Doc tat ca cac file *.txt
cout << "Reading..." << endl;
for (auto file : fileNames)
{
cout << file << endl;
double value;
fstream getfile(file); //Mở file .txt
getfile >> value; //Lưu giá trị đọc được vào biến value
if (repeat != 0) {
for (int j = 0; j < inter; j++) {
get_Y.push_back((T)value);
//Lưu value vào vector get_Y với inter lần lặp
}
}
getfile.close(); //Đónng file txt
i++;
}
cout << "Complete...." << i << " text" << endl;
return get_Y;}

15
Báo cáo bài tập lớn NNLT Nhóm 6
2.1.3 Tính toán một vector biểu diễn ảnh
Có thể tính trực tiếp như công thức, các bước đã đề trên lý thuyết nhưng để thuận
lợi cho việc tính toán sau thì nhóm chúng em sử dụng hàm có sẵn trong thư viện
OpenCV.
ŷ=ω0 +ω 1 x 1+ ω2 x2 +... … .+ω n x n

Hàm đa tuyến tính ŷ n biến có chứa hệ số tự do ω 0, nên ta cần tạo vector đầu vào n
+ 1 chiều với giá trị đầu của vector là 1.

//Tính vector đặc trưng hog của 1 ảnh đã đọc để ước lượng
template<typename T>
vector<T> get_hogImage(Mat input) {
resize(input, input, Size(64, 128)); //Đặt lại size của ảnh
HOGDescriptor hog;
vector<float> ders;
vector<T> Hog;
vector<Point> locs;
Hog.push_back(1);
hog.compute(input, ders, Size(32, 32), Size(0, 0), locs); //Tính HOG
for (int i = 0; i < ders.size(); i++) {
Hog.push_back((T)ders.at(i));
}
return Hog;
}

2.1.4 Biểu diễn các dữ liệu ảnh như đã thu thập bằng vector đặc trưng biểu diễn
Ảnh sau khi đọc sẽ được lưu dưới dạng ma trận và sau khi sử dụng vector đặc trưng
và tính ở bước trên ta sẽ thu được vector biểu diễn cho ảnh. Khi làm bài, để chương
trình được đơn giản hơn, chúng em tính hog và đọc ảnh trong cùng một bước.

//Đọc tất và các ảnh từ file và tính hog tương ứng


//Đầu vào src_path là đường dẫn link file cần đọc
template<typename T>
vector<vector<T> > readHOGImgs(string src_path)
{
vector<vector<double> > input;
int i = 0;
Mat img;
vector <cv::String> fileNames;

16
Báo cáo bài tập lớn NNLT Nhóm 6
cout << "readImgs...." << endl;
glob(src_path + pattern + pattern1, fileNames, true); //Đọc file
for (auto file : fileNames)
{
cout << file << endl;
img = imread(file);
input.push_back(get_hogImage<T>(img)); //Tính hog và lưu vào cuối vector
i++;
}
cout << "Complete.." << i << " image" << endl;
return input;
}

2.1.5 Cài đặt thuật toán hồi qui đa tuyến tính(Multiple linear regression) để tìm
mô hình dự toán BMI của một khuôn mặt từ ảnh
Bước quan trọng trong việc ước lượng đó chính là xác định chỉ số của phương trình
tuyến tính. Theo như công thức = (XT.X)-1.XT.Y (1. 3) ta cần xác
định ma trậnω. Có thể có nhiều cách: tính trực tiếp, sử dụng thư viện của bên thứ ba,
dựa vào gradient... Để thuận tiện cho việc tính toán, chúng em tạo class để thực hiện và
gắn vào thư viện “Mlr.h”. Kí hiệu ma trận ω là B.

// Tính hàm chi phí đo sai số bình phương trung bình gốc giữa các giá trị dự đoán
(trước)(X*B) và các giá trị thực (Y) tương úng
double Mlr::cost_fuction(vector<vector<double> > X,vector<double>
Y,vector<double> B){
double loss = 0;
int n = 2 * rows;
for (int i = 0; i < rows; i++) {
double temp = 0;
for (int j = 0; j < colums; j++) {// X(i)*B
temp += X[i][j] * B[j];
}
loss += (Y[i] - temp) * (Y[i] - temp);// tổng {(Y(i) - X(i)*B)^2}
}
return loss / n ;// cost fuction
}
//cập nhật các hệ số, dựa trên đạo hàm theo từng biến của hàm mất mát khi thử
nghiệm trước đó
void Mlr::update(vector<vector<double> > X, vector<double> Y, vector<double>

17
Báo cáo bài tập lớn NNLT Nhóm 6
&B,double learning_rate){
vector<double> B_temp;
for (int i = 0; i < rows; i++) {
double temp = 0;
for (int j = 0; j < colums; j++) {//X(i)*B
temp += X[i][j] * B[j];
}
B_temp.push_back(temp - Y[i]); //X(i)* B - Y(i)
}
for (int i = 0; i < colums; i++) {
double temp1 = 0;
for (int j = 0; j < rows; j++) {
temp1 += B_temp[j] * X[j][i];//tổng {(X(i)*B - Y(i)]*X(i)[j]}
}
B[i] -= learning_rate * (temp1 / rows);//learning rate: tốc độ học
}
}
//Tính hàm chi phí và cập nhật các hệ số sau “inter” lần lặp(khi độ lớn hàm cost
fuction đủ nhỏ)
vector<double> Mlr::train(vector<vector<double> > X, vector<double> Y,
vector<double>& B, double learning_rate, int inter) {
vector<double> cost_hist;
for (int i = 0; i < inter; i++) {
update(X, Y, B, learning_rate);
cost_hist.push_back(cost_fuction(X, Y, B));
cout << cost_fuction(X, Y, B) << endl; // in ra giá trị hàm mất mát
}
return cost_hist; // trả về vector lưu các giá trị hàm mất mát}
Sau khi xác định được hệ số (ma trận B), ta lưu các giá trị của B vào file text và
tiến hành ước lượng. Biến “inter” chính là số lần lặp lại để xác định hàm mất mát nhỏ
nhất, nhưng ảnh hưởng tới tốc độ hay thời gian chạy chương trình (1000 lần mất gần
2’, 10000 lần mất tầm 7’).

//Lưu B
template<typename T>
void set_bias(string name, vector<T> B) {//name: đường dẫn lưu B
ofstream bias(name); // mở file
bias << B.size() << " ";// lưu kích thước của B
for (int i = 0; i < B.size(); i++) {

18
Báo cáo bài tập lớn NNLT Nhóm 6
bias << B[i] << " ";// lưu từng phần tử của B
}
bias.close();
}
//Ước lượng BMI
//Đầu vào: value:
//B: ma trận hệ số của hàm Y = X*B
//size: size của B
template<typename T>
T predic(vector<T> value, vector<T> B, size_t size) {
T y = 0;
for (int i = 0; i < size; i++) {
y += (T)(value[i] * B[i]);
}
return y;
}

2.1.6 . Chương trình tính toán


Chúng em sử dụng thư viện “loadImage.h” tự tạo để đọc và hiển thị ảnh, tính HOG, lưu,
lấy vector tính toán, lớp “Mlr.h” để tìm mô hình dự toán BMI của một khuôn mặt từ ảnh

#include<iostream>
#include<fstream>
#include<vector>
#include"loadImage.h";
#include"Mlr.h";
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include<opencv2/objdetect.hpp>
#include<opencv2/opencv.hpp>
using namespace img;
using namespace std;
using namespace cv;
int main() {
//Tính ma trận B bằng thuật toán Gradient desent: Y = X*B
vector<vector<double> > X = readHOGImgs<double>("D:\\test1\\");

19
Báo cáo bài tập lớn NNLT Nhóm 6
// Tính ma trận X chứa giá trị biến đầu vào của ảnh trong CSDL(140 ảnh)
vector<double> Y = get_Y<double>("D:/BMI/",Y, 7);// Lấy giá trị BMI
Mlr b1(X, Y, 3781, 20);// thiết lập ma trận X, Y
vector<double> B = b1.setB_zeros();// thiết lập ma trận B
vector<double> cost = b1.train(X, Y, B, 0.001, 1000);
set_bias("D:/test/B_1000_nn.txt", B);// lưu B vào text}

2.1.7 Thực hiện đánh giá với tối thiểu 10 người mới không có trong CSDL đã thu,
và đánh giá sai số ước lượng
Với dữ liệu vào của 10 người ta sẽ xác định được chỉ số BMI tương ứng và từ đấy
đánh giá ước lượng sai số. Đây là đánh giá đối với 1 người:

//uoc luong BMI tu 1 anh


Mat img1 = imread("D:/Test/Test/Lisa.jpg"); //đọc ảnh từ địa chỉ
//resize(img1, img1, Size()); đặt lại kích thước ảnh nếu cần
vector<Point> pos;
vector<Mat> img = facesDierction(img1, pos);//Xác định khuôn mặt
vector<double> B;
get_bias<double>("D:/test/B_1000_nn.txt", B);//Lấy ma trận hệ số multiple linear
regression được lưu sẵn
predic_image_BMI<double>(img, img1, B, pos); //Tính HOG, ước lượng BMI và gắn
lên ảnh
imshow("Anh", img1); //Hiển thị ảnh có BMI
waitKey(0);
Tương tự ta sẽ đánh giá với 10 người và thu được BMI tương ứng, cùng với kết quả
thực tế, xác định chênh lệch trung bình của 10 người giữ BMI ước lượng và BMI thực
tế ta sẽ thu được kết quả của sai số.

2.2 Kết quả và nhận xét


Sau khi thực hiện chương trình xong ta thu được kết quả BMI của 10 người sau khi
ước lượng và từ đó cũng tính được giá trị sai số.

20
Báo cáo bài tập lớn NNLT Nhóm 6

Hình 2. 1. Kết quả ước lượng

Hình 2. 1. Kết quả ước lượng là kết quả của ước lượng BMI với 2 người không có
trên cơ sở dữ liệu. Trên mỗi ảnh có nhận diện khuôn mặt và tính chỉ số BMI của khuôn
mặt vừa nhận diện. Chỉ số BMI được ghi lên tương ứng. Đây là ước lượng dựa vào
linaer regression và có giá trị sai số nhất định.

Giá trị sai số ta thu được là: 1.46384556.

Mặc dù chương trình của nhóm em đã chạy và ước lượng BMI từ mặt người,
Nhưng từ giá trị sai số ta thấy, tuy đây là ước lượng nên vẫn còn sai số nhưng sai số
khá nhiều và chưa hẳn tối ưu bài toán. Để chính xác hơn, ta phải sử dụng nhiều hơn
vector biểu diễn ảnh và kĩ thuật machine learning cần được nâng cao hơn. Và dự án
này vẫn có rất nhiều hướng có thể phát triển và ứng dụng vào y học hay cuộc sống
hàng ngày của chúng ta để có thể có một cơ thể khỏe mạnh nhất.

KẾT LUẬN

Thông qua đề tài này: “Ước lượng BMI của người dựa trên ảnh khuôn mặt” chúng
em đã tìm hiểu thêm về những kỹ năng chuyên môn (sử dụng thông thạo hơn ngôn ngữ
lập trinh, sử dụng thư viện OpenCV, tạo thư viện, xử lí ảnh,..) cũng như kỹ năng mềm

21
Báo cáo bài tập lớn NNLT Nhóm 6
(kỹ năng giao tiếp, kỹ năng truyền đạt, kỹ năng làm việc nhóm...). Nhóm em cảm ơn cô
Trần Thị Thanh Hải đã tạo điều kiện cho chúng em làm đề tài này. Cách làm và báo cáo
có thể có nhiều điều thiếu sót mong cô có thể phản hồi lại với chúng em đê lần làm bài
lần sau của chúng em tốt hơn.

Chúng em xin cảm ơn!

PHỤ LỤC

TÀI LIỆU THAM KHẢO


1. Jiang, Min, Guodong Guo, and Guowang Mu. "Visual BMI estimation from
face images using a label distribution based method." Computer Vision and
Image Understanding (2020): 102985

2. https://machinelearningcoban.com/2016/12/28/linearregression/

3. https://www.programmersought.com/article/54454971788/

22

You might also like