64x64
Bilbil Isma
Entuziast.
15 Qershor 2020 · 10 min lexim

Detektimi i dremitjes gjatë vozitjes

Detektimi i dremitjes gjatë vozitjes

Abstrakt


Si fëmijë kam qenë kurioz në eksperiencën e vozitësve të kamionave të tonazhit të lartë (transportues ndërkombëtar). Ideja e profesionit që të qon nëpër vende të ndryshme, aventurat e udhëtimit dhe njohja e njerëzve të ndryshëm gjatë rrugës padyshim janë eksperiencë e veqantë dhe profesion që të jep vetëm knaqësi.

Ky mendim mu sfidua kur një i afërt i yni vozitës i transportit ndërkombëtar pësoi një vet-aksident të rëndë dhe ishte mrekulli se si shpëtoi.

Arsyeja e aksidentit ishte dremitja e papritur e shoferit. Dy sekonda dremitje dhe shoferi kishte përfunduar në humnerë në gjendje shumë të rëndë shëndetsore.


Pastaj nga disa kërkime në ueb, kuptova se në fakt ky ishte njëri nga shkaktarët kryesor në vdekshmërinë e vozitësve të transportit ndërkombëtar dhe ishte e dhimbshme për faktin se dremitja vinte shpeshherë si pasojë e presionit nga kontraktuesi për të arritur në destinacion në kohë sa më të shkurtër.


Nga atëherë kam menduar se si do të ishte një zgjidhje ose të paktën një ndihmesë për vozitësit dhe kjo më motivoi që më në fund të vë njohuritë e mija modeste në punë.

 

Shënim: Disa nga termet teknike në vazhdim qëllimisht janë lënë të papërkthyer meqë nuk kam arritur të gjej terme të kuptimshme në gjuhën shqipe.

 

Detektimi i dremitjes duke përdorur OpenCV


Ideja ime ishte e thjeshtë në parim, një sistem i mbështetur nga Computer Vision që do të mund të detektonte me sukses dhe në kohë dremitjen e vozitësit dhe të vepronte proaktivisht në lajmërimin e vozitësit me një sinjal akustik.


Projekti do të realizohej duke përdorur OpenCV, dlib dhe Python. Kjo e bënë projektin të varur vetëm nga Computer Vision, Machine Learning algoritmet nga dlib dhe prellogaritjet e mija, gjë që do duhej të ofronte një zgjidhje të ‘lirë’ për nga kostoja e kodimit/zhvillimit dhe njëkohësisht lehtë të implementueshme.


Mirë shumë, po çka janë OpenCV e dlib?


OpenCV(eng. Open Source Computer Vision Library) është pra një librari me kod burimor të hapur rreth Computer Vision dhe Machine Learning. E tash Computer Vision është një nën-fushë e Shkencave Kompjuterike e cila ka për synim ta rris aftësinë e kompjuterëve për të përvetësuar aftësi të larta të njohjes vizuele. Nga aspekti inxhinierik, tenton ta kopjoj sistemin pamor të njeriut.


Dlib është poashtu librari me kod burimor të hapur e shkruar në C++ dhe mjaft gjenerale në aplikime në Python. Dlib implementon një sërë algoritmesh të Machine Learning duke përfshirë classification, regression, clustering, data transformation, dhe structured prediction.


Tash po besoj e kemi të qartë se kemi të bëjmë me procesim imazhesh, njohje dhe llogaritje, prandaj e kam ndarë zhvillimin e projektit në tri faza:

1.     Detektimi i pikave kyqe të fytyrës(eng. Facial Landmarks) e pastaj izolimi i regjionit të syve.

2.     Llogaritja e aspect ratio të syrit për të detektuar kur sytë janë të mbyllur.

3.     Matja e frames për sa gjatë sytë janë të mbyllur dhe sinjalizimi akustik nëse arrihet limit i caktuar.

Paraprakisht kemi importuar të gjitha libraritë e nevojshme:


from scipy.spatial import distance as dist
from imutils.video import VideoStream
from imutils import face_utils
from threading import Thread
import numpy as np
import playsound
import argparse
import imutils
import time
import dlib
import cv2


1.   Detektimi i pikave kyqe të fytyrës(eng. Facial Landmarks) dhe izolimi i regjionit të syve


