CHƯƠNG 4 THI CÔNG HỆ THỐNG
4.1 LƯU ĐỒ GIẢI THUẬT
4.1.1 Ảnh từ camera
Ban đầu hệ thống sẽ nhận ảnh đầu vào từ camera và đọc ảnh với câu lệnh: image = cv2.imread('imange.jpg').
Hình 4.2. Ảnh gốc lấy từ camera 4.1.2. Chuyển ảnh gốc sang ảnh xám 4.1.2. Chuyển ảnh gốc sang ảnh xám
Tiếp theo nhóm tiến hành xử lý ảnh bằng cách chuyển ảnh gốc sang ảnh xám với câu lệnh trong OpenCV: grayImage = cv2.cvtColor (image,
cv2.COLOR_BGR2GRAY).
4.1.3. Phát hiện khuôn mặt [11]
Để tìm khuôn mặt trong hình ảnh ta cần chuyển ảnh màu thành ảnh xám. Sau đónhìn vào mỗi pixel đơn lẻ và các điểm xung quanh nó.
Mục tiêu là tìm ra được độ tối của điểm ảnh hiện tại so với các điểm ảnh xung quanh. Sau đó vẽ một mũi tên chỉ ra hướng mà hình ảnh trở nên tối hơn.
Lặp lại quá trình đó cho mỗi pixel đơn trong ảnh, quá trình sẽ kết thúc với mỗi pixel được thay thế bằng một mũi tên. Những mũi tên này được gọi là gradients và chúng thể hiện hướng từ sáng đến tối trên toàn bộ hình ảnh.
Lý do để thay thế các điểm ảnh bằng các gradient là nếu phân tích pixel trực tiếp ảnh thật sự tối và thật sự sáng của cùng một người sẽ có các giá trị pixel khác nhau. Nhưng khi xem xét về hướng thay đổi độ sáng thì khi kết thúc quá trình ảnh thậtsự sáng và thật sự tối sẽ cùng được diễn tả chính xác.
Việc lưu trữ gradient cho mỗi pixel sẽ cho quá nhiều chi tiết nên tốt hơn là chỉ cần nhìn thấy hướng cơ bản của ánh sáng hay bóng tối ở mức cao hơn để nhìn thấy các mẫu cơ bản của hình ảnh. Để thực hiện việc này, thực hiện chia nhỏ hình ảnh thành những ô vuông nhỏ kích thước 16x16 pixel. Trong mỗi hình vuông đó, thực hiện đếm gradient trong mỗi hướng chính (bao nhiêu điểm lên, điểm lên phải, điểm lên trái, điểm xuống…). Sau đó thay thế hình vuông đó trong hình ảnh bằng hướng mũi tên mạnh nhất. Kết quả cuối cùng là biến hình ảnh ban đầu thành một biểu diễn đơn giảnđể nắm bắt cấu trúc cơ bản của khuôn mặt một cách đơn giản.
Để phát hiện mặt người với các đặc trưng HOG, thực hiện tìm một phần của hình ảnh trong giống nhất với một mẫu HOG đã biết được trích xuất từ một loạt khuôn mặt đã được huấn luyện, chúng tôi tiến hành các bước sau:
Bước 1: Chuẩn bị P mẫu là ảnh mặt người và trích xuất các vector đặc trưng HOG
từcác bức ảnh này.
Bước 2: Chuẩn bị N mẫu không phải ảnh mặt người (N rất lớn so với P) và trích
Bước 3: Sử dụng một bộ phân loại SVM tuyến tính để học các vector của các mẫu
tích cực (là ảnh mặt người) và tiêu cực (các ảnh không phải mặt người) đã chuẩn bị.
Bước 4: Đối với mỗi bức ảnh trong bộ ảnh tiêu cực, sử dụng một cửa sổ trượt di
chuyển đi qua tất cả các vị trí có thể của ảnh vào. Tại mỗi vị trí của cửa sổ trượt tính vector HOG của cửa sổ và đưa vào bộ phân lớp. Nếu bộ phân lớp sai một cửa sổ là ảnh mặt thì ghi lại vector tương ứng cùng với xác xuất phân lớp.
Bước 5: Lấy các mẫu nhận dạng sai ở bước 4 và sắp xếp chúng theo mức xác xuất
nhận dạng sai và cho bộ phân lớp học lại sử dụng các mẫu sai này.
Bước 6: Áp dụng bộ phân lớp đã được học lại với các ảnh cần phát hiện mặt người
Để tìm khuôn mặt trong ảnh nhóm đã dựa vào đặc trưng Haar like kết hợp với Adaboost được cài sẵn trong bộ thư viện OpenCV. Để sử dụng phương thức này trong OpenCV nhóm đã sử dụng hàm detectMultiScale trong ảnh xám vừa được chuyển với các tham số scaleFactor =1.1 và minNeighbors = 3 bằng bộ phân lớp faceCascade. Hàm này thuộc lớp CascadeClassifier (lớp phục vụ tìm kiếm đối tượng của OpenCV).
scaleFactor là tỉ lệ tăng kích thước của khung cửa sổ tìm kiếm. Khi scaleFactor =1.1 thì sau khi quét hết bức ảnh 1 lần, khung cửa sổ tăng kích thướclên 10% và thực hiện lần quét tiếp theo. Tham số này ảnh hưởng tới tốc độ xử lý vs độ tin cậy của chương trình. Nếu để tham số này quá lớn thì tốc độ chương sẽ tăng lên do số lần quét giảm đi, tuy nhiên có thể chương trình có thể bỏ qua không phát hiện được một số khuôn mặt có kích thước nằm giữa 2 khung cửa sổ liên tiếp do độ tăng kích thước khung quá lớn. Nếu để tham số này quá thấp thì chương trình có thể không bỏ sót bất kì khuôn mặt nào nhưng chương trình sẽ tốn nhiều thời gian hơn vì tăng số lần quét lên.
minNeighbors là giá trị tối thiểu số hình chữ nhật lận cận được gộp lại sau khi
quá trình quét đã xong.
4.1.4 Vẽ hình chữ nhật xung quanh khuôn mặt
Hàm detectMultiScale sau khi tìm kiếm xong sẽ trả về bộ gái trị gồm tọa độ gốc của khung hình chứa khuôn mặt x, y; chiều dài, chiều rộng của khung w, h. Các
giá trị này nằm trong mảng faces. Cấu trúc for…in sẽ duyệt qua toàn bộ giá trị này, mỗi bộ giá trị ta dùng hàm rectangle để vẽ 1 hình chữ nhật lên ảnh ban đầu với tọa độ 2 điểm trái trên và phải dưới: (x,y), (x+w, y+h). Thông số (0,255,0) là màu vẽ của khung hình chữ nhật.
Hình 4.4. Ảnh được vẽ hình chữ nhật lên khuôn mặt. 4.1.5. Đếm số lượng khuôn mặt 4.1.5. Đếm số lượng khuôn mặt
Sau khi vẽ hình chữ nhật xung quanh khuôn mặt xong, nhóm gọi phương thức
shape sẽ được trả về kích thước của khuôn mặt bao gồm 1 ma trận có N hàng và 4
cột. Trong đó, N là số lượng khuôn mặt được phát hiện trong ảnh và 4 là kích thước của hình chữ nhật của mỗi mặt.
4.1.6. Xuất kết quả ra màng hình
Dùng hàm cv2.imshow('Ket qua', image) để hiển thị ảnh đã vẽ xong lên 1
cửa sổ windown có tên là Ket qua.
Hình 4.5. Kết quả được xuất ra cửa sổ windown
4.2 Kết quả
Hình 4.7. Kết quả sau khi chạy chương trình
Hình 4.7 là kết quả của quá trình đếm số lượng người trong ảnh. Trên hình ảnh, chúng ta có thể thấy rằng những khuôn mặt xuất hiện trong ảnh đều được vẽ hình chữ nhật. Sau khi được xử lý và đếm số lượng kết quả được xuất ra trên màng hình.
Chương 5. KẾT QUẢ_NHẬN XÉT_ĐÁNH GIÁ
Nhóm bắt đầu nhận đề tài “Đếm số lượng người trong ảnh sử dụng kit
Raspberry Pi” từ ngày 26/08/2019. Bắt đầu nghiên cứu và thực hiện đề tài trong vòng
17 tuần để hoàn thành hệ thống. Trong quá trình nghiên cứu và thực hành nhóm đã học và rút ra được nhiều kinh nghiệm như: biết cách tìm hiểu nghiên cứu về một vấn đề, hiểu và biết sử dụng LCD, chuẩn truyền I2C. Biết thêm về tính năng của Raspberry Pi, cách cài đặt kết nối với các Module và hiểu thêm về ngôn ngữ Python.
Trong quá trình nhóm nghiên cứu đã thu được rất nhiều kết quả để chứng minh cho những cơ sở lý thuyết, những tính toán thiết kế và thi công của mình đi đúng hướng. Kết quả thực hiện nhóm đã hoàn thành được để tài. Bây giờ hệ thống có thể đếm được số lượng người trong hình. Thời gian đáp ứng để thực hiện đếm của hệ thống trong một lần đếm là khoảng 10 giây. Hệ thống dễ dàng sử dụng và an toàn.
5.1. KẾT QUẢ
Hình 5.1. Kết quả chương trình
Hình 5.1 là kết quả của chương trình đếm số lượng người trong ảnh. Trong quá trình tìm kiếm khuôn mặt chương trình sẽ tìm được nhiều những khung hình chữ nhật chứa khuôn mặt cho dù đó chỉ là một khuôn mặt và có những trường trường hợp
Hình 5.2. Kết quả chương trình đếm nhầm số lượng
Hình 5.2 chương trình đã nhận diện nhằm túi áo của bạn nam sinh là khuôn mặt (bạn nam thứ 2 từ trái sang phải và từ trên xuống dưới) dẫn đến kết quả đếm sai so với số lượng người thực tế có trong ảnh.
Nếu ta để tham số minNeighbor = 0 cho hàm tìm kiếm khuôn mặt, tức là để
nguyên những gì tìm được sau khi quét thì sẽ có kết quả như sau:
Kết quả đếm số lượng người trong trường hợp này lớn hơn rất nhiều so với kết quả thực tế (thực tế trong ảnh chỉ có 11 người nhưng chương trình xuất ra kết quả là 300 người).
Từ kết quả của hình 5.3 cho ta thấy tham số này sẽ gộp lại những khung hình chữ nhật chứa cùng 1 khuôn mặt để chỉ cho ra 1 hình chữ nhật cho 1 khuôn mặt. Đồng thời nó sẽ loại bỏ đi những kết quả sai vì những kết quả chỉ cho ra 1 khung hình chữ nhật con kết quả đúng thì có nhiều khung hình lân cận bao lấy.
Hình 5.4. Kết quả đếm sai khi minNeighbor = 5
Khi chọn tham số minNeighbor = 5 trong trường hợp hình 5.4 thì cho ra kết quả sai với số lượng thực tế. Vì những hình chữ nhật lân cận đã được gộp lại sau khi quá trình quét xong. Để cho kết quả đúng với thực tế ta cần chỉnh sửa tham số minNeighbor = 2 dựa vào chạy thử nghiệm chương trình nhiều lần.
Hình 5.5. Kết quả đếm đúng khi minNeighbor = 2
Hình 5.6. Kết quả đếm số lượng người trong ảnh với khuôn mặt nghiêng
Nhìn vào hình 5.5 ta có thể thấy hệ thống có thể đếm được số lượng khi khuôn mặt nghiêng hoặc bị che khuất khoảng 10-20% khuôn mặt. Để có kết quả đếm chính xác nhóm đã chạy thử nghiệm nhiều lần và đã chọn được thông số minNeighbor = 2 , scaleFactor = 1.3 để chương trình có thể quét nhiều lần hơn tránh bỏ sót. Tuy nhiên, thời gian xử lý sẽ chậm hơn so với những ảnh thông thường.
Hình 5.7. Kết quả đếm khi không có người trong ảnh
Hình 5.7 là kết quả đếm khi không có người xuất hiện trong ảnh. Bên cạnh đó nếu như trong ảnh có người mà không có xuất hiện khuôn mặt (người trong ảnh lúc này quay lưng lại hoặc khuôn mặt nghiêng hơn 30%).
5.2. Nhận xét
Để đánh giá, nhận xét một cách thực tế, nhóm đã chạy thử nghiệm trên những ảnh có mật độ người trong ảnh cao và thấp hoặc trong ảnh có khuôn mặt nghiêng. Kết quả được thể hiện ở bảng 5.1 và 5.2:
Bảng 5.1. Thống kê kết quả đếm số người trong ảnh khi khuôn mặt chính diện STT Số lượng thực tế Kết quả đếm từ hệ STT Số lượng thực tế Kết quả đếm từ hệ thống Sai số 1 1 1 0 2 4 4 0 3 5 5 0 4 8 8 0 5 10 10 0 6 15 15 0 7 23 21 2 8 27 28 1 9 30 28 2 10 39 38 1
Từ những hình ảnh kết quả chạy thử nghiệm và được thống kê trong bảng 5.1 cho thấy hệ thống khá ổn định, độ chính xác tương đối cao.
Bảng 5.2. Thống kê kết quả đếm số người trong ảnh khi khuôn mặt nghiêng STT Số lượng
thực tế
Số lượng đếm được Sai số
< =25% > 25% < =25% > 25% 1 1 1 0 0 1 2 3 3 1 0 2 3 6 5 9 1 3 4 8 8 5 0 3 5 10 10 6 0 4
Theo kết quả chạy thử nghiệm và thống kế trong bảng 5.2 cho thấy hệ thống đếm ổn định, sai số thấp có thể chấp nhận được khi khuôn mặt trong hình nghiêng nhỏ hơn
25%. Khi khuôn mặt trong hình nghiêng lớn hơn 25% hệ thống sẽ không nhận diện được khuôn mặt dẫn đến hệ thống đếm sai số lượng người có trong hình.
Tuy nhiên, nhóm vẫn chỉ dừng lại ở mức mô hình. Nếu như mô hình này khi được khai thác thì sẽ ứng dụng rất nhiều trong việc điểm danh trong lớp học hay chấm công trong công ty. Việc khai thác mô hình này trong thực tiễn thì phải tốn thêm nhiều thời gian và chi phí để thực hiện.
Chương 6. KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN
6.1 KẾT LUẬN
Mục tiêu chính của đề tài là đếm được số lượng người trong ảnh. Sau quá trình thực hiện thì hệ thống đã có thể đếm được số lượng người trong ảnh tương đối chính xác với sai số nhỏ khi trong ảnh có xuất hiện mặt người hoặc khi khuôn mặt nghiêng từ 10 – 25%.
Qua thời gian nghiên cứu và thực hiện thì nhóm chỉ dừng lại ở mức mô hình sản phẩm để thử nghiệm và không thể đếm với số lượng người trong ảnh khi mặt bị che khuất hoặc chỉ thấy từ đằng sau người đó. Mặc dù đã cố gắng nhưng do giới hạn về thời gian thực hiện và năng lực còn yếu nên nhóm không thể hoàn toàn khắc phục được hạn chế của sản phẩm.
Trong suốt quãng thời gian nghiên cứu đồ án, nhóm chúng em cũng đã học được khá nhiều điều như học được cách đương đầu với áp lực, cách nghiên cứu về một vấn đề, khả năng phân chia công việc và lên kế hoạch, nhất là đức tính kiên trì khi lập trình bị lỗi. Quả thực, môi trường Đại Học Sư Phạm Kỹ Thuật là rất tốt trong việc rèn luyện nhân cách, phương pháp học tập, kinh nghiệm sống của chúng mỗi người. Những điều đó làm nền tảng cho việc phát triển của mỗi cá nhân trong nhóm sau này.
6.2 HƯỚNG PHÁT TRIỂN
Dựa vào những kiến thức được tham khảo và học hỏi. Nhóm nghiên cứu nghĩ rằng đề tài này có thể phát triển và mở rộng thêm ở một số khía cạnh sau:
Có thể đếm được đối tượng khi không có xuất hiện khuôn mặt trong ảnh hoặc khuôn mặt nghiêng hơn 30%.
Nghiên cứu cải tiến những giải thuật phát hiện, nhận diện hiệu quả, chính xác và tốiưu hơn.
TÀI LIỆU THAM KHẢO
[1] Nguyễn Thanh Hải, “Giáo Trình: Xử Lý Ảnh”, Xuất bản Đại Học Quốc Gia TP.HCM, 2013.
[2] Trần Hải Đăng, “Giao tiếp I2C với nhiều module”, 2016.
[3] Đào Văn Hậu, “Nhận diện khuôn mặt với OpenCV trên Raspberry Pi”, 2019.
[4] “Raspbian Stretch: Install OpenCV 3 + Python on your Raspberry Pi” https://www.pyimagesearch.com/2017/09/04/raspbian-stretch-install-opencv-3- python-on-your-raspberry-pi/
[5] Raspberry Pi Việt Nam, “Raspberry Pi là gì? Giới thiệu về Raspberry Pi”, 2014.
https://raspberrypi.vn/tin-tuc/raspberry-pi-la-gi-gioi-thieu-ve-raspberry-pi-261.pi
[6] Nitin Patil, “How to install OpenCV on Raspberry Pi and do Face Tracking”, 2017. [7] Antepher, “Python OpenCV: Face detection and counting”, 2017.
https://techtutorialsx.com/2017/05/02/python-opencv-face-detection-and-counting/
[8] Minh Nguyễn, “Xử lý ảnh - OpenCV resize, crop và padding hình ảnh (code Python và C++) ”, 2018.
[9] Stack Overflow, “ Count the number of objects OpenCV – Python”, 2017.
https://stackoverflow.com/questions/39261378/count-the-number-of-objects-opencv- python
[10] Team Việt Dev, “OpenCV là gi, ứng dụng trong thế giới thực”, 2018.
[11] Võ Lê Huy, “OpenCV với Python Trong Ứng Dụng Phát Hiện Khuôn Mặt Trong Bức Ảnh”, 2018.
[12] Nông Văn Tâm và Trần Thị Mỹ Khiêm, “Ứng dụng xử lý ảnh vào việc phát hiện ngủ gật dùng Kit Raspberry”, 2019.
[13] Võ Sĩ Nguyên, “Thiết kế và thi công hệ thống đếm số lượng cá giống”, 2019. [13] Dương Nguyễn, “Python là gì? Tại sao nên chọn python?”, 2019.
https://quantrimang.com/python-la-gi-tai-sao-nen-chon-python-140518
[14] Tuấn Nguyễn, “Hiển thị dữ liệu từ Raspberry Pi lên LCD16x2 qua mạch chuyển tiếp LCM1602”, 2017.
[15] “Adaboost - Haar Features - Face detection” [Online]. Available: http://www.ieev.org/2010/03/adaboost-haar-features-face-detection_22.html
PHỤ LỤC
#khai bao thu vien import numpy as np import cv2
import smbus import time
I2C_ADDR = 0x3f # dung lenh sudo i2cdetect -y 1 ban se thay dia chi cua module lcd la 0x3f
LCD_WIDTH = 16 # so ki tu tren 1 dong
LCD_CHR = 1 # Gui ki tu LCD_CMD = 0 # Gui lenh
LCD_LINE_1 = 0x80 # dia chi RAM dong 1 LCD_LINE_2 = 0xC0 # dia chi RAM dong 2
LCD_BACKLIGHT = 0x08 # On #LCD_BACKLIGHT = 0x00 # Off
ENABLE = 0b00000100 # Enable bit
# delay
E_PULSE = 0.0005 E_DELAY = 0.0005
#bus = smbus.SMBus(0) # Pi Rev 1 ban su dung dong nay bus = smbus.SMBus(1) # Pi Rev 2 ban su dung dong nay
def lcd_init(): # Initialise display
lcd_byte(0x33,LCD_CMD) # che do 8 bits
lcd_byte(0x32,LCD_CMD) # che do 8 bits lan nua
lcd_byte(0x06,LCD_CMD) # che do 4 bits, LCD hien thi 2 dong lcd_byte(0x0C,LCD_CMD) # xoa hien thi
lcd_byte(0x28,LCD_CMD) # con tro tu dong di chuyen
lcd_byte(0x01,LCD_CMD) # bat hien thi, tat con tro nhap nhay time.sleep(E_DELAY)