123
Hoạt động với độ chính xác thấp nếu tầm quan sát của camera đến người lái vượt q 60cm như hình 6.8. Độ chính xác của việc thu nhận thơng tin hình ảnh vào để xử lý sẽ bị nhiễu, gây khó khăn cho việc xử lý, dễ đưa ra kết quả sai lệch cho việc cảnh báo.
6.5 Thuận lợi và khó khăn khi thực hiện đề tài 6.5.1 Thuận lợi 6.5.1 Thuận lợi
Trong quá trình thực hiện được sự hướng dẫn tận tình của Thầy TS. Nguyễn Phụ Thượng Lưu hỗ trợ nhóm về những vấn đề khó giải và chỉnh sửa những lỗi thiếu sót trong q trình thực hiện đồ án.
Đề tài chúng em dựa trên nền tảng của các thiết bị có sẵn trên thị trường nên tài liệu tham khảo có nhiều.
Các phụ tùng có sẵn trên thị trường.
Các thành viên trong nhóm đều có khả năng tìm kiếm và sàng lọc tài liệu nên hoàn thành đồ án đúng thời gian.
6.5.2 Khó khăn
Trong lúc thực hiện đồ án thì tình hình dịch Covid 19 diễn biến phức tạp nên ảnh hưởng nhiều đến việc tập trung nhóm để thảo luận phát triển và thi công đề tài, việc mua phụ tùng cho mơ hình rất khó khăn. Do đó mơ hình hồn thành khơng được tồn vẹn chỉnh chu như dự kiến ban đầu.
Các thuật tốn lập trình cho ngơn ngữ Python và ứng dụng OpenCV cần địi hỏi kỹ năng chun mơn cao, do đó trong lúc thực hiện đồ án gây nhiều khó khăn cho cả nhóm nên sản phẩm của nhóm tạo ra có những sai lệch so với thực tế.
124
6.6 Khả năng phát triển đề tài
Có thể nói vấn đề an tồn khi lái xe là một trong những điều cấp thiết lúc này. Do đó đề tài của nhóm em có khả năng tiếp cận được với thị trường do giá thành thấp, kích thước nhỏ gọn, thích hợp với mọi dịng xe trên thị trường.
Ngồi ra, với việc sử dụng mạch xử lý Raspberry như 1 máy tính thu nhỏ. Ta có thể phát triển đề tài bằng cách tích hợp nhiều ứng dụng khác nhau.
Một khả năng phát triển đề tài như nâng cấp thêm màn hình cảm ứng, kết nối điều khiển với mạch xử lý. Hoạt động quan sát theo dõi hành vi mệt mỏi của người lái xe, đồng thời phát triển mạch như 1 màn hình cảm ứng có thể bật được cái ứng dụng tiện lợi như, nghe nhạc trực tuyến, map chỉ đường...
Hoặc nhận diện vạch kẻ đường để cảnh báo người lái xe đi đúng làn đường của mình...
125
TÀI LIỆU THAM KHẢO
[1]. Lê Thế Hải, Lê Thanh Hòa, “Nhận diện chớp mắt và cảnh báo buồn ngủ khi lái xe trên nền windows và android”, Khoa Điện - Điện tử Viễn Thông, TP. Hồ Chí Minh, 1/2012.
[2]. Thái Thị Hịa Vân, “Nghiên cứu tình trạng buồn ngủ của người lái xe dựa trên nhận dạng cử chỉ khuôn mặt”, Trung tâm Thông tin-Học liệu, Đại học Đà Nẵng, 2017. [3]. Nông Quang Huy, “Nghiên cứu thiết kế thiết bị chống ngủ gật cho lái xe ô tô”, Viện Điện Tử - Viễn Thông, Đại học BKHN, Hà Nội, 2013.
[4]. Th.S Nguyễn Duy Linh, Th.S Trần Cơng Trung, “Tìm hiểu một số hệ thống cảnh báo lái xe ngủ gật (drowsy driver alert system) và đề xuất phương pháp xây dựng ứng dụng với thư viện mã nguồn mở OpenCV”, Tạp chí thơng tin khoa học & Cơng nghệ Quảng Bình, Số 4/2019.
[5]. Gérard Blanchet, Maurice Charbit, “Digital Signal and Image Processing
using MATLAB®”, United States, 2006 by ISTE Ltd.
[6]. Rafael C.Gonzalez, Richard E.Woods, Steven L.Eddins, “Digital Image
Processing using MATLAB®”, United States, 2004 by Pearson Education, Inc. [7]. Thông tư số 17/2010/TT-BGTVT ngày 05/07/2010 ban hành Quy chuẩn kỹ thuật Quốc gia về báo hiệu đường bộ.
[8]. PGS.TS Nguyễn Quang Hoan, “Giáo trình xử lý ảnh”, Học Viện Bưu Chính
Viễn Thơng, Hà Nội, 24/07/2014.
[9]. Chongke Zhong, Jingyuan Yang, Tan Xu, et al, “Serum matrix
metalloproteinas-9 levels and prognosis of acute ischemic stroke”, 26/7/2017, [Online] Available: https://www.neurology.org/.
[10]. Tristan Hearn, “using only their own webcam”, 27/6/2017, [Online] Available:
126
[11]. American Thoracic Society, [Online] Available:
https://www.thoracic.org/patients/patient-resources/resources/sleepiness-and- driving.pdf.
[12]. MLAB, “Raspberry Pi 4 Model B’’07/11/2013, [Online] Available:
https://pivietnam.com.vn/raspberry-pi-4-model-b-pivietnam-com-vn.html
[13]. Hiền Nguyễn, “Python là gì? Đặc điểm của ngơn ngữ lập trình Python”,
27/11/2019. [Online] Available: https://toidayhoc.com/lap-trinh/python-la-gi-dac- diem-cua-ngon-ngu-lap-trinh-python/
[14]. Phạm Trung, “Công nghệ AI giúp cảnh báo buồn ngủ khi lái xe”, 18/12/2019, [Online] Available: https://vnexpress.net/cong-nghe-ai-giup-canh-bao-buon-ngu- khi-lai-xe-4029264.html.
[15]. Tin Học Sóc Trăng, “Tổng quang về OpenCV”, 17/02/2017, [Online] Available: https://www.tinhocsoctrang.com/2017/02/tong-quan-ve-opencv.html
[16]. Công ty TNHH CARCAM Việt Nam, [Online] Available:
https://carcam.vn/thiet-bi-canh-bao-buon-ngu-khi-lai-xe-carcam-carcam-fatigue- warning-system-pd105571.html
127
PHỤ LỤC
PHỤ LỤC 1. CHƯƠNG TRÌNH XỬ LÝ ẢNH TRONG NHẬN DIỆN ĐIỀU KHIỂN Ô TÔ
import numpy as np import time
import pylab
from keras import backend as K import imutils
from keras.models import load_model import keras
import requests
from scipy.spatial import distance as dist from imutils import face_utils
import dlib
import cv2, os, sys import face_recognition import tensorflow as tf
import RPi.GPIO as GPIO ## Import GPIO library
from pygame import mixer # Load the popular external library from datetime import datetime
facial_landmarks_predictor = '68_face_landmarks_predictor.dat' sleep_predictor = dlib.shape_predictor(facial_landmarks_predictor) # Load model predict xem mat nguoi dang dong hay mo
model_hdf5 = load_model('weights.149-0.01.hdf5')
#message: Thong diep hien len man hinh // Thơng điệp hiện lên màn hình #waring_time: Thoi gian canh bao // Thời gian cảnh báo
128 #sound_name: Am Thanh canh bao
waring_config = [ [#=== Th1 { #Lan 1
"message": "Nguoi lai xe nham mat hon 3 giay", "waring_time": 2,
"on_type": 0,
"sound_name": 'sound/th1_1.mp3' },{ #Lan 2
"message": "Nguoi lai xe nham mat hon 7 giay", "waring_time": 2,
"on_type": 0,
"sound_name": 'sound/th1_2.mp3' },{ #Lan 3
"message": "Nguoi lai xe nham mat hon 12 giay", "waring_time": 4, "on_type": 'relay_1', "sound_name": 'sound/th1_3.mp3' } ], [#=== Th2 { #Lan 1
"message": "Khong tim thay khuon mat trong 3s", "waring_time": 2,
"on_type": 0,
"sound_name": 'sound/th2_1.mp3' },{ #Lan 2
"message": "Khong tim thay khuon mat trong 7s", "waring_time": 2,
129 "on_type": 0,
"sound_name": 'sound/th2_2.mp3' },{ #Lan 3
"message": "Khong tim thay khuon mat vuot qua 12s", "waring_time": 4, "on_type": 'relay_1', "sound_name": 'sound/th2_3.mp3' } ], [#=== Th3 { #Lan 1
"message": "Nhip tim vuot qua nguong 50-100 trong 3s", "waring_time": 2,
"on_type": 0,
"sound_name": 'sound/th3_1.mp3' },{ #Lan 2
"message": "Nhip tim vuot qua nguong 50-100 trong 7s", "waring_time": 3,
"on_type": 0,
"sound_name": 'sound/th3_2.mp3' },{ #Lan 3
"message": "Nhip tim vuot qua nguong 50-100 qua 12s", "waring_time": 4, "on_type": 'relay_1', "sound_name": 'sound/th3_3.mp3' } ], [#=== Th4 { #Lan 1
130 "message": "Th4.1", "waring_time": 1, "on_type": 0, "sound_name": 'sound/th4_1.mp3' },{ #Lan 2 "message": "Th4.2", "waring_time": 3, "on_type": 0, "sound_name": 'sound/th4_2.mp3' },{ #Lan 3 "message": "Th4.3", "waring_time": 4, "on_type": 'relay_1', "sound_name": 'sound/th4_3.mp3' } ], ] def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """ try:
# PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
131 class FacialLandMarksPosition: left_eye_start_index, left_eye_end_index = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"] right_eye_start_index, right_eye_end_index = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"] def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """ try:
# PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
class findFaceGetPulse(object):
def __init__(self, bpm_limits=[], data_spike_limit=250, face_detector_smoothness=10): self.frame_in = np.zeros((10, 10)) self.frame_out = np.zeros((10, 10)) self.fps = 0 self.buffer_size = 250 #self.window = np.hamming(self.buffer_size) self.data_buffer = []
132 self.times = [] self.ttimes = [] self.samples = [] self.freqs = [] self.fft = [] self.slices = [[0]] self.t0 = time.time() self.bpms = [] self.bpm = 0 dpath = resource_path("haarcascade_frontalface_alt.xml") if not os.path.exists(dpath):
print("Cascade file not present!")
self.face_cascade = cv2.CascadeClassifier(dpath) self.face_rect = [1, 1, 2, 2] self.last_center = np.array([0, 0]) self.last_wh = np.array([0, 0]) self.output_dim = 13 self.trained = False self.idx = 1 self.find_faces = True self.find_face = False #sleep self.sleep_scale = 0.5 self.count_eye_close = 0 self.curr_state = 0 self.curr_state_list = [] GPIO.setmode(GPIO.BCM)
133 GPIO.setup(21, GPIO.OUT) mixer.init() self.before_time = datetime.now() self.before_time_1 = datetime.now() self.before_time_2 = datetime.now() self.before_time_3 = datetime.now() self.message_warning = False self.curr_warning_type = 0 self.curr_warning_time = 0 self.waring_time = 0 self.estimate = 5 def find_faces_toggle(self):
self.find_faces = not self.find_faces return self.find_faces
def get_faces(self): return
def shift(self, detected): x, y, w, h = detected
center = np.array([x + 0.5 * w, y + 0.5 * h]) shift = np.linalg.norm(center - self.last_center)
self.last_center = center return shift
134 x, y, w, h = rect
cv2.rectangle(self.frame_out, (x, y), (x + w, y + h), col, 1)
def get_subface_coord(self, fh_x, fh_y, fh_w, fh_h): x, y, w, h = self.face_rect
return [int(x + w * fh_x - (w * fh_w / 2.0)), int(y + h * fh_y - (h * fh_h / 2.0)), int(w * fh_w),
int(h * fh_h)]
def get_subface_means(self, coord): x, y, w, h = coord subframe = self.frame_in[y:y + h, x:x + w, :] v1 = np.mean(subframe[:, :, 0]) v2 = np.mean(subframe[:, :, 1]) v3 = np.mean(subframe[:, :, 2]) return (v1 + v2 + v3) / 3. def train(self):
self.trained = not self.trained return self.trained def plot(self): data = np.array(self.data_buffer).T np.savetxt("data.dat", data) np.savetxt("times.dat", self.times) freqs = 60. * self.freqs
idx = np.where((freqs > 50) & (freqs < 180)) pylab.figure()
135 n = data.shape[0] for k in xrange(n): pylab.subplot(n, 1, k + 1) pylab.plot(self.times, data[k]) pylab.savefig("data.png") pylab.figure() for k in xrange(self.output_dim): pylab.subplot(self.output_dim, 1, k + 1) pylab.plot(self.times, self.pcadata[k]) pylab.savefig("data_pca.png") pylab.figure() for k in xrange(self.output_dim): pylab.subplot(self.output_dim, 1, k + 1) pylab.plot(freqs[idx], self.fft[k][idx]) pylab.savefig("data_fft.png") quit()
def run(self, cam):
self.times.append(time.time() - self.t0) self.frame_out = self.frame_in self.gray = cv2.equalizeHist(cv2.cvtColor(self.frame_in, cv2.COLOR_BGR2GRAY)) col = (100, 255, 100) if self.find_faces: detected = list(self.face_cascade.detectMultiScale(self.gray, scaleFactor=1.3, minNeighbors=4, minSize=(50, 50),
136
flags=cv2.CASCADE_SCALE_IMAGE)) if len(detected) > 0:
detected.sort(key=lambda a: a[-1] * a[-2])
if self.shift(detected[-1]) > 10: self.face_rect = detected[-1] if set(self.face_rect) == set([1, 1, 2, 2]): return forehead1 = self.get_subface_coord(0.5, 0.18, 0.25, 0.15) self.draw_rect(forehead1) vals = self.get_subface_means(forehead1) self.data_buffer.append(vals) L = len(self.data_buffer) if L > self.buffer_size: self.data_buffer = self.data_buffer[-self.buffer_size:] self.times = self.times[-self.buffer_size:] L = self.buffer_size processed = np.array(self.data_buffer) if len(self.times) > 0 and len(processed) > 0: while len(self.times) != len(processed): if len(self.times) > len(processed): self.times.pop()
else:
processed.pop() self.samples = processed
137 if L > 10:
self.output_dim = processed.shape[0]
self.fps = float(L) / (self.times[-1] - self.times[0])
even_times = np.linspace(self.times[0], self.times[-1], L) interpolated = np.interp(even_times, self.times, processed) interpolated = np.hamming(L) * interpolated
interpolated = interpolated - np.mean(interpolated) raw = np.fft.rfft(interpolated)
phase = np.angle(raw) self.fft = np.abs(raw)
arran_num = L / 2 + 1 < len(self.fft) and L / 2 + 1 or len(self.fft) self.freqs = float(self.fps) / L * np.arange(arran_num)
freqs = 60. * self.freqs
idx = np.where((freqs > 50) & (freqs < 180)) pruned = self.fft[idx] phase = phase[idx] if len(pruned): pfreq = freqs[idx] self.freqs = pfreq self.fft = pruned idx2 = np.argmax(pruned) t = (np.sin(phase[idx2]) + 1.) / 2. t = 0.9 * t + 0.1 alpha = t beta = 1 - t
138
self.bpm = self.freqs[idx2] + self.estimate self.idx += 1 x, y, w, h = self.get_subface_coord(0.5, 0.18, 0.25, 0.15) r = alpha * self.frame_in[y:y + h, x:x + w, 0] g = alpha * \ self.frame_in[y:y + h, x:x + w, 1] + \ beta * self.gray[y:y + h, x:x + w] b = alpha * self.frame_in[y:y + h, x:x + w, 2] self.frame_out[y:y + h, x:x + w] = cv2.merge([r,g,b]) x1, y1, w1, h1 = self.face_rect self.slices = [np.copy(self.frame_out[y1:y1 + h1, x1:x1 + w1, 1])] text_color = (50, 155, 50)
gap = (self.buffer_size - L) / self.fps self.bpms.append(self.bpm) self.ttimes.append(time.time()) if len(self.bpms) > 10: bpm = sum(self.bpms)/10 self.bpms.pop(0) cv2.putText(self.frame_out, "Bpm: %0.1f " %bpm, (10, 25), cv2.FONT_HERSHEY_PLAIN, 2, text_color)
text = "(estimate: %0.1f bpm)" % (self.bpm) tsize = 1
cv2.putText(self.frame_out, text,
(int(x - w / 2), int(y)), cv2.FONT_HERSHEY_PLAIN, tsize, text_color)
datetime_now = datetime.now()
delta_3 = datetime_now - self.before_time_3 if self.find_face: # tim ra khuon
139
if bpm >= 50 and bpm <= 100:#Nhip tim on dinh thi tat thong bao self.before_time_3 = datetime_now
if self.curr_warning_type == 3: self.curr_warning_time = 0 self.message_warning = False else: # Th3: Cảnh báo nhịp tim
if delta_3.seconds > 12: #Lan3: Nếu thời gian cảnh báo nhắc nhở ban đầu vượt quá 10 giây
if self.curr_warning_type == 3 and self.curr_warning_time != 3: self.turn_on_waring(3,3)
self.curr_warning_time = 0
elif delta_3.seconds >= 7:#Lan2: Khi nhịp tim vượt quá ngưỡng 50-100 bpm trong khoảng thời gian 5 giây
if self.curr_warning_type == 3 and self.curr_warning_time != 2: self.turn_on_waring(3,2)
elif delta_3.seconds >= 3:#Lan1: Khi nhịp tim vượt quá ngưỡng 50-100 bpm trong khoảng thời gian 3 giây
self.turn_on_waring(3,1) else:
if gap:
text = "(estimate: %0.1f bpm, wait %0.0f s)" % (self.bpm, gap) tsize = 1
cv2.putText(self.frame_out, text,
(int(x - w / 2), int(y)), cv2.FONT_HERSHEY_PLAIN, tsize, text_color)
else:
text = "(estimate: %0.1f bpm)" % (self.bpm) tsize = 1
140
(int(x - w / 2), int(y)), cv2.FONT_HERSHEY_PLAIN, tsize, text_color)
# ==== CODE sleep w
def predict_eye_state(self, model, image): # Resize anh ve 20x10
image = cv2.resize(image, (20, 10)) image = image.astype(dtype=np.float32)
# Chuyen thanh tensor
image_batch = np.reshape(image, (1, 10, 20, 1)) # Dua vao mang mobilenet de xem mat dong hay mo
image_batch = keras.applications.mobilenet.preprocess_input(image_batch)
return np.argmax(model.predict(image_batch)[0]) #buon ngu
def run_sleep(self, cam):
# Doc anh tu camera va chuyen thanh RGB
image = cv2.cvtColor(self.frame_in, cv2.COLOR_BGR2RGB)
# Resize anh con 50% kich thuoc goc
original_height, original_width = image.shape[:2]
resized_image = cv2.resize(image, (0, 0), fx=self.sleep_scale, fy=self.sleep_scale)
# Chuyen sang he mau LAB de lay thanh lan Lightness lab = cv2.cvtColor(resized_image, cv2.COLOR_BGR2LAB) l, _, _ = cv2.split(lab)
141 resized_height, resized_width = l.shape[:2]
height_ratio, width_ratio = original_height / resized_height, original_width / resized_width
# Tim kiem khuon mat bang HOG
face_locations = face_recognition.face_locations(l, model='hog')
# Neu tim thay it nhat 1 khuon mat if len(face_locations):
# Lay vi tri khuon mat
top, right, bottom, left = face_locations[0] x1, y1, x2, y2 = left, top, right, bottom x1 = int(x1 * width_ratio)
y1 = int(y1 * height_ratio) x2 = int(x2 * width_ratio) y2 = int(y2 * height_ratio) #self.find_faces = True # Trich xuat vi tri 2 mat
gray = cv2.cvtColor(self.frame_in, cv2.COLOR_BGR2GRAY)
shape = sleep_predictor(gray, dlib.rectangle(x1, y1, x2, y2)) face_landmarks = face_utils.shape_to_np(shape) left_eye_indices = face_landmarks[FacialLandMarksPosition.left_eye_start_index: FacialLandMarksPosition.left_eye_end_index] (x, y, w, h) = cv2.boundingRect(np.array([left_eye_indices])) left_eye = gray[y:y + h, x:x + w]
142 right_eye_indices = face_landmarks[FacialLandMarksPosition.right_eye_start_index: FacialLandMarksPosition.right_eye_end_index] (x, y, w, h) = cv2.boundingRect(np.array([right_eye_indices])) right_eye = gray[y:y + h, x:x + w]
# Dung mobilenet de xem tung mat la MO hay DONG
left_eye_open = 'yes' if self.predict_eye_state(model=model_hdf5, image=left_eye) else 'no'
right_eye_open = 'yes' if self.predict_eye_state(model=model_hdf5, image=right_eye) else 'no'
# Neu 2 mat dong thi hien thi mau do con khong thi mau xanh if left_eye_open == 'no' and right_eye_open == 'no':
cv2.rectangle(self.frame_out, (x1, y1), (x2, y2), (0, 0, 255), 2) # turn off view
self.curr_state_list += [1] self.count_eye_close +=1 else:
cv2.rectangle(self.frame_out, (x1, y1), (x2, y2), (0, 255, 0), 2) # turn off view
self.curr_state_list += [0] self.count_eye_close = 0
self.find_face = True # Đánh dấu: tìm ra khn mặt else:
self.find_face = False #Đánh dấu: khong tìm ra khn mặt datetime_now = datetime.now()
143 delta = datetime_now - self.before_time if delta.seconds >=1:
self.before_time = datetime_now
if len(self.curr_state_list) and sum(self.curr_state_list) / len(self.curr_state_list) >0.5: self.curr_state = 1 else: self.curr_state_list = [] self.curr_state = 0
if self.waring_time > 0: # Kiem tra thoi gian tat thong bao self.waring_time -=1
if self.waring_time == 0: self.turn_off_waring()
datetime_now = datetime.now() delta_1 = datetime_now - self.before_time_1
if self.find_face and delta_1.seconds >= 1:# Th1: tim ra khuon Dấu hiệu người lái xe nhắm mắt
if self.curr_state == 0: #mo mat thi tat thong bao self.before_time_1 = datetime_now
if self.curr_warning_type == 1:#Neu la truong hop 1 thi tat canh bao self.curr_warning_time = 0
self.message_warning = False #xoa thong diep tren man hinh else:
if delta_1.seconds >= 12: #Lan3: vượt quá 12 giây
if self.curr_warning_type == 1 and self.curr_warning_time != 3:#bo self.turn_on_waring(1,3)
144
if delta_1.seconds >= 7:#Lan2: Khi người lái xe nhắm mắt từ 7 giây trở lên
if self.curr_warning_type == 1 and self.curr_warning_time != 2: self.turn_on_waring(1,2)
else:
if delta_1.seconds >= 3:#Lan1: Dấu hiệu người lái xe nhắm mắt 3 giây trở lên
self.turn_on_waring(1,1) datetime_now = datetime.now()
delta_2 = datetime_now - self.before_time_2 if delta_2.seconds >= 1:#bo qua
if self.find_face: # tim ra khuon #Th2: Các trường hợp mất nhận diện người lái xe
self.before_time_2 = datetime_now #luu thoi gian hien tai
if self.curr_warning_type == 2: #Neu la truong hop 2 thi tat canh bao self.curr_warning_time = 0
self.message_warning = False #xoa thong diep tren man hinh else:
if delta_2.seconds > 12: # Nếu thời gian cảnh báo nhắc nhở ban đầu vượt quá 10 giây
if self.curr_warning_type == 2 and self.curr_warning_time != 3: self.turn_on_waring(2,3)
self.curr_warning_time = 0
elif delta_2.seconds >= 7: # Khi không nhận diện được khuôn mặt người lái xe trong 5 giây
if self.curr_warning_type == 2 and self.curr_warning_time != 2: self.turn_on_waring(2,2)
elif delta_2.seconds >= 3: # Khi không nhận diện được khuôn mặt người lái xe trong 3 giây
145 self.turn_on_waring(2,1)
def show_message_warning(self): #Hien Thong bao len
if self.message_warning: tsize = 1
text_color = (5, 5, 255)
cv2.putText(self.frame_out, self.message_warning, (100, 350), cv2.FONT_HERSHEY_PLAIN, tsize, text_color)
#Tat canh bao
def turn_off_waring(self): mixer.music.stop() GPIO.output(21, 0)
#Chay canh bao
def turn_on_waring(self, warning_type = 0, time = 1):
message = waring_config[warning_type - 1][time - 1].get('message',False) waring_time = waring_config[warning_type - 1][time -
1].get('waring_time',False)
on_type = waring_config[warning_type - 1][time - 1].get('on_type',False) sound_name = waring_config[warning_type - 1][time -
1].get('sound_name',False) self.curr_warning_type = warning_type if self.curr_warning_time != time: self.message_warning = message self.turn_off_waring() self.curr_warning_time = time self.waring_time = waring_time
146 #Bat Relay
if on_type == 'relay_1': GPIO.output(21, 1) elif on_type == 'relay_2': GPIO.output(21, 1) elif on_type == 'relay_3': GPIO.output(21, 1) #Bat am thanh theo ten if sound_name:
mixer.music.load(sound_name) mixer.music.play()
147
PHỤ LỤC 1.1 Trích xuất nhận diện khn mặt
image = cv2.resize(image, (20, 10)) // Thay đổi kích thước ảnh thô image = image.astype(dtype=np.float32)
image_batch = np.reshape(image, (1, 10, 20, 1))
image_batch = keras.applications.mobilenet.preprocess_input(image_batch) return np.argmax(model.predict(image_batch)[0]) // Chuyển dữ liệu vè hệ
Tensor.
def run_sleep(self, cam): // Để dự đoán các hành vi ta đặt tên hàm là
“run_sleep”.
image = cv2.cvtColor(self.frame_in, cv2.COLOR_BGR2RGB) // Chuyển đổi
sang hệ màu RGB.
original_height, original_width = image.shape[:2]
resized_image = cv2.resize(image, (0, 0), fx=self.sleep_scale, fy=self.sleep_scale)
lab = cv2.cvtColor(resized_image, cv2.COLOR_BGR2LAB) l, _, _ = cv2.split(lab)
resized_height, resized_width = l.shape[:2]
height_ratio, width_ratio = original_height / resized_height, original_width / resized_width // Chuyển sang hệ màu L*a*b* để lấy các mốc điểm chiều cao và
chiều rộng.
face_locations = face_recognition.face_locations(l, model='hog') // Tìm kiếm
khn mặt bằng HOG.
148
top, right, bottom, left = face_locations[0] // Trích xuất vị trí, vẽ khung
nhận diện khuôn mặt.
x1, y1, x2, y2 = left, top, right, bottom x1 = int(x1 * width_ratio)
y1 = int(y1 * height_ratio) x2 = int(x2 * width_ratio) y2 = int(y2 * height_ratio)
PHỤ LỤC 1.2 Xác định vị trí mắt và trích xuất trạng thái mắt đóng/mở
gray = cv2.cvtColor(self.frame_in, cv2.COLOR_BGR2GRAY) //Trích xuất
vị trí 2 mắt.
shape = sleep_predictor(gray, dlib.rectangle(x1, y1, x2, y2)) face_landmarks = face_utils.shape_to_np(shape) left_eye_indices = face_landmarks[FacialLandMarksPosition.left_eye_start_index: FacialLandMarksPosition.left_eye_end_index] (x, y, w, h) = cv2.boundingRect(np.array([left_eye_indices])) left_eye = gray[y:y + h, x:x + w] right_eye_indices = face_landmarks[FacialLandMarksPosition.right_eye_start_index: FacialLandMarksPosition.right_eye_end_index] (x, y, w, h) = cv2.boundingRect(np.array([right_eye_indices])) right_eye = gray[y:y + h, x:x + w]
149
left_eye_open = 'yes' if self.predict_eye_state(model=model_hdf5, image=left_eye) else 'no' //Dùng Mobilnet để kiểm tra mắt đóng hay mắt mở. right_eye_open = 'yes' if self.predict_eye_state(model=model_hdf5, image=right_eye) else 'no'
self.find_face = True // Đánh dấu: nhận diện được khuôn mặt. else:
self.find_face = False // Đánh dấu: không nhận diện được khuôn mặt
PHỤ LỤC 1.3 Cách thức trích xuất nhịp tim bằng OpenCV trong Python
(Tham khảo: Tristan Hearn, “using only their own webcam”, ngày 27 tháng 6 năm 2017 <https://github.com/thearn/webcam-pulse-detector>).
ef resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """