Saya bekerja sebagai guru di taman teknologi anak-anak Quantorium. Selama periode isolasi diri, kami, seperti orang lain, beralih ke pembelajaran jarak jauh. Dan karena fakta bahwa anak-anak mulai menghabiskan lebih banyak waktu di depan komputer, pihak administrasi memutuskan untuk mempersingkat jam akademik dan beristirahat di antara pekerjaan - untuk menjaga penglihatan mereka. Kami telah menulis sebuah aplikasi yang menghitung waktu yang dihabiskan di depan komputer, membuat statistik tetap unggul - berguna bagi orang tua, dan memberikan peringatan suara saat waktunya istirahat.
Aplikasi ini akan berguna bagi mereka yang tersesat dalam waktu bekerja di PC dan ingin mendorong diri mereka sendiri ke dalam kerangka waktu atau melacak bagian hidup mana yang hilang dalam ruang digital.
Link ke repositori
Di bawah pemotongan, analisis rinci.
Untuk membuat program, Anda perlu menyelesaikan tugas-tugas berikut:
- web ( mtcnn);
- ( time)
- excel ( openpyxl);
- ;
- .
web
Kami mempertimbangkan opsi pelacakan kehadiran di komputer dengan gerakan mouse komputer, mungkin lebih mudah dan kamera web akan tetap gratis, tetapi kemudian kami tidak akan dapat memperhitungkan tampilan acara TV atau video youtube, selain itu, menggunakan pengenalan wajah jauh lebih menarik.
Untuk deteksi wajah, kami menggunakan arsitektur mtcnn. Kepala yang diposisikan di sembarang sudut, mengenakan kacamata, dalam kondisi pencahayaan yang buruk, bahkan jika wajah tidak sepenuhnya jatuh ke dalam bingkai atau ditutupi oleh tangan, jaringan saraf berfungsi dengan baik. Kami tidak akan membangunnya sendiri, kami akan menghubungkan pustaka dengan nama yang sama, yang akan menyelesaikan masalah kami menggunakan beberapa baris kode.
Awalnya, metode Viola-Jones digunakan. Akurasinya jauh lebih buruk daripada mtcnn, prosesor memuat sama.
Kami akan memindahkan keluaran hasil ke dalam fungsi terpisah, yang diperlukan hanya untuk melihat cara kerja pengenalan.
import cv2
import os
from mtcnn.mtcnn import MTCNN
def show_face_frame():
if faces:
bounding_box = faces[0]['box']
keypoints = faces[0]['keypoints']
cv2.rectangle(img,
(bounding_box[0], bounding_box[1]),
(bounding_box[0] + bounding_box[2],
bounding_box[1] + bounding_box[3]),
(0, 0, 255),
2)
cv2.circle(img, (keypoints['left_eye']), 3, (0, 0, 255), 2)
cv2.circle(img, (keypoints['right_eye']), 2, (0, 0, 255), 2)
cv2.circle(img, (keypoints['nose']), 3, (0, 0, 255), 2)
cv2.circle(img, (keypoints['mouth_left']), 3, (0, 0, 255), 2)
cv2.circle(img, (keypoints['mouth_right']), 3, (0, 0, 255), 2)
cv2.imshow('frame', img)
cap = cv2.VideoCapture(0)
detector = MTCNN()
while cap.isOpened():
_, img = cap.read()
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
faces = detector.detect_faces(img)
show_face_frame()
cv2.waitKey(300)
cap.release()
cv2.destroyAllWindows()
Penundaan besar cv2.waitKey (300) agar tidak memuat prosesor. Memproses 3-4 frame per detik memuat i3-8145U dengan rata-rata 15%.
Menghitung waktu
Program tidak boleh menulis ke log dalam kasus berikut:
- duduk di depan komputer selama 5 detik untuk melakukan sesuatu byrik;
- pergi keluar untuk menuangkan kopi atau meregangkan kaki saya.
Untuk mengatasi masalah ini, program menggunakan dua stopwatch time_here (menghitung mundur waktu saat wajah ada di bingkai) dan time_not_here (saat tidak ada wajah). Kedua stopwatch disetel ulang saat entri log dibuat. Selain itu, time_not_here disetel ulang setiap kali wajah muncul di bingkai.
Variabel min_time_here menunjukkan waktu minimum yang dihabiskan di depan komputer, setelah itu perlu menulis ke log. Rekaman akan dibuat setelah orang tersebut dialihkan dari komputer untuk waktu yang lebih lama dari yang ditentukan di min_time_not_here .
Dalam kode di bawah ini, pencatatan dilakukan jika Anda telah menghabiskan setidaknya 5 menit di depan komputer. Program tidak akan memperhitungkan fakta bahwa saya terganggu kurang dari 2 menit.
import cv2
import time
import os
from mtcnn.mtcnn import MTCNN
cap = cv2.VideoCapture(0)
path = os.path.abspath(__file__)[:-11] #
here, not_here = 0, 0 #
time_here, time_not_here = 0, 0 #
switch = True #
min_time_here = 300 # , ( )
min_time_not_here = 120 # ( )
detector = MTCNN()
try:
while cap.isOpened():
_, img = cap.read()
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
faces = detector.detect_faces(img)
show_face_frame()
audio_message(path, here)
if faces and switch:
not_here = 0
switch = False
if here == 0:
here = time.time()
print(' ' + time.strftime("%H:%M:%S", time.localtime(here)))
elif not faces and not switch:
not_here = time.time()
switch = True
if not_here != 0:
time_not_here = time.time() - not_here
if here != 0 and not switch:
time_here = time.time() - here
if time_here > min_time_here and time_not_here > min_time_not_here: # min_time_here
write_excel(path, here)
print(' ' + time.strftime('%H:%M:%S', time.gmtime(time.time() - here)))
time_here, time_not_here = 0, 0
here, not_here = 0, 0
elif time_not_here > min_time_not_here and time_here < min_time_here: # min_time_here,
print(' ')
time_here, time_not_here = 0, 0
here, not_here = 0, 0
cv2.waitKey(300)
except KeyboardInterrupt:
if time_here > min_time_here: # min_time_here
write_excel(path, here)
cap.release()
cv2.destroyAllWindows()
Jika pengguna ingin mematikan komputer, pertama-tama Anda perlu menghentikan program (ctrl + c) dan waktu pekerjaan saat ini akan dicatat. Untuk ini, pengendali pengecualian digunakan.
Menulis data menjadi dokumen excel
Untuk bekerja dengan excel, pustaka openpyxl yang luar biasa akan membantu, yang secara bersamaan membaca dan menulis data.
Setiap hari program membuat lembar baru dengan tanggal saat ini.

