Professional Documents
Culture Documents
Fingerprint and Face Authentication Portable Digital Electronic Voting Machine Final With Appendices June 9
Fingerprint and Face Authentication Portable Digital Electronic Voting Machine Final With Appendices June 9
D. Voter's Recognition
To be able to vote, one must pass either the fingerprint or
face authentication. The voter is to authenticate first through
the fingerprint authentication method. However, if the voter’s
fingerprint biometric is not recognized, they will be redirected
to the face authentication instead. If the voter fails to
authenticate themselves from both methods, they cannot
proceed to the voting proper.
Fig. 6 shows the fingerprint recognition block diagram.
Figure 7. Face Recognition Block Diagram
This is when the voter touches the fingerprint scanner for
authentication. Scanned images will be enhanced through the E. System Integration
HSP amplifier and will then be matched to the stored The EVM and registration are separated, as shown in Fig.
fingerprint data. Once it finds a match, the voter information 8. A laptop will be used to collect voter data, which are their
will be fetched from the database for authentication and then name and their fingerprint and face data. The gathered data
the recognized voter can proceed to the voting display. will be sorted and transferred to the storage of the Raspberry
Pi. The transferred features will then be used to authenticate
the voters. Additionally, the Internet of Things database will
be used to store the users who already voted together with
their votes to the Firebase database to prevent data loss in
instances where there is a storage corruption of the Raspberry
Pi. Additionally, this cloud database will only connect when
the EVM validates the voter’s already-voted status or appends
the recent voter and its vote selection.
F. Hardware Development
Fig. 9 illustrates the prototype design of the Electronic
Figure 6. Fingerprint Recognition Block Diagram
Voting Machine. The size and dimensions of the prototype are
based on the needs and capacity of the potential categories of
voters. There is a presumption that one of the potential Fig. 12 illustrates the system flow in vote casting. It has
categories of voters who will use the Electronic Voting two methods of authentication. Voter's data is stored and
Machine are Persons with Disabilities (PWDs), with the matched (fingerprint and/or face) before proceeding to the
exclusion of blind voters. The Electronic Voting Machine will voting display. The system is on standby displaying a prompt
be placed on a table so that it reaches the height of 48" to place their finger on the scanner. If the fingerprint scanner
(~1.2m), which is the ideal height of an EVM according to the detects a fingerprint, it will start the authentication process,
Kiosk ADA Accessibility ADA Compliance for it to be and when it matches to a registered data, the system will
accessible to the PWDs, especially the people on a wheelchair proceed to the voting display. However, if the fingerprint
like the crippled [13]. authentication fails, it will be redirected to face authentication.
Once the voter passes the face recognition, the system will
then require the voter to blink twice for them to pass
anti-spoofing. Next, the system will check the database to
confirm whether they have already voted. If not yet, the voter
will proceed to the voting display and can now select their
desired candidates, else if they have already voted, they are
shown an error display indicating that they already have voted
and cannot cast more votes. Once the voter is done selecting
their candidates, the voter will be directed to a page showing
Figure 9. EVM Prototype Design the candidates that they have chosen to confirm their
selection. After this, their votes will be counted in the system.
Fig. 10 illustrates the hardware design for the Electronic Additionally, already-voted voters and vote counts will be
Voting Machine, which consists of several devices that are saved on a cloud database, presuming that there is a sudden
connected to a processing unit. The Raspberry Pi implements and unprecedented data loss. Lastly, a receipt will be printed
the Python code, which is the brain of the EVM system. It will showing the exact candidates selected by the voter in the
be powered by a power supply to turn on the connected process for transparency and for the voters to ensure that their
external devices. External peripherals, which are the monitor votes are read correctly. The receipts generated will then be
screen, mouse, camera, and thermal printer are connected to dropped in a drop box and will be kept by the committee for
the RPi. The fingerprint scanner and the camera are the main manual recounting, especially when there are anomalies or
devices for the authentication of voters. Both devices collect when a candidate requests for it. This is also another way of
data for processing and matching to the existing data that were preserving data in case of data corruption or loss.
uploaded to the system. Furthermore, the overall device is the
portable EVM, made for convenience.
Figure 11. Registration Hardware Design Figure 12. Hardware System Flow
G. Testing Procedure III. RESULTS AND DISCUSSIONS
Fig. 13 illustrates the testing procedure cycle of the study.
The requirement of definition signifies the problems of the A. Electronic Voting Machine
study and comes up with solutions that are feasible to the Fig. 14 shows the actual device used to conduct the mock
issue. The prototyping stage is carried out before building the election with the following components used: the monitor
actual device. The design of the actual device involves screen, mouse, camera, and thermal printer, all of which are
hardware components and peripherals. Furthermore, the connected to the Raspberry Pi 4 to perform the voting
software design has a graphical user interface, fingerprint and procedure.
face authentication, and the Internet of Things. The next phase
is the implementation of the actual device, testing its
functionality, and debugging errors. Thorough testing of the
device will be done until it gives good and fairly accurate
results. The final step of the testing will be the full operation
of the completed device while also maintaining its function for
the registration of voters and the election proper at the
University of Mindanao.
Researchers Constraints
The researchers decide on various factors in study. The following parameters were selected to get the most favorable
results that will be used as design for the study.
Complexity. The materials functions are difficult to integrate to each of the proposed designs due to their complex
nature. The researcher encountered challenges in seamlessly integrating the material functions into each design variant.
Performance. Performance evaluation was vital in assessing how well the designs met objectives. Metrics like speed,
accuracy, reliability, durability, and energy consumption were used. Rigorous testing and statistical analysis compared and
identified strengths and weaknesses.
Attractive. Focused on enhancing the attractiveness of the designs. Aesthetics played a significant role in the study, as
they influenced user perception and acceptance.
Economical. Emphasized the importance of economic considerations in the designs. Cost-effectiveness and efficiency
were key factors in the study. The researcher employed strategies to optimize resource utilization and minimize expenses
without compromising quality.
Maintenance. Recognizing the significance of long-term usability and sustainability, the researcher incorporated
features that simplified maintenance and upkeep.
Availability. The researcher took into account potential challenges related to limited stocks and availability of the
designs.
Manufacturability. Aligning the designs with existing methods, the researcher minimized the need for significant
modifications or investments in new equipment
Proposed Design
The proponents proposed two designs of Electronic Voting Machine for the study. Both designs have pros and cons that
will be evaluated through trade-off analysis using the pugh matrix.
The proposed design shown in figure 1 is composition of hardwares that composed the electronic voting machine. It
uses a touchscreen LCD with a table-like set-up with covers at both sides for privacy voting. It is seen there the camera,
fingerprint sensor, and thermal printer.
Fig. 2 EVM Design 2
The second proposed design shown in figure 2 is more portable but uses monitor and mouse to navigate in the votation
process. The following devices such as camera, fingerprint sensor, and thermal printer. It also has covers at the sides for voter’s
privacy while voting.
Pugh Matrix
As shown in Table 1 the pugh matrix table is used to assess the proposed designs by evaluating the parameters. Using
the “+”,”0”, and “-“ used to rate the parameters. Wherein, "+" (Plus): A "+" rating signifies that the alternative performs better,
offers more benefits, or meets the criteria to a higher degree. "0" (Zero): A "0" rating there is neither a significant advantage or
disadvantage compared to the baseline. And, "-" (Minus): A "-" rating suggests that the alternative performs worse, offers fewer
benefits, or fails to meet the criteria as effectively. For the two designs, design 2 is 1st in rank with the highest rating of 4 while
design 1 rating is -2. Design 2 is considered more advantageous compared to design 2 due to its complexity, cost-effectiveness,
maintenance, availability, and manufacturability.
APPENDIX B
Fingerprint Authentication Accuracy Test Raw Data
Fingerprint Authentication
Registered
Trial 1 Trial 2 Trial 3
Voters
1 ✗ ✗ ✓
2 ✓ ✓ ✓
3 ✓ ✓ ✓
4 ✓ ✓ ✓
5 ✓ ✓ ✓
6 ✓ ✓ ✓
7 ✓ ✓ ✓
8 ✓ ✓ ✗
9 ✗ ✓ ✓
10 ✓ ✓ ✓
11 ✓ ✓ ✓
12 ✗ ✓ ✓
13 ✗ ✗ ✓
14 ✗ ✓ ✓
15 ✗ ✓ ✓
APPENDIX C
Face Authentication Accuracy Test Raw Data
Face Authentication
Name Trial 1 Trial 2 Trial 3
Registered Face Confidence A-Spoof Face Confidence A-Spoof Face Confidence A-Spoof
1 Voter 1 ✓ 98.43 ✓ ✓ 98.64 ✓ ✓ 98.09 ✓
2 Voter 2 ✓ 98.88 ✓ ✓ 99.30 ✓ ✓ 99.47 ✓
3 Voter 3 ✓ 98.72 ✓ ✓ 99.82 ✓ ✓ 98.80 ✓
4 Voter 4 ✓ 98.67 ✓ ✓ 98.97 ✓ ✓ 99.48 ✓
5 Voter 5 ✓ 98.37 ✓ ✓ 98.81 ✓ ✓ 98.54 ✓
6 Voter 6 ✓ 99.76 ✓ ✓ 99.38 ✓ ✓ 99.74 ✓
7 Voter 7 ✓ 99.16 ✓ ✓ 99.79 ✓ ✓ 99.49 ✓
8 Voter 8 ✓ 99.62 ✓ ✓ 99.16 ✓ ✓ 99.52 ✓
9 Voter 9 ✓ 99.24 ✓ ✓ 98.96 ✓ ✓ 99.07 ✓
10 Voter 10 ✓ 99.09 ✓ ✓ 99.53 ✓ ✓ 98.83 ✓
11 Voter 11 ✓ 99.25 ✓ ✓ 99.45 ✓ ✓ 99.79 ✓
12 Voter 12 ✓ 99.38 ✓ ✓ 99.20 ✓ ✓ 98.78 ✓
13 Voter 13 ✓ 99.77 ✓ ✓ 99.30 ✓ ✓ 99.24 ✓
14 Voter 14 ✓ 99.60 ✓ ✓ 99.19 ✓ ✓ 98.68 ✓
15 Voter 15 ✓ 99.40 ✓ ✓ 99.28 ✓ ✓ 99.03 ✓
Unregistered Face Confidence A-Spoof Face Confidence A-Spoof Face Confidence A-Spoof
16 Voter 16 ✓ 95.19 ✓ ✓ 95.75 ✓ ✓ 95.83 ✓
17 Voter 17 ✓ 93.09 ✓ ✓ 94.64 ✓ ✓ 93.78 ✓
18 Voter 18 ✓ 95.79 ✓ ✓ 95.47 ✓ ✓ 95.63 ✓
19 Voter 19 ✓ 95.49 ✓ ✓ 94.10 ✓ ✓ 93.70 ✓
20 Voter 20 ✓ 89.98 ✓ ✓ 90.22 ✓ ✓ 90.58 ✓
21 Voter 21 ✓ 93.91 ✓ ✓ 92.09 ✓ ✓ 92.63 ✓
22 Voter 22 ✓ 93.16 ✓ ✓ 94.16 ✓ ✓ 94.86 ✓
23 Voter 23 ✓ 94.26 ✓ ✓ 91.47 ✓ ✓ 94.08 ✓
24 Voter 24 ✓ 92.62 ✓ ✓ 93.14 ✓ ✓ 92.93 ✓
25 Voter 25 ✗ 97.29 ✓ ✓ 94.57 ✓ ✓ 92.64 ✓
26 Voter 26 ✗ 95.03 ✓ ✗ 97.98 ✓ ✗ 97.47 ✓
27 Voter 27 ✓ 95.39 ✓ ✓ 96.08 ✓ ✓ 96.27 ✓
28 Voter 28 ✓ 93.09 ✓ ✓ 95.92 ✓ ✓ 95.79 ✓
29 Voter 29 ✓ 95.34 ✓ ✓ 94.09 ✓ ✓ 92.99 ✓
30 Voter 30 ✓ 91.76 ✓ ✓ 93.83 ✓ ✓ 90.31 ✓
Tabulated Table for Face Authentication Accuracy Test
Trial 1
Confusion Matrix REGISTERED VOTERS = 30 samples
n = 30 Predicted Required Positive Negative
15 0 sample for 15 0
face
(True Positive) (False Positive) UNREGISTERED VOTERS = 30 samples
Actual recognition
2 13 testing: 30 Fake Unknown
(False Negative) (True Negative) 2 13
Trial 2
Confusion Matrix REGISTERED VOTERS = 30 samples
n = 30 Predicted Required Positive Negative
15 0 sample for 15 0
face
(True Positive) (False Positive) UNREGISTERED VOTERS = 30 samples
Actual recognition
1 14 testing: 30 Fake Unknown
(False Negative) (True Negative) 1 14
Trial 3
Confusion Matrix REGISTERED VOTERS = 30 samples
n = 30 Predicted Required Positive Negative
15 0 sample for 15 0
face
(True Positive) (False Positive) UNREGISTERED VOTERS = 30 samples
Actual recognition
1 14 testing: 30 Fake Unknown
(False Negative) (True Negative) 1 14
Voting GUI
APPENDIX F
Software Source Code
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
image_dir = os.path.join(BASE_DIR, "images")
conn = sqlite3.connect('voting_database.db')
curs = conn.cursor()
class Registration(QMainWindow):
known_face_encodings = []
known_face_names = []
def __init__(self):
super(Registration, self).__init__()
loadUi('Registrationtest.ui', self)
self.image=None
self.screenshot = False
self._image_counter = 1
self.start_webcam()
self.fingerCapture.clicked.connect(self.fingercapture)
self.pushCapture.clicked.connect(self.nameFirstLast)
self.deleteButton.clicked.connect(self.deleteRow)
self.saveButton.clicked.connect(self.save)
self.trainButton.clicked.connect(self.trainbutton)
self.csvexp.clicked.connect(self.csvexport)
self.printtally.clicked.connect(self.votecounts)
self.face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
self.firstNameInput.moveCursor(QTextCursor.Start)
self.firstNameInput.setTabChangesFocus(True)
self.lastNameInput.setTabChangesFocus(True)
def votecounts(self):
#updateFiretoSql()
print("done")
voteCounts()
self.warningText.setText("Done Printing")
def csvexport(self):
votecountsPrintCSV()
self.warningText.setText("Done Exporting")
def trainbutton(self):
faceencodePKL = open('faceencode.pkl', 'wb')
count = 0
for root, dirs, files in os.walk(image_dir):
count += (len(files))
actualcount = 0
for root, dirs, files in os.walk(image_dir):
for file in files:
actualcount += 1
print(f"{actualcount}/{count}")
print(root)
self.warningText.setText(f"{actualcount}/{count}")
path = os.path.join(root, file)
label = os.path.basename(root).replace("-", " ").lower()
face_image = face_recognition.load_image_file(path)
face_encoding = face_recognition.face_encodings(face_image)[0]
self.known_face_encodings.append(face_encoding)
self.known_face_names.append(label)
faceencode = []
for name, encoded in zip(self.known_face_names, self.known_face_encodings):
faceencode.append([name, encoded])
pickle.dump(faceencode, faceencodePKL)
self.warningText.setText("TRAINING DONE!!!")
faceencodePKL.close()
@QtCore.pyqtSlot()
def start_webcam(self):
self.capture=cv2.VideoCapture(0)
self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
self.capture.set(cv2.CAP_PROP_FRAME_WIDTH,640)
self.timer=QTimer(self)
self.timer.timeout.connect(self.update_frame)
self.timer.start(5)
@QtCore.pyqtSlot()
def update_frame(self):
ret, self.image=self.capture.read()
if self.screenshot == True:
if self._image_counter != 100: #number of images
firstName1 = self.firstNameInput.toPlainText().replace(" ", "").lower()
lastName1 = self.lastNameInput.toPlainText().replace(" ", "").lower()
fullName1 = firstName1 + ' ' + lastName1
path = os.path.join(image_dir, fullName1)
name = "{}.png".format(self._image_counter+1)
print(os.path.join(path, name))
cv2.imwrite(os.path.join(path, name), self.image)
self._image_counter += 1
cv2.imwrite(os.path.join(path, name), self.image)
self.warningText.setText('Please wait! Capturing Images\n'+str(self._image_counter))
self.camOtherButtons(False)
else:
self.screenshot = False
self.saveButton.setEnabled(True)
else:
self.screenshot = False
self._image_counter = 0
self.image=cv2.flip(self.image,1)
self.displayImage(self.image, 1)
detected_image=self.faceDetection(self.image)
self.displayImage(detected_image,1)
@QtCore.pyqtSlot()
def faceDetection(self,img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = self.face_cascade.detectMultiScale(gray,1.2,minNeighbors=5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
return img
def displayImage(self,img,window=1):
qformat=QImage.Format_Indexed8
if len(img.shape)==3:
if img.shape[2]==4:
qformat=QImage.Format_RGBA8888
else:
qformat=QImage.Format_RGB888
outImage=QImage(img,img.shape[1],img.shape[0],img.strides[0],qformat)
outImage=outImage.rgbSwapped()
if window==1:
self.displayVideo.setPixmap(QPixmap.fromImage(outImage))
self.displayVideo.setScaledContents(True)
@QtCore.pyqtSlot()
def nameFirstLast(self):
firstName = self.firstNameInput.toPlainText().replace(" ", "").lower()
lastName = self.lastNameInput.toPlainText().replace(" ", "").lower()
fullName = firstName + ' ' + lastName
special_char = re.compile('[@_!#$%^&*()<>?/\|}{~:]')
if ((any(map(str.isdigit, firstName)) == True) or (special_char.search(firstName) != None)) or ((any(map(str.isdigit,
lastName)) == True) or (special_char.search(lastName) != None)):
self.warningText.setText("please don't use number/special characters")
else:
if os.path.exists(fullName) == False:
os.chdir("images")
os.makedirs(fullName)
self.screenshot=True
else:
self.warningText.setText("Name Already Taken")
@QtCore.pyqtSlot()
def save(self):
self.firstNameInput.setReadOnly(False)
self.lastNameInput.setReadOnly(False)
self.firstNameInput.clear()
self.lastNameInput.clear()
self.camOtherButtons(True)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
def fingercapture(self):
special_char = re.compile('[@_!#$%^&*()<>?/\|}{~:]')
if ((any(map(str.isdigit, firstName)) == True) or (special_char.search(firstName) != None)) or (
(any(map(str.isdigit, lastName)) == True) or (special_char.search(lastName) != None)):
self.warningText.setText("please don't use number/special characters")
return None
else:
curs.execute("SELECT name FROM voters ")
nameList=[]
for column in curs.fetchall():
nameList.append(column)
for i in range(len(nameList)):
if fullName in nameList[i]:
self.warningText.setText('Name Already taken')
return None
try:
f = PyFingerprint('COM3', 57600, 0xFFFFFFFF, 0x00000000)
if (f.verifyPassword() == False):
raise ValueError('The given fingerprint sensor password is wrong!')
except Exception as e:
self.warningText.setText('The fingerprint sensor could not be initialized!\n Exception message: ' + str(e))
return None
self.warningText.setText('Remove finger')
time.sleep(2)
self.warningText.setText('Waiting for same finger again...')
## Creates a template
f.createTemplate()
except Exception as e:
self.warningText.setText('Operation failed!Exception message: ' + str(e))
return None
def deleteRow(self):
self.warningText.setText("")
if self.lastNameInput.toPlainText() != "" or self.lastNameInput.toPlainText() != "" :
try:
f = PyFingerprint('COM3', 57600, 0xFFFFFFFF, 0x00000000)
if (f.verifyPassword() == False):
raise ValueError('The given fingerprint sensor password is wrong!')
except Exception as e:
self.warningText.setText('The fingerprint sensor could not be initialized!\nException message: ' + str(e))
return None
print("wew")
if (f.deleteTemplate(int(pos)) == True):
self.warningText.setText(nameSql + "\nfingerprint and pictures are deleted")
conn.commit()
return None
app=QApplication(sys.argv)
window = Registration()
window.show()
try:
sys.exit(app.exec_())
conn.close()
except:
print('exiting')
conn.close()
For Voting Code
import time
from PyQt5.QtGui import QImage, QPixmap, QMovie
from PyQt5.QtCore import pyqtSlot, QTimer, Qt, QThread, pyqtSignal
import face_recognition
import os, sys
import cv2
import numpy as np
import math
import pickle
from PyQt5.QtWidgets import *
from PyQt5.uic import loadUi
from pyfingerprint.pyfingerprint import PyFingerprint
from PyQt5 import QtWidgets
from pyFire import *
import sqlite3
import dlib
from printertest import printcandidates
from config import *
#################################################################################################
##Initialize
conn = sqlite3.connect('voting_database.db')
curs = conn.cursor()
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
image_dir = os.path.join(BASE_DIR, "images")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("model_landmarks/shape_predictor_68_face_landmarks.dat")
def addimage(self):
qpixmap = QPixmap('background.png')
self.background.setPixmap(qpixmap)
def putFinger(self):
f = PyFingerprint(fingerprint(), 57600, 0xFFFFFFFF, 0x00000000)
try:
#self.startwords()
# print('Waiting for finger...')
## Wait that finger is read
while (f.readImage() == False):
pass
if (positionNumber == -1):
#widget.setCurrentIndex(widget.currentIndex() + 1)
print("here")
#self.showFinger()
# print("im here")
#return None
#print('No match found!\n Try Again!')
else:
##print('The accuracy score is: ' + str(accuracyScore))
pass
except Exception as e:
widget.setCurrentIndex(widget.currentIndex() + 1)
print('Operation failed!')
print('Exception message: ' + str(e))
def openSecondWindow(self,name,pos):
self.window7 = selectedResult()
self.window7.namePOS(name,pos)
print(name+pos)
#widget.setCurrentIndex(widget.currentIndex()+1)
class error1(QMainWindow):
def __init__(self):
super(error1, self).__init__()
loadUi('votersGui11.ui', self)
qpixmap = QPixmap('errorsym.png')
self.background.setPixmap(qpixmap)
self.initFinger.clicked.connect(self.home)
self.initFinger_2.clicked.connect(self.face)
def home(self):
widget.setCurrentIndex(widget.currentIndex() - 1)
def face(self):
widget.setCurrentIndex(widget.currentIndex() + 2)
class error2(QMainWindow):
def __init__(self):
super(error2, self).__init__()
loadUi('votersGui12.ui', self)
qpixmap = QPixmap('errorsym.png')
self.background.setPixmap(qpixmap)
self.initFinger.clicked.connect(self.home)
def home(self):
widget.setCurrentIndex(widget.currentIndex() - 2)
############################################################################################
capcheck = []
nameget = []
facecheck = []
class Recognition(QMainWindow):
def __init__(self):
super(Recognition, self).__init__()
loadUi("faceRECOGNITIONWINDOW.ui", self)
self.encoded()
self.webcam.clicked.connect(self.faceREC)
self.exit.clicked.connect(self.quit)
face_locations = []
face_encodings = []
face_names = []
known_face_encodings = []
known_face_names = []
def recclear(self):
self.image.clear()
self.namePrev.clear()
self.camStatus.clear()
self.image.setText(">Press FACE RECOGNITION to Start Authentication\n\n >Press EXIT when you want to Quit")
def quit(self):
self.recclear()
widget.setCurrentIndex(widget.currentIndex() - 3)
@pyqtSlot()
def encoded(self):
faceencodePKL = open('faceencode.pkl', 'rb')
faceencodeloop = pickle.load(faceencodePKL)
for label, face_encoding in faceencodeloop:
self.known_face_encodings.append(face_encoding)
self.known_face_names.append(label)
if facetoeyes == True:
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
rgb_small_frame = small_frame[:, :, ::-1]
self.face_locations = face_recognition.face_locations(rgb_small_frame)
self.face_encodings = face_recognition.face_encodings(rgb_small_frame, self.face_locations)
if matches[best_match_index]:
confidence = face_confidence(face_distances[best_match_index])
numconfidence = float(confidence.strip('%'))
if numconfidence >= 97:
name = self.known_face_names[best_match_index]
else:
name = "Unknown"
self.face_names.append(f'{name}')
if len(self.face_names) > 1:
for i in range(len(self.face_names)-1):
#print("im here")
if self.face_names[i] == self.face_names[i+1]:
#print(self.face_names)
if len(self.face_names) == 3:
print(self.face_names)
self.namePrev.setText(name)
if checkAlreadyVotedName(name) == True: # FIREBASE CHECK IF ALREADY VOTED
#if sqlNoInternet(name) == True: ## NO internet
video_capture.release()
cv2.destroyAllWindows()
return self.exit.setEnabled(True), self.camStatus.setText("already voted")
elif self.face_names[0] == "Unknown":
self.namePrev.setText(name)
video_capture.release()
cv2.destroyAllWindows()
return self.image.setText("Unknown Voter: \n Press Face Recognition to try again or \n Press Exit to
Quit"),self.camStatus.setText("Not Registered"), self.exit.setEnabled(True)
else:
facetoeyes = False
else:
self.face_names.clear()
else:
def proceedVote(self):
curs.execute("SELECT name,position FROM voters")
nameList = []
posList = []
############################################################################################
getResult = []
namE = []
poS = []
class instructionVoting(QMainWindow):
def __init__(self):
super(instructionVoting, self).__init__()
loadUi('votersGui2.ui', self)
self.nextButton.clicked.connect(self.presvote)
def presvote(self):
widget.setCurrentIndex(widget.currentIndex() + 1)
class presVote(QMainWindow):
def __init__(self):
super(presVote, self).__init__()
loadUi('votersPres.ui', self)
self.pres1.setCheckable(True)
self.pres2.setCheckable(True)
self.pres3.setCheckable(True)
self.pres4.setCheckable(True)
self.pres1.clicked.connect(self.togglepres1)
self.pres2.clicked.connect(self.togglepres2)
self.pres3.clicked.connect(self.togglepres3)
self.pres4.clicked.connect(self.togglepres4)
self.nextPres.clicked.connect(self.nextButPres)
def untoggle(self):
for statusBut in [self.pres1,self.pres2,self.pres3,self.pres4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglepres1(self):
if self.pres1.isChecked():
for statusBut in [self.pres2,self.pres3,self.pres4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglepres2(self):
if self.pres2.isChecked():
for statusBut in [self.pres1, self.pres3, self.pres4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglepres3(self):
if self.pres3.isChecked():
for statusBut in [self.pres1, self.pres2, self.pres4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglepres4(self):
if self.pres4.isChecked():
for statusBut in [self.pres1, self.pres2, self.pres3]:
if statusBut.isChecked() == True:
statusBut.toggle()
def nextButPres(self):
for statusBut in [self.pres1, self.pres2, self.pres3, self.pres4]:
if statusBut.isChecked() == True:
#print(statusBut.text())
self.showVote(statusBut.text())
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() + 1)
class internalVP(QMainWindow):
def __init__(self):
super(internalVP, self).__init__()
loadUi('votersInternalVice.ui', self)
self.vice1.setCheckable(True)
self.vice2.setCheckable(True)
self.vice3.setCheckable(True)
self.vice4.setCheckable(True)
self.vice1.clicked.connect(self.togglevice1)
self.vice2.clicked.connect(self.togglevice2)
self.vice3.clicked.connect(self.togglevice3)
self.vice4.clicked.connect(self.togglevice4)
self.backVice.clicked.connect(self.backButVice)
self.nextVice.clicked.connect(self.nextButVice)
def untoggle(self):
for statusBut in [self.vice1, self.vice2, self.vice3, self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice1(self):
if self.vice1.isChecked():
for statusBut in [self.vice2,self.vice3,self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice2(self):
if self.vice2.isChecked():
for statusBut in [self.vice1, self.vice3, self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice3(self):
if self.vice3.isChecked():
for statusBut in [self.vice1, self.vice2, self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice4(self):
if self.vice4.isChecked():
for statusBut in [self.vice1, self.vice2, self.vice3]:
if statusBut.isChecked() == True:
statusBut.toggle()
def nextButVice(self):
for statusBut in [self.vice1, self.vice2, self.vice3, self.vice4]:
if statusBut.isChecked() == True:
self.showVote(statusBut.text())
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() + 1)
def backButVice(self):
getResult.pop()
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() - 1)
class externalVP(QMainWindow):
def __init__(self):
super(externalVP, self).__init__()
loadUi('votersExternalVice.ui', self)
self.vice1.setCheckable(True)
self.vice2.setCheckable(True)
self.vice3.setCheckable(True)
self.vice4.setCheckable(True)
self.vice1.clicked.connect(self.togglevice1)
self.vice2.clicked.connect(self.togglevice2)
self.vice3.clicked.connect(self.togglevice3)
self.vice4.clicked.connect(self.togglevice4)
self.backVice.clicked.connect(self.backButVice)
self.nextVice.clicked.connect(self.nextButVice)
def untoggle(self):
for statusBut in [self.vice1, self.vice2, self.vice3, self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice1(self):
if self.vice1.isChecked():
for statusBut in [self.vice2,self.vice3,self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice2(self):
if self.vice2.isChecked():
for statusBut in [self.vice1, self.vice3, self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice3(self):
if self.vice3.isChecked():
for statusBut in [self.vice1, self.vice2, self.vice4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglevice4(self):
if self.vice4.isChecked():
for statusBut in [self.vice1, self.vice2, self.vice3]:
if statusBut.isChecked() == True:
statusBut.toggle()
def nextButVice(self):
for statusBut in [self.vice1, self.vice2, self.vice3, self.vice4]:
if statusBut.isChecked() == True:
self.showVote(statusBut.text())
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() + 1)
def backButVice(self):
getResult.pop()
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() - 1)
class secVote(QMainWindow):
def __init__(self):
super(secVote, self).__init__()
loadUi('votersSec.ui', self)
self.sec1.setCheckable(True)
self.sec2.setCheckable(True)
self.sec3.setCheckable(True)
self.sec4.setCheckable(True)
self.sec1.clicked.connect(self.togglesec1)
self.sec2.clicked.connect(self.togglesec2)
self.sec3.clicked.connect(self.togglesec3)
self.sec4.clicked.connect(self.togglesec4)
self.backSec.clicked.connect(self.backButSec)
self.nextSec.clicked.connect(self.nextButSec)
def untoggle(self):
for statusBut in [self.sec1, self.sec2, self.sec3, self.sec4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglesec1(self):
if self.sec1.isChecked():
for statusBut in [self.sec2,self.sec3,self.sec4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglesec2(self):
if self.sec2.isChecked():
for statusBut in [self.sec1, self.sec3, self.sec4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglesec3(self):
if self.sec3.isChecked():
for statusBut in [self.sec1, self.sec2, self.sec4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def togglesec4(self):
if self.sec4.isChecked():
for statusBut in [self.sec1, self.sec2, self.sec3]:
if statusBut.isChecked() == True:
statusBut.toggle()
def nextButSec(self):
for statusBut in [self.sec1, self.sec2, self.sec3, self.sec4]:
if statusBut.isChecked() == True:
#print(statusBut.text())
self.showVote(statusBut.text())
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() + 1)
def backButSec(self):
getResult.pop()
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() - 1)
class treaVote(QMainWindow):
def __init__(self):
super(treaVote, self).__init__()
loadUi('votersTrea.ui', self)
self.trea1.setCheckable(True)
self.trea2.setCheckable(True)
self.trea3.setCheckable(True)
self.trea4.setCheckable(True)
self.trea1.clicked.connect(self.toggletrea1)
self.trea2.clicked.connect(self.toggletrea2)
self.trea3.clicked.connect(self.toggletrea3)
self.trea4.clicked.connect(self.toggletrea4)
self.backTrea.clicked.connect(self.backButTrea)
self.nextTrea.clicked.connect(self.nextButTrea)
def untoggle(self):
for statusBut in [self.trea1, self.trea2, self.trea3, self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea1(self):
if self.trea1.isChecked():
for statusBut in [self.trea2,self.trea3,self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea2(self):
if self.trea2.isChecked():
for statusBut in [self.trea1, self.trea3, self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea3(self):
if self.trea3.isChecked():
for statusBut in [self.trea1, self.trea2, self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea4(self):
if self.trea4.isChecked():
for statusBut in [self.trea1, self.trea2, self.trea3]:
if statusBut.isChecked() == True:
statusBut.toggle()
def nextButTrea(self):
for statusBut in [self.trea1, self.trea2, self.trea3, self.trea4]:
if statusBut.isChecked() == True:
self.showVote(statusBut.text())
self.untoggle()
#print("Im here")
widget.setCurrentIndex(widget.currentIndex() + 1)
def showVote(self,getVote):
window7 = selectedResult()
window7.selected(getVote)
def backButTrea(self):
getResult.pop()
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() - 1)
class auditor(QMainWindow):
def __init__(self):
super(auditor, self).__init__()
loadUi('votersAuditor.ui', self)
self.trea1.setCheckable(True)
self.trea2.setCheckable(True)
self.trea3.setCheckable(True)
self.trea4.setCheckable(True)
self.trea1.clicked.connect(self.toggletrea1)
self.trea2.clicked.connect(self.toggletrea2)
self.trea3.clicked.connect(self.toggletrea3)
self.trea4.clicked.connect(self.toggletrea4)
self.backTrea.clicked.connect(self.backButTrea)
self.nextTrea.clicked.connect(self.nextButTrea)
def untoggle(self):
for statusBut in [self.trea1, self.trea2, self.trea3, self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea1(self):
if self.trea1.isChecked():
for statusBut in [self.trea2,self.trea3,self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea2(self):
if self.trea2.isChecked():
for statusBut in [self.trea1, self.trea3, self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea3(self):
if self.trea3.isChecked():
for statusBut in [self.trea1, self.trea2, self.trea4]:
if statusBut.isChecked() == True:
statusBut.toggle()
def toggletrea4(self):
if self.trea4.isChecked():
for statusBut in [self.trea1, self.trea2, self.trea3]:
if statusBut.isChecked() == True:
statusBut.toggle()
def nextButTrea(self):
for statusBut in [self.trea1, self.trea2, self.trea3, self.trea4]:
if statusBut.isChecked() == True:
self.showVote(statusBut.text())
window7.result()
self.untoggle()
widget.setCurrentIndex(widget.currentIndex() + 1)
def showVote(self,getVote):
window7 = selectedResult()
window7.selected(getVote)
def backButTrea(self):
getResult.pop()
widget.setCurrentIndex(widget.currentIndex() - 1)
class selectedResult(QMainWindow):
def __init__(self):
super(selectedResult, self).__init__()
loadUi('votersPreview.ui', self)
self.backSelect.clicked.connect(self.backButSelect)
self.finalizeSelect.clicked.connect(self.finalizeVote)
def selected(self,candidates):
getResult.append(candidates)
def result(self):
self.presSelect.setText(getResult[0])
self.internalSelect.setText(getResult[1])
self.externalSelect.setText(getResult[2])
self.secSelect.setText(getResult[3])
self.treaSelect.setText(getResult[4])
self.auditorSelect.setText(getResult[5])
def backButSelect(self):
getResult.pop()
widget.setCurrentIndex(widget.currentIndex() - 1)
def finalizeVote(self):
for pos in poS:
poss = pos
for name in namE:
namee = name
print(getResult)
finalizeFire(namee, poss ,getResult[0],getResult[1],getResult[2],getResult[3],getResult[4],getResult[5]) # internet
#finalizeNoInternet(namee, poss ,getResult[0],getResult[1],getResult[2],getResult[3],getResult[4],getResult[5]) #NO
internet
printcandidates(getResult[0],getResult[1],getResult[2],getResult[3],getResult[4],getResult[5],namee)
updateFiretoSql() ####### internet
poS.clear()
getResult.clear()
namE.clear()
capcheck.clear()
nameget.clear()
widget.setCurrentIndex(widget.currentIndex() + 1)
class thankyou(QMainWindow):
def __init__(self):
super(thankyou, self).__init__()
loadUi('thankyou.ui', self)
self.done.clicked.connect(self.done1)
def done1(self):
widget.setCurrentIndex(0)
app=QApplication(sys.argv)
window = Voting()
window1 = error1()
window12 = error2()
windowRec = Recognition()
window2 = instructionVoting()
window3 = presVote()
window4 = internalVP()
window44 = externalVP()
window5 = secVote()
window6 = treaVote()
window67 = auditor()
window7 = selectedResult()
window8 = thankyou()
widget = QtWidgets.QStackedWidget()
widget.addWidget(window)
widget.addWidget(window1)
widget.addWidget(window12)
widget.addWidget(windowRec)
widget.addWidget(window2)
widget.addWidget(window3)
widget.addWidget(window4)
widget.addWidget(window44)
widget.addWidget(window5)
widget.addWidget(window6)
widget.addWidget(window67)
widget.addWidget(window7)
widget.addWidget(window8)
window.setFixedWidth(720)
window.setFixedHeight(480)
# windowRec.setFixedWidth(800)
# windowRec.setFixedHeight(600)
#widget.showFullScreen()
widget.show()
try:
sys.exit(app.exec_())
conn.close()
except:
print('exiting')
conn.close()
For Cloud Database Code
import sqlite3
import pyrebase
import csv
import pandas as pd
from urllib import request
from printertest import totalVotes
config = {
"apiKey": "AIzaSyCeHmYk0JWMGrqaY7zE12TagjEklxdH8ME",
"authDomain": "evmthesis.firebaseapp.com",
"databaseURL": "https://evmthesis-default-rtdb.firebaseio.com",
"projectId": "evmthesis",
"storageBucket": "evmthesis.appspot.com",
"messagingSenderId": "762023483827",
"appId": "1:762023483827:web:eef8e7b36420e575fc53c6",
"measurementId": "G-0941KERDG6"
}
firebase=pyrebase.initialize_app(config)
db = firebase.database()
conn = sqlite3.connect('voting_database.db')
curs = conn.cursor()
def checkAlreadyVoted(posnumber):
for result in db.child("thesis").get().each():
for pos in db.child("thesis").child(result.key()).get().each():
if pos.val() == posnumber:
return True
def checkAlreadyVotedName(name):
for result in db.child("thesis").get().each():
if result.key() == name:
return True
def finalizeFire(name,pos,pres,internal,external,sec,trea,auditor):
posdata = {"pos": pos}
data = {"pres": pres, "internalVP": internal, "exteralVP": external, "secretary": sec, "trea": trea, "auditor": auditor}
db.child("thesis").child(name).set(posdata)
db.child("thesis").child(name).child('selection').set(data)
print('DONE!')
def getDataFiretoSQL():
data = []
for result in db.child("thesis").get():
if result.key() != "zero zero":
dataParent = []
for pos in db.child("thesis").child(result.key()).get():
if pos.key() == "pos":
dataParent.append(result.key())
dataParent.append(pos.val())
def updateFiretoSql():
data = getDataFiretoSQL()
curs.execute("DELETE FROM syncvotes;")
sql = """INSERT INTO syncvotes(name,pos,pres,internal,external,sec,trea,auditor) VALUES(?,?,?,?,?,?,?,?);"""
curs.executemany(sql, data)
conn.commit()
print("Firebase data updated to SQL syncvotes") # sync firebase and sql
def votecountsPrintCSV():
sqlquery = "SELECT * FROM syncvotes"
curs.execute(sqlquery)
for row in curs.fetchall():
df = pd.read_sql_query(sqlquery, conn)
df.to_csv('votes.csv', index=False) #microsoft excel file
def voteCounts():
presA = []
inviceB = []
exviceB = []
secC = []
treaD = []
audE = []
curs.execute("SELECT pres,internal,external,sec,trea,auditor FROM syncvotes")
def fingerNoInternet(poss):
curs.execute("SELECT pos FROM syncvotes")
checkpos = []
for pos in curs.fetchall():
checkpos.append(pos)
for i in range(len(checkpos)):
if poss in checkpos[i]:
conn.commit()
print("yes")
return True
For Thermal Printer Code
import adafruit_thermal_printer
import serial
from config import *
import adafruit_thermal_printer
ThermalPrinter = adafruit_thermal_printer.get_printer_class(2.69)
printer = ThermalPrinter(uart, auto_warm_up=True)
printer.warm_up(120)
def printcandidates(pres,internal,external,sec,trea,auditor,candidatename):
printer.bold = True
printer.underline = adafruit_thermal_printer.UNDERLINE_THICK
printer.size = adafruit_thermal_printer.SIZE_MEDIUM
printer.justify = adafruit_thermal_printer.JUSTIFY_CENTER
printer.bold = True
printer.print('CANDIDATES SELECTED')
printer.bold = True
printer.print(candidatename)
printer.feed(1)
printer.underline = None
printer.size = adafruit_thermal_printer.SIZE_SMALL
printer.justify = adafruit_thermal_printer.JUSTIFY_LEFT
printer.bold = True
printer.print('President: ')
printer.print(pres)
printer.bold = True
printer.print('Internal Vice-President: ')
printer.print(internal)
printer.bold = True
printer.print('External Vice-President: ')
printer.print(external)
printer.bold = True
printer.print('Secretary: ')
printer.print(sec)
printer.bold = True
printer.print('Treasurer: ')
printer.print(trea)
printer.bold = True
printer.print('Auditor: ')
printer.print(auditor)
printer.bold = True
printer.feed(3)
printer.bold = False
def totalVotes(pres,internal,external,sec,trea,auditor):
printer.bold = True
printer.underline = adafruit_thermal_printer.UNDERLINE_THICK
printer.size = adafruit_thermal_printer.SIZE_MEDIUM
printer.justify = adafruit_thermal_printer.JUSTIFY_CENTER
printer.print('Vote Counts')
printer.feed(1)
printer.underline = None
printer.size = adafruit_thermal_printer.SIZE_SMALL
printer.justify = adafruit_thermal_printer.JUSTIFY_LEFT
printer.print('President:')
for Akey, Aval in pres.items():
printer.print(f"{Akey} = {Aval}")
printer.print('\nInternal VP:')
for Bkey, Bval in internal.items():
printer.print(f"{Bkey} = {Bval}")
printer.print('\nExternal VP:')
for BBkey, BBval in external.items():
printer.print(f"{BBkey} = {BBval}")
printer.print('\nSecretary:')
for Ckey, Cval in sec.items():
printer.print(f"{Ckey} = {Cval}")
printer.print('\nTreasurer:')
for Dkey, Dval in trea.items():
printer.print(f"{Dkey} = {Dval}")
printer.print('\nAuditor:')
for Ekey, Eval in auditor.items():
printer.print(f"{Ekey} = {Eval}")
printer.feed(4)
printer.bold = False
For Configuration Code
def fingerprint():
return str("COM14")
def printer():
return str("COM9")
def camera():
return int(0)
APPENDIX F
Informed Consent
Title of Research: Fingerprint and Face Authentication Portable Digital Electronic Voting Machine
Investigators, Affiliations, and Contact Information:
Subject Participation
20 participants are needed for this study. They must be a bonafide student at University of
Mindanao for the second semester of the academic year 2022-2023, enrolled in BS
Electronics Engineering program. Participants will be involved in 3 meetings in total,
approximately 30 minutes to 1 hour in length.
Confidentiality
All information collected from the study will be coded to protect each subject’s name.
Although your information will be stored in our database as they are needed for the
authentication processes, no names or other identifying information will be used when
discussing or reporting data. The researchers will safely keep all data gathered from the said
database, and only them can access it. Once the data has been fully analyzed, it will be
destroyed.
Authorization
By signing this form, you authorize the use and disclosure of the following information
for this research:
I authorize the use of the data collected from me during this study for the sole purpose of the
said research.
Cost
There is no cost for participating in this study.
Name of Participant
Name of Witness
Objective
• I am eager to find a job that aligns with my educational background, allowing me to gain
valuable experience and enhance my professional growth.
Education
• Bachelor of Science in Electronics Engineering
University of Mindanao, Matina, Davao City
October 2018 – Present
Affiliations
• Society of Electronics Engineering Students (SECES)
Member
2019 - Present
• Junior Institute of Electronics Engineers of the Philippines - Southern Mindanao
Sector
Member
2018 – Present
PRINCESS DIANE MABOLOC
Address: 37-A Andaya St., Daliao, Toril, Davao City
Contact Number: +639971104688
Email Address: p.maboloc.499584@umindanao.edu.ph
Objective
• To seize job opportunities that will nurture my capabilities and skills as a future professional
electronics engineer.
Education
• Bachelor of Science in Electronics Engineering
University of Mindanao, Matina, Davao City
October 2018 – Present
Affiliations
• Society of Electronics Engineering Students (SECES)
Member
2020 - Present
Objective
• To proliferate and enhance my skill set in engineering in order to become a competitive
professional electronics engineer.
Education
• Bachelor of Science in Electronics Engineering
University of Mindanao, Matina, Davao City
June 2019 – Present
Affiliations
• Society of Electronics Engineering Students (SECES)
Member
2020 - Present