Artificial Intelligence 8 min read

Python‑Based IoT Attendance System with 2D Face Recognition

This article describes a Python IoT attendance system that uses 2D face recognition for clock‑in/clock‑out, calculates attendance time, stores records in CSV files, and provides a PyQt5 graphical interface, detailing required environments, core code, and system limitations.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Python‑Based IoT Attendance System with 2D Face Recognition

The project implements an IoT laboratory attendance system where personnel can sign in and out using 2D face recognition, calculate attendance duration, and save records as CSV files. The system avoids the complex training phase of deep‑learning face models, offering a lightweight and quick solution.

Key Features 1. Face‑based sign‑in/sign‑out 2. Attendance time calculation 3. CSV data export

Required Environment Core libraries: OpenCV‑Python 4.5.5.64, face_recognition 1.30 (with face_recognition_model 0.3.0), dlib 19.23.1. UI framework: PyQt5 5.15.4 (including pyqt5‑plugins, PyQt5‑Qt5, PyQt5‑sip, pyqt5‑tools). Development tools: PyCharm 2021.1.3, Python 3.9.12, Anaconda.

Core Code – MainWindow.py

class Ui_Dialog(QDialog):
    def __init__(self):
        super(Ui_Dialog, self).__init__()
        loadUi("mainwindow.ui", self)  # load QT UI file
        self.runButton.clicked.connect(self.runSlot)
        self._new_window = None
        self.Videocapture_ = None

Camera Invocation

def refreshAll(self):
    print("Current camera index (0 = built‑in, 1 = USB):")
    self.Videocapture_ = "0"

Core Code – OutWindow.py (Time Display)

class Ui_OutputDialog(QDialog):
    def __init__(self):
        super(Ui_OutputDialog, self).__init__()
        loadUi("./outputwindow.ui", self)  # load output UI
        now = QDate.currentDate()
        current_date = now.toString('ddd dd MMMM yyyy')
        current_time = datetime.datetime.now().strftime("%I:%M %p")
        self.Date_Label.setText(current_date)
        self.Time_Label.setText(current_time)

Attendance Time Calculation

def ElapseList(self, name):
    with open('Attendance.csv', "r") as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        line_count = 2
        Time1 = datetime.datetime.now()
        Time2 = datetime.datetime.now()
        for row in csv_reader:
            for field in row:
                if field in row:
                    if field == 'Clock In' and row[0] == name:
                        Time1 = datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S')
                        self.TimeList1.append(Time1)
                    if field == 'Clock Out' and row[0] == name:
                        Time2 = datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S')
                        self.TimeList2.append(Time2)

Face Recognition Process

# Face recognition part
faces_cur_frame = face_recognition.face_locations(frame)
encodes_cur_frame = face_recognition.face_encodings(frame, faces_cur_frame)
for encodeFace, faceLoc in zip(encodes_cur_frame, faces_cur_frame):
    match = face_recognition.compare_faces(encode_list_known, encodeFace, tolerance=0.50)
    face_dis = face_recognition.face_distance(encode_list_known, encodeFace)
    name = "unknown"
    best_match_index = np.argmin(face_dis)
    if match[best_match_index]:
        name = class_names[best_match_index].upper()
        y1, x2, y2, x1 = faceLoc
        cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
        cv2.rectangle(frame, (x1, y2-20), (x2, y2), (0, 255, 0), cv2.FILLED)
        cv2.putText(frame, name, (x1+6, y2-6), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1)
    mark_attendance(name)
    return frame

CSV Data Saving and Sign‑In/Sign‑Out Logic

def mark_attendance(name):
    if self.ClockInButton.isChecked():
        self.ClockInButton.setEnabled(False)
        with open('Attendance.csv', 'a') as f:
            if name != 'unknown':
                buttonReply = QMessageBox.question(self, 'Welcome ' + name, 'Start sign‑in', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                if buttonReply == QMessageBox.Yes:
                    date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
                    f.writelines(f'\n{name},{date_time_string},Clock In')
                    self.ClockInButton.setChecked(False)
                    self.NameLabel.setText(name)
                    self.StatusLabel.setText('Sign‑in')
                    self.HoursLabel.setText('Timing started')
                    self.Time1 = datetime.datetime.now()
                    self.ClockInButton.setEnabled(True)
                else:
                    print('Sign‑in failed')
                    self.ClockInButton.setEnabled(True)
    elif self.ClockOutButton.isChecked():
        self.ClockOutButton.setEnabled(False)
        with open('Attendance.csv', 'a') as f:
            if name != 'unknown':
                buttonReply = QMessageBox.question(self, 'Hi ' + name, 'Confirm sign‑out?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                if buttonReply == QMessageBox.Yes:
                    date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
                    f.writelines(f'\n{name},{date_time_string},Clock Out')
                    self.ClockOutButton.setChecked(False)
                    self.NameLabel.setText(name)
                    self.StatusLabel.setText('Sign‑out')
                    self.Time2 = datetime.datetime.now()
                    self.ElapseList(name)
                    self.TimeList2.append(datetime.datetime.now())
                    CheckInTime = self.TimeList1[-1]
                    CheckOutTime = self.TimeList2[-1]
                    self.ElapseHours = (CheckOutTime - CheckInTime)
                    self.MinLabel.setText(f"{abs(self.ElapseHours.total_seconds() / 60) % 60:.0f}m")
                    self.HoursLabel.setText(f"{abs(self.ElapseHours.total_seconds() / 3600):.0f}h")
                    self.ClockOutButton.setEnabled(True)
                else:
                    print('Sign‑out failed')
                    self.ClockOutButton.setEnabled(True)

The article also shows UI screenshots of the login screen, main interface, sign‑in/out displays, and backend CSV records, as well as the project directory structure. The concluding remarks note that the system lacks a trained face model, leading to higher mis‑recognition rates, high CPU usage, low frame rates, and limited data security due to CSV storage.

Pythonface recognitionIoTCSVopencvPyQt5Attendance System
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.