Përmes OpenCV kemi arritur t’i qasemi video feed nga web cam dhe të kemi një objekt vizual të gatshëm për pre-procesim. Objekti është pregaditur për njohje duke përdorur Histogramin e Gradientëve të Orientuar e mbi të duke aplikuar Parashikuesin e Pikave Kyqe të Fytyrës që Dlib e mundëson. 


Duke aplikuar algoritmin e klasifikimit nga Machine Learning në objektin e pregaditur vizual, përmes Dlib kemi arritur të nxjerrim një varg koordinatash të pikave kyqe të fytyres. Kjo na ka ofruar mundësinë e izolimit të regioneve të cakuara të fytyrës duke njohur indekset e këtyre koordinatave.


2.   Llogaritja e aspect ratio të syrit për të detektuar kur sytë janë të mbyllur


Regjioni i secilit sy përcaktohet nga gjithsej gjashtë(6) koordinata Karteziane të shenjuara sipas kahut të rrotullimit të akrepave të orës. Duke përdorur librarinë NumPy të Python, kemi arritur t’i qasemi këtij vargu duke nxjerrur koordinatat e syrit të majtë dhe të djathtë respektivisht.


Fig. 2.1 Koordinatat e regjionit të syrit.

Duke i pasur këto të dhëna, përmes një ekuacioni që përkufizon raportin ku numëruesi llogaritë distancën mes pikave vertikale të syrit, kurse emëruesi llogaritë distancën mes pikave horizontale të syrit. Poashtu kemi peshuar proporcionalisht emëruesin ngase kemi vetëm një çift të pikave horizontale e dy çifte të atyre vertikale. Këtë raport e kemi quajtur si Eye Aspect Ration(nga këtu: EAR).


Fig. 2.2 Ekuacioni i EAR


Çka na hyn në punë ky ekuacion? – Vlera e EAR është përafërsisht konstante gjatë kohës që sytë qëndrojnë të hapur(shumicës së kohës aktive të syrit) e kjo vlerë bie drastikisht drejt zeros kur syri mbyllet.


Pra me këtë ekuacion, ne mund t’i shmangim teknikatë procesuese të imazhit dhe përdorimin e algoritmeve të ML/DL. Duke marr si vlerë referente mesatarën e vlerave të EAR të të dy syve, ne kemi arritur të detektojmë kur syri është i mbyllur.


Vlera mesatare përveq që jep saktësinë e duhur matematikore, na ndihmon që të evitojmë rastet kur vetëm njëri sy është i mbyllur si jo të kualifikuar për detektim.

Kodi në vazhdim paraqet këtë pjesë:


def eye_aspect_ratio(eye):
# compute the euclidean distances between the two sets of
# vertical eye landmarks (x, y)-coordinates
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
# compute the euclidean distance between the horizontal
# eye landmark (x, y)-coordinates
C = dist.euclidean(eye[0], eye[3])
# compute the eye aspect ratio
ear = (A + B) / (2.0 * C)
# return the eye aspect ratio
return ear


3.   Matja e kohës për sa gjatë sytë janë të mbyllur dhe sinjalizimi akustik nëse arrihet limit i caktuar kohor


Duke e parë që puna më e vështirë është kryer, në këtë fazë jemi fokusuar në reagimin proaktiv të sistemit për lajmërimin/sinjalizimin e vozitësit në rast dremitje. Kemi caktuar vlerën kufitare të EAR ku syri konsiderohet I mbyllur (0.3), limitin e frames për sa gjatë sytë mund të qëndrojnë të mbyllur para se të sinjalizojmë vozitësin(48).


Me pak kod, kemi arritur që nga momenti i detektimit të inkrementojmë numëruesin deri në limitin e paracaktuar dhe kemi implementuar përmes librarisë soundPy, sinjalizimin akustik si alarm rreziku për vozitësin.

Fig. 3.1 Detektimi dhe paraqitja vizuele e mbylljes së syrit.


E rëndësishme ka qenë që sinjalizimi të ekzekutohet në një thread të ndarë ashtu që programi kryesor të mos bllokohet ndërkohë.


Si përfundim, kemi bllokun e kodit ku menaxhohet rasti kur vlera e EAR është më e madhe si vlera kufitare e detektimit dhe sytë konsiderohen të hapur, me ç’rast, sinjalizimi ndërpritet dhe vlera e variablës ALARM_ON resetohet.



Për arsye lexueshmërie, në vazhdim kam vendosur një version të thjeshtësuar të kodit:


# define two constants, one for the eye aspect ratio to indicate
# blink and then a second constant for the number of consecutive
# frames the eye must be below the threshold for to set off the
# alarm
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 48
# initialize the frame counter as well as a boolean used to
# indicate if the alarm is going off
COUNTER = 0
ALARM_ON = False

# initialize dlib's face detector (HOG-based) and then create
# the facial landmark predictor
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

# grab the indexes of the facial landmarks for the left and
# right eye, respectively
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

# start the video stream thread
print("[INFO] starting video stream thread...")
vs = VideoStream(src=args["webcam"]).start()
time.sleep(1.0)
# loop over frames from the video stream
while True:
# grab the frame from the threaded video file stream, resize
# it, and convert it to grayscale
# channels)
frame = vs.read()
frame = imutils.resize(frame, width=450)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# detect faces in the grayscale frame
rects = detector(gray, 0)

# loop over the face detections
for rect in rects:
# determine the facial landmarks for the face region, then
# convert the facial landmark (x, y)-coordinates to a NumPy
# array
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# extract the left and right eye coordinates, then use the
# coordinates to compute the eye aspect ratio for both eyes
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
# average the eye aspect ratio together for both eyes
ear = (leftEAR + rightEAR) / 2.0

# compute the convex hull for the left and right eye, then
# visualize each of the eyes
leftEyeHull = cv2.convexHull(leftEye)
rightEyeHull = cv2.convexHull(rightEye)
cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)

# check to see if the eye aspect ratio is below the blink
# threshold, and if so, increment the blink frame counter
if ear < EYE_AR_THRESH:
COUNTER += 1
# if the eyes were closed for a sufficient number of
# then sound the alarm
if COUNTER >= EYE_AR_CONSEC_FRAMES:
# if the alarm is not on, turn it on
if not ALARM_ON:
ALARM_ON = True
# check to see if an alarm file was supplied,
# and if so, start a thread to have the alarm
# sound played in the background
if args["alarm"] != "":
t = Thread(target=sound_alarm,
args=(args["alarm"],))
t.deamon = True
t.start()
# draw an alarm on the frame
cv2.putText(frame, "DROWSINESS ALERT!", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
# otherwise, the eye aspect ratio is not below the blink
# threshold, so reset the counter and alarm
else:
COUNTER = 0
ALARM_ON = False

# draw the computed eye aspect ratio on the frame to help
# with debugging and setting the correct eye aspect ratio
# thresholds and frame counters
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
# show the frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()



Aplikimi, sfidat dhe avancimet


Arsyeja pse kemi insistuar që ky sistem të jetë sa më lehtë i implementueshëm ka qenë rritja e mundësive të aplikimit në platforma dhe mjedise të ndryshme. Fakti që ky system është zhvilluar me një vend aplikim në mendje nuk kufizon mundësitë e përshtatjes dhe aplikimit në mjedise dhe skenar tjerë si për shembull: Monitorimi i rojeve gjatë turnit të natës e çdo situatë tjetër që rrezikohet nga dremitja e pakontrolluar.


Sfidë për momentin është portabiliteti i sistemit në një pajisje të vetme si mikro-kompjuteri Raspberry Pi meqë I vetmi version me resurse të mjaftueshme është RPi 4 dhe atë jo në nivelit e kënaqshëm të performancës. Patjetër që sfidë mbetet pregaditja e një mjedisi më të përshtatshëm për detektim(ndriqimi, vendosja e kamerës) duke minimizuar efektin shpërqendrues tek vozitësi(apo cilido shfrytëzues direkt).


Krahas sfidave aktuale, ka vend për shumë avancime meqë projekti është më shumë si punim ambicioz sesa produkt industrial. Përparsia e të zhvilluarit modular të projekteve qëndron në mundësinë që jep për modifikime si në kod ashtu edhe në pajisjet përcjellëse si web cam me kualitet të lart(1080p) apo mikro-kompjuter të avancuar(ex. Nvidia Jetson Xavier).


Konkludimi


Me aftësitë e mija modeste, me resurset dhe mbështetjen nga komuniteti online dhe me pak netë të vona, besoj se kemi arritur që së paku të dëshmojmë se problemet nga jeta reale mund të zgjidhen ose të paktën të lehtësohen nga programet kompjuterike.


Demo Video - Day mode:

https://vimeo.com/user106951581/review/429093121/a3584cea87


Demo Video - Night mode:

https://vimeo.com/user106951581/review/429093597/8facaa7448


Bilbil Isma
Entuziast.

Gjithashtu lexoni


0 komente