Dalam 1 lembar, informasi harian dicatat, pada hari berapa banyak waktu yang dihabiskan di depan komputer.
Fungsi write_excel membuka dokumen, menulis data, dan segera menutupnya.
Anda tidak dapat mengubah dokumen melalui openpyxl jika sudah dibuka oleh pengguna. Pengecualian telah ditambahkan untuk kasus ini.
def write_excel(path_excel, time_start):
wb = openpyxl.load_workbook(path_excel + r'\dnevnik.xlsx')
today = time.strftime("%d.%m.%Y", time.localtime(time.time()))
if today not in wb.sheetnames: # ,
wb.create_sheet(title=today)
sheet = wb[today]
sheet.column_dimensions['A'].width = 20
sheet.column_dimensions['B'].width = 20
sheet.column_dimensions['C'].width = 20
sheet.column_dimensions['D'].width = 31
sheet['A1'] = ' '
sheet['B1'] = ' '
sheet['C1'] = ' '
sheet['D1'] = ' :'
sheet['D2'] = ' :'
sheet = wb[today]
row = 2
all_time = 0
else: #
sheet = wb[today]
row = sheet['E1'].value # excel
all_time = sheet['E2'].value #
all_time = all_time.split(':')
all_time = int(all_time[0]) * 3600 + int(all_time[1]) * 60 + int(all_time[2]) #
row = row + 2 #
sheet['A' + str(row)] = time.strftime("%H:%M:%S", time.localtime(time_start)) #
sheet['C' + str(row)] = time.strftime("%H:%M:%S", time.localtime(time.time())) # -
seconds = time.time() - time_start #
sheet['B' + str(row)] = time.strftime('%H:%M:%S', time.gmtime(seconds))
sheet['E1'] = row - 1 #
all_time = all_time + seconds
all_time = time.strftime('%H:%M:%S', time.gmtime(all_time))
sheet['E2'] = all_time
#
sheet_0 = wb.worksheets[0]
sheet_0['A' + str(len(wb.sheetnames))] = today
sheet_0['B' + str(len(wb.sheetnames))] = all_time
while True: #
try:
wb.save(path_excel + r'\dnevnik.xlsx')
except PermissionError:
input(' excel enter')
else:
break
Peringatan suara
Untuk perubahan, kami membuat 8 file audio menggunakan penyintesis ucapan , yang berjalan secara acak setelah satu jam bekerja. Sampai Anda beristirahat, tidak akan ada peringatan audio yang berulang.
def audio_message(path, here):
if here == 0:
pass
elif time.strftime('%H:%M:%S', time.gmtime(time.time()-here)) == "01:00:00":
wav = random.choice(os.listdir(path + r'\audio'))
winsound.PlaySound(path + r'\audio\\' + wav, winsound.SND_FILENAME)
Skrip startup saat menyalakan PC
Agar program dapat dimuat bersama dengan Windows, Anda dapat membuat file batch yang akan menjalankan skrip python. File batch harus ditempatkan di direktori:
C: \ Users \% username% \ AppData \ Roaming \ Microsoft \ Windows \ Start Menu \ Programs \ Startup
Karena file batch dan file sumber disimpan dalam direktori yang berbeda, Anda tidak dapat menggunakan os.getcwd ( ) karena akan mengembalikan jalur ke file batch. Kami menggunakan os.path.abspath (__ file __) [: - 11]
UPD: ak545menyarankan opsi yang lebih baik os.path.dirname (os.path.abspath (__ file__))
Di masa depan
Saya ingin program mengikuti wajah saya, dan tidak semua orang yang duduk di depan komputer. Untuk ini, FaceNet akan digunakan, yang mampu mengenali wajah.
Ada juga rencana untuk mengembangkan widget yang indah, bukan konsol hitam yang jelek, dan agar saat komputer dimatikan, perekaman dilakukan secara otomatis, dan tidak menggunakan interupsi.
Terima kasih atas perhatian Anda. Jika Anda memiliki pertanyaan, tulis di komentar atau di https://www.linkedin.com/in/evg-voronov/