G08-2022-ExamMonitoringSystem

Le sujet se base sur la mise en place d’un système de surveillance d’examen, ceci en développant deux applications : mobile et desktop qui vont permettre un bon fonctionnement du système.
Le candidat aura un téléphone attaché sur son front qui va surveiller l’ensemble de ces activités ainsi qu’au objets qui l’entoure, la machine ou il passera l’examen va avoir une connexion directe avec ce téléphone, et sa caméra va essayer de détecter l’ensemble d’objets et de personnes situé dans l’espace du candidat. Toute tentative suspicieuse de triche va empêcher le candidat de continuer le passage de son examen en lui affichant un message d’avertissement.
Avant d’établir les scénarios possible une très bonne analyse à été mise en place en établissant l’ensemble des acteurs qui interviendront dans notre système.
Afin de passer son examen le candidat devrait
• S’identifier par reconnaissance faciale.
• Attacher le téléphone dans son front et le bien placer.
• Commencer à passer son examen.
Lors de son passage d’examen le système va essayer de détecter toute tentative de triche possible pour cela un ensemble de scénarios sera donc possible
• Lors de la connexion, le système va essayer de reconnaitre la personne autorisée à passer l’examen, s’il ne le détecte pas la connexion ne sera pas établie
• Le candidat commence à passer son examen,
si le candidat essaye de tricher soit :
- Partir
- Présence d'une personne non autorisée
- Présence d'un objet non autorisé
Le système va détecter la tentative de triche
sinon le candidat pourrait continuer à passer son examen.

Slides & Videos

Members

NameContribution
BENSAID Mohammed19/01/2022 au 20/01/2022 -> Etablissement d'un système de détection de mouvement en utilisant un accéléromètre
20/01/2022 au 26/01/2022 -> Application mobile de détection des objets avec Android
26/01/2022 au 27/01/2022 -> Integration de la reconnaissance faciale avec les sockets sur desktop avec python
27/01/2022 au 03/02/2022 -> Etablissement des scénarios possibles pour la passation de l'examen.
03/02/2022 au 10/02/2022 -> Connexion entre téléphone android et pc.
11/02/2022 -> Envoie des objets détecter du téléphone au pc.
du 11/02 au 18/02 -> Etablir l'ensemble des scénarios possibles et les intégrer dans l'application desktop en utilisant la liste prédéfinis auparavant
du 18/02 au 24/02 ->Rassembler l'ensemble des fonctionnalités dans une seule application en définissons une interface graphique de l'application
BENDIMRAD Mehdi19/01/2022 au 20/01/2022-> Intégration de l'application de Détection des objets sur Desktop en utilisant Python
20/01/2022 au 26/01/2022 -> Intégration de la reconnaissance faciale sur Desktop en utilisant Python
27/01/2022 au 11/02/2022 -> Établissement des scénarios possibles pour la passation de l'examen.
11/02/2022 -> Récupérer les informations détecter de l'ensemble des fonctionnalités et les stocker dans une liste sur python pour une utilisation ultérieures.
du 11/02/2022 au 18/02/2022 -> Intégration de l’ensemble des scénarios possibles définies auparavant dans l'application Desktop en utilisant une liste prédéfinies.
du 18/02 au 24/02 ->Rassembler l'ensemble des fonctionnalités dans une seule application en définissons une interface graphique de l'application

State of the Art

Business Aspect

EvalBox

Permettre sans effort, de gérer des QCMs les plus variés possibles, auto-corrigés, auto-archivant, sur un système construit pour éliminer la fraude

Evalbox est une plateforme d’évaluation pour gérer des tests QCM en ligne. C’est un outil professionnel, facile à utiliser, avec un mécanisme de correction automatique de vos tests et questionnaires. Vous générez simplement vos QCM par tirage au sort à partir de banques de questions, ou manuellement en choisissant vos questions, planifiez vos sessions d’examen, et les candidats peuvent passer les examens en ligne.

Sa console de surveillance unique, vous permet de surveiller les examens en temps réel, et vous avertit grâce à des algorithmes anti-triche avancés, lorsqu’un élève adopte un comportement suspicieux…

1-2-2-1 EvalBox et le Système d’Anti triche avancé

  • Temps des questions limité.
  • Mécanisme pour empêcher de sauter à une autre fenêtre durant le QCM.
  • Pendant l’examen, suivi des étudiants en temps réel et affichage instantané des alertes de tricherie

Prix:

Liste de comparaison des abonnements de cette solution: evalboxprice-converti

TestWeApp

TestWe est une solution d’e-Exam complète : plateforme pour le corps enseignant et l’administration, logiciel offline pour les apprenants. Créez tous vos examens/évaluations : concours d’entrée, contrôles continus, partiels… Sécurité, confort, simplicité… Plus besoin de choisir !

 Utilisé dans des établissements d’éducation primaire, secondaire, supérieure, les centres de formations et de certifications ou encore les universités d’entreprises et les départements RH.

Le Système antitriche de l’application permet :

  • L’accessibilité sécurisée à la plateforme.
  • Le verrouillage des fonctions de l’ordinateur pendant l’examen.
  • L’authentification du candidat par la prise de photo.
Technical Aspect

Application mobile Android pour la détection des objets

On a choisit d’utiliser une application android déjà développer en java et de l’adapter avec notre besoin.                                                       Il s’agit d’une application de caméra qui détecte en continu les objets (boîtes englobantes et classes)
dans les images vues par la caméra arrière de l’appareil, à l’aide d’un modèle SSD MobileNet quantifié
formé sur l’ensemble de données COCO. Ces instructions vous guident tout au long de la création et de
l’exécution de la démo sur un appareil Android.

On essayera d’utiliser cette application pour détecter les objets dans la face avant du candidat, on va modifier le comportement de l’application on choisissant des objets spécifiques à interdire durant le passage d’examen (personne, document, pc, etc …)

Application desktop pour la détection des objets

On a choisit d’utiliser une application déjà développer en python et de l’adapter avec notre besoin
C’est un modèle de reconnaissance d’objets utilisant MobileNet et Python avec une belle interface utilisateur pour interagir avec les scripts python. On pourra facilement former des modèles et les classer. Cela fonctionne sur les bases en temps réel

On essayera d’utiliser cette application pour détecter les objets dans la face arrière du candidat, on va modifier le comportement de l’application on choisissant des objets spécifiques à interdire durant le passage d’examen.

Application desktop pour la reconnaissance faciale

Reconnaître et manipuler les visages à partir de Python ou de la ligne de commande avec la bibliothèque de reconnaissance faciale la plus simple au monde. Construit à l’aide de la reconnaissance faciale de pointe de dlib construite avec un apprentissage en profondeur. Le modèle a une précision de 99,38 % sur le benchmark étiquetés .

Cela fournit également un simple outil de ligne de commande face_recognition qui vous permet de faire la reconnaissance faciale sur un dossier d’images à partir de la ligne de commande !

On a choisit d’utiliser cette application pour pouvoir l’utiliser lors de la première connexion du candidat à l’examen.

Notre système va soit permettre à l’utilisateur de se connecter à l’examen ou pas, il se basera sur une base de donnée prédéfinis.

Application de reconnaissance vocale sur desktop avec python

Application permettant une reconnaissance vocale et de transcrire les mots prononcés en texte.

On a choisit d’utiliser cette application pour pouvoir reconnaitre les mots prononcés lors du passage de l’examen par le candidat et interdire ainsi des mots spécifiques susceptible d’être des indicatifs de triche.

Project Description

Problem Definition
Lors du passage d’une épreuve plusieurs candidats essaye de trouver des manières intelligentes et intuitif pour essayer de tricher, plusieurs systèmes ont été mis en place pour un contrôle efficace mais il existe diverses manières de contourner le système.
Et c’est là d’où vient notre problématique principale.
De ce fait on devrait établir un maximum de scénarios évidents pour pouvoir bien contrôler le candidat.
Notre application à la tache de permettre de résoudre l’ensemble des problèmes rencontrées et d’établir les scénarios possibles touts en l’appliquant dans une application fonctionnelle et bien conçu.
Challenges & Motivation
Challenges:
- Comment connecter un pc avec un téléphone: C'est une étape qui nous a prie beaucoup de temps et qui nécessite l'installation d'un ensemble de composantes ainsi que la capacité de faire les développements nécessaires pour la connexion entre les deux dispositifs.
- Comment détecter les tentatives de triches de façon automatique: C'est la partie la plus essentiels dans notre projet qui nécessite le traitement d'un ensembles de scénarios possibles de triches.
Motivations:
- Découvrir le domaine des internets des objets.
- Utilisation des outils de reconnaissance (avec le machine Learning): Certes on a utilisé des fonctionnalités existantes sur le marché mais ça nous a permis de comprendre réellement le fonctionnement des composantes pour intégrer les adaptations nécessaires à nos cas d'utilisations.
Real and Complete Usecases

Lien vers le cas d’utilisation:  Detection_usecase

1/ Scénario permettant au système de vérifier si un candidat essaye de se déplacer durant l’examen

  • Système va essayer de détecter un mouvement brusque du candidat
  • Système va envoyer un avertissement au candidat s’il détecte un mouvement suspicieux.

2/ Scénario permettant la détection de présence des personnes et d’empêcher le candidat d’être aidée par cette personne.

  • Système va essayer de détecter une personne autour du candidat
  • Si une personne est détectée un avertissement va s’afficher pour empêcher le candidat de continuez de passer l’examen

3/ Scénario permettant au système de vérifier la présence des objets non autorisées et d’empêcher au candidat de les utiliser.

  • Système va essayer de détecter un objet non autorisé autour du candidat
  • Système va essayer de détecter un objet non autorisé autour du candidat
    • Si un objet non autorisé est détecté un avertissement va s’afficher pour empêcher le candidat de continuer à passer l’examen
Technical Description

Vous trouverez ci-dessus le rapport final du projet avec la description technique au dernier chapitre

Hardware

Materials
ImageNamePart NumberPriceCountLink
Samsung SM-A515F (Téléphone)13501🛒
HP PAVILON GAMING 15 (PC)113001🛒
Schematic

Software

Arduino Code

from datetime import time

import speech_recognition
import threading
import socket
import face_recognition
import cv2
import numpy as np
import os
import time
import sys
from collections import Counter
import tkinter
from tkinter import messagebox
from tkinter import *
video_capture = cv2.VideoCapture(0)
tempsattente = 10
temps_total = 10 * 1
os.system("cls")

 # Reconnaissance faciale prie de https://holypython.com/face-recognition-on-screen-capture-with-cv2/
def face_recognitions(etats, connex_mode):
    path = 'pictures'

    known_face_encodings = []
    for file in os.listdir(path):
        # Check whether file is an jpg format or not
        if file.endswith(".jpg"):
            file_path = f"{path}/{file}"
            img_file_recog = face_recognition.load_image_file(file_path)
            known_face_encodings.append(face_recognition.face_encodings(img_file_recog)[0])
    known_face_names = [
        "Mehdi",
        "Mohammed",
    ]

    # Initialize some variables
    face_locations = []
    face_names = []
    process_this_frame = True
    t_end = time.time() + tempsattente
    if connex_mode == 1 :
        t_end = time.time() + 10
    total_names = []
    all_frames = 0
    while time.time() < t_end:
        # Grab a single frame of video
        ret, frame = video_capture.read()

        # Resize frame of video to 1/4 size for faster face recognition processing
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

        # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
        rgb_small_frame = small_frame[:, :, ::-1]

        # Only process every other frame of video to save time
        if process_this_frame:
            all_frames += 1
            # Find all the faces and face encodings in the current frame of video
            face_locations = face_recognition.face_locations(rgb_small_frame)
            face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

            face_names = []
            for face_encoding in face_encodings:
                # See if the face is a match for the known face(s)
                matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
                name = "Unknown"

                # Or instead, use the known face with the smallest distance to the new face
                face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
                best_match_index = np.argmin(face_distances)
                if matches[best_match_index]:
                    name = known_face_names[best_match_index]
                face_names.append(name)

        process_this_frame = not process_this_frame

        # Display the results
        for (top, right, bottom, left), name in zip(face_locations, face_names):
            # Scale back up face locations since the frame we detected in was scaled to 1/4 size
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4


# code ajouté


            total_names.append(name)
    occurence_element = []
    returned_name = ""
    error_state = "tb"
    if total_names:
        unique_total_names = np.unique(total_names)
        occurence_count = Counter(total_names)
        returned_name = occurence_count.most_common(1)[0][0]
        for i in range(len(unique_total_names)):
            occurence_element.append(total_names.count(unique_total_names[i]) / len(total_names))
        for i in range(len(unique_total_names)):
# traitement de pourcentage des tolérences des erreurs
            if unique_total_names[i] == returned_name and occurence_element[i] <=0.2:
                error_state = "abs"
            if unique_total_names[i] != returned_name:
                if unique_total_names[i] == "Unknown":
                    if occurence_element[i] >= 0.2:
                        error_state = "unk"
                else:
                    if occurence_element[i] > 0:
                        error_state = "nau"
    if len(total_names) / all_frames < 0.5 :
        error_state = "abs"
    if connex_mode == 1:
        etats[1] = returned_name
        etats[2] = error_state
    else:
        etats[0][2] = error_state

# Reconnaissance vocale


def speech_recognitions(etats):

    recognizer = speech_recognition.Recognizer()
    # Code ajouté pour les mots clés interdits
    speech_keywords = ["question", "reponse", "réponse", "réponds", "questions"]
    said_stuff = []
    t_end = time.time() + tempsattente
    # Code ajouté
    while time.time() < t_end:
    # Code prie du lien https://www.youtube.com/watch?v=9GJ6XeB-vMg&t=336s&ab_channel=NeuralNine
        try:
            with speech_recognition.Microphone() as mic:
                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)
                text = recognizer.recognize_google(audio, language="fr_FR")
                text = text.lower()
                said_stuff.append(text)
        except:
            continue
    flag5 = 0
    for sentence in said_stuff:
        for keyword in speech_keywords:
            if keyword in sentence:
                flag5 = 1
    etats[0] = flag5

# Reconnaissance des objets :Code prie du lien https://www.youtube.com/watch?v=HXDD7-EnGBY&t=1499s&ab_channel=Murtaza%27sWorkshop-RoboticsandAI


def object_detection(etats):
    detected_object = []
    classFile = 'coco.names'
    with open(classFile, 'rt') as f:
        classNames = (f.read().rstrip('\n').split('\n'))
    configPath = 'ssd_mobilenet_v3_large_coco_2020_01_14.pbtxt'
    weightsPath = 'frozen_inference_graph.pb'

    net = cv2.dnn_DetectionModel(weightsPath, configPath)
    net.setInputSize(320, 320)
    net.setInputScale(1.0 / 127.5)
    net.setInputMean((127.5, 127.5, 127.5))
    net.setInputSwapRB(True)
    all_stuff_detected = []
    t_end = time.time() + tempsattente
    while time.time() < t_end:
        success, img = video_capture.read()
        classIds, confs, bbox = net.detect(img, confThreshold=0.5)
        detected_object_i = []
        if len(classIds) != 0:
            for classId, confidence, box in zip(classIds.flatten(), confs.flatten(), bbox):
                if classId <= 80:
                    cv2.rectangle(img, box, color=(0, 255, 0), thickness=2)
                    cv2.putText(img, classNames[classId - 1], (box[0] + 10, box[1] + 40),
                                cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
                    cv2.putText(img, str(round(confidence * 100, 2)), (box[0] + 200, box[1] + 30),
                                cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
                    detected_object_i.append(classNames[classId-1])
                    all_stuff_detected.append(classNames[classId-1])
# code ajouté
        detected_object.append(detected_object_i)

    objects_dectetcetd, number_detected = np.unique(all_stuff_detected,return_counts=True)
    etats[3] = "tb"
    flag_tel = 0
    for i in range(len(objects_dectetcetd)):
        if objects_dectetcetd[i] in ["book"] and \
                number_detected[i] / len(detected_object) >= 0.5:
            etats[3] = "livre"
        if objects_dectetcetd[i] in ["cell phone"]:
            flag_tel = 1
            if (number_detected[i]/len(detected_object) < 0.1):
                etats[3] = "tel1"
            if (number_detected[i]/len(detected_object) >= 1.7):
                etats[3] = "tel2"
        if objects_dectetcetd[i] in ["laptop", "keyboard"] and\
                number_detected[i]/len(detected_object) >= 0.5:
            etats[3] = "pc"
    if flag_tel == 0 and etats[3] == "tb":
        etats[3] = "tel1"

# code ajouté

root = Tk()
# Interface de l'application
root.title("The exam App")
root.geometry("400x600")
mylabel1 = Label(root, text="The system is trying to identify you")
mylabel1.pack()
root.update()

etats = [0, "", "tb", "nothing", 0, "nothing"]

flag2 = 0
while flag2 == 0:
    face_recognitions(etats, 1)
    if etats[1] and etats[1] != "Unknown" and etats[2] == "tb":
        flag2 = 1
    else:
        mylabel2 = Label(root, text="The connexion is not established either we could not identify you or someone else is present,"
              " try to be somewhere alone")
        mylabel2.pack()
        root.update()

mylabel = Label(root, text="Bienvenue Mr/Mme : " + etats[1])
mylabel.pack()
root.update()
#code de la connexion pc téléphone prie du lien
#https://gist.githubusercontent.com/MinaGabriel/c97b7a22c40c94b283723c7226dc9b68/raw/6ade3a6c459150ee31b26ce3ef2d9d61db55ecd9/gistfile1.txt

HOST = '192.168.137.1'
PORT = 8888

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind((HOST, PORT))
except socket.error as err:
    print('Bind Failed, Error Code: ' + str(err[0]) + ', Message: ' + err[1])
    sys.exit()


s.listen(10)

# Recupération des données envoyées par le téléphone ajouté par nous


def listen(phone_id, etats):
    str_phone_id = ''.join([phone_id])
    time_end = time.time() + tempsattente
    all_stuff_detected = []
    detected_object = []
    accelo = 0
    while time.time() < time_end:
        try:
            conn, addr = s.accept()
            received_id = addr[0]
            if str_phone_id == received_id:
                buf = conn.recv(64)
                received_object = buf.decode('ascii').split("|")
                detected_objects = received_object[0].split(",")
                if "Motion" in received_object[1]:
                    accelo += 1
                detected_object_i = []
                for obj in detected_objects :
                    detected_object_i.append(obj)
                    all_stuff_detected.append(obj)
                detected_object.append(detected_object_i)
        except:
            continue
    objects_dectetcetd, number_detected = np.unique(all_stuff_detected, return_counts=True)
    etats[0][5] = "tb"
    for i in range(len(objects_dectetcetd)):
        if objects_dectetcetd[i] in ["book"] and \
                number_detected[i] / len(detected_object) >= 0.1:
            etats[0][5] = "livre"
        elif objects_dectetcetd[i] in ["cell phone"] and \
                number_detected[i] / len(detected_object) >= 0.1:
            etats[0][5] = "tel"
        elif objects_dectetcetd[i] in ["laptop", "keyboard", "tv"] and \
                number_detected[i] / len(detected_object) >= 2:
            etats[0][5] = "pc"
        elif objects_dectetcetd[i] in ["person"] and \
                number_detected[i] / len(detected_object) >= 0.5:
            etats[0][5] = "person"
    etats[0][4] = 0
    if detected_object:
        if accelo / len(detected_object) > 0.5:
            etats[0][4] = 1
    s.close()

# Connexion du téléphone avec le pc tout le code a été ajouté par nous


def connex_test():
    flag_some = 0
    while 1:
        conn, addr = s.accept()
        buf = conn.recv(64)
        if buf.decode('ascii') == "connexion_established":
            mylabel4 = Label(root, text="The connexion has been established with the phone")
            mylabel4.pack()
            root.update()
            return addr[0]
        if flag_some == 0:
            mylabel5 = Label(root, text="No connection with phone, try closing the app and opening it again.")
            flag_some = 1
            mylabel5.pack()
            root.update()


mylabel6 = Label(root, text="You can enter the mobile app now")
mylabel6.pack()
root.update()
id_phone = connex_test()

#Traitement de l'ensemble des scénarios de triches possible tout le code a été ajouté par nous

time_end = time.time() + temps_total
while time.time() < time_end:
    p1 = threading.Thread(target=speech_recognitions, args=([etats]))
    p4 = threading.Thread(target=listen, args=(id_phone, [etats]))
    p2 = threading.Thread(target=face_recognitions, args=([etats], 0))
    p3 = threading.Thread(target=object_detection, args=[etats])
    p4.start()
    p1.start()
    p1_waiting_time = time.time() + tempsattente
    p2.start()
    p3.start()
    time.sleep(20)
    root.update()
    # Leave
    if etats[2] == "abs" and etats[4] == 1:
        messagebox.showwarning("Warning!!!", "You are trying to leave !")
        root.update()
        break
    # Person detected
    elif etats[2] == 'unk' or etats[2] == 'nau' or (etats[0] == 1 and etats[5] == "person"):
        messagebox.showwarning("Warning!!!", "You are trying to cheat, a non authorized person has been detected")
        root.update()
        break
    # Object detected
    elif etats[5] == "livre" or etats[5] == "tel" or etats[5] == "pc" or etats[3] == 'tel2':
        messagebox.showwarning("Warning!!!", "You are trying to sheet, an non authorized object has been detected")
        root.update()
        break
    # Phone not adjusted
    elif etats[3] == 'tel1':
        messagebox.showwarning("Warning!!!", "Your phone is not adjusted")
        root.update()
        break


video_capture.release()

 # Reconnaissance vocale : code prie du lien 
def speech_recognitions(etats):

    recognizer = speech_recognition.Recognizer()
    speech_keywords = ["question", "reponse", "réponse", "réponds", "questions"]
    said_stuff = []
    t_end = time.time() + tempsattente
    while time.time() < t_end:
        try:
            with speech_recognition.Microphone() as mic:
                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)
                text = recognizer.recognize_google(audio, language="fr_FR")
                text = text.lower()
                said_stuff.append(text)
        except:
            continue
    flag5 = 0
    for sentence in said_stuff:
        for keyword in speech_keywords:
            if keyword in sentence:
                flag5 = 1
    etats[0] = flag5


def object_detection(etats):
    detected_object = []
    classFile = 'coco.names'
    with open(classFile, 'rt') as f:
        classNames = (f.read().rstrip('\n').split('\n'))
    configPath = 'ssd_mobilenet_v3_large_coco_2020_01_14.pbtxt'
    weightsPath = 'frozen_inference_graph.pb'

    net = cv2.dnn_DetectionModel(weightsPath, configPath)
    net.setInputSize(320, 320)
    net.setInputScale(1.0 / 127.5)
    net.setInputMean((127.5, 127.5, 127.5))
    net.setInputSwapRB(True)
    all_stuff_detected = []
    t_end = time.time() + tempsattente
    while time.time() < t_end:
        success, img = video_capture.read()
        classIds, confs, bbox = net.detect(img, confThreshold=0.5)
        detected_object_i = []
        if len(classIds) != 0:
            for classId, confidence, box in zip(classIds.flatten(), confs.flatten(), bbox):
                if classId <= 80:
                    cv2.rectangle(img, box, color=(0, 255, 0), thickness=2)
                    cv2.putText(img, classNames[classId - 1], (box[0] + 10, box[1] + 40),
                                cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
                    cv2.putText(img, str(round(confidence * 100, 2)), (box[0] + 200, box[1] + 30),
                                cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
                    detected_object_i.append(classNames[classId-1])
                    all_stuff_detected.append(classNames[classId-1])
        detected_object.append(detected_object_i)

    objects_dectetcetd, number_detected = np.unique(all_stuff_detected,return_counts=True)
    etats[3] = "tb"
    flag_tel = 0
    for i in range(len(objects_dectetcetd)):
        if objects_dectetcetd[i] in ["book"] and \
                number_detected[i] / len(detected_object) >= 0.5:
            etats[3] = "livre"
        if objects_dectetcetd[i] in ["cell phone"]:
            flag_tel = 1
            if (number_detected[i]/len(detected_object) < 0.1):
                etats[3] = "tel1"
            if (number_detected[i]/len(detected_object) >= 1.7):
                etats[3] = "tel2"
        if objects_dectetcetd[i] in ["laptop", "keyboard"] and\
                number_detected[i]/len(detected_object) >= 0.5:
            etats[3] = "pc"
    if flag_tel == 0 and etats[3] == "tb":
        etats[3] = "tel1"

root = Tk()
root.title("The exam App")
root.geometry("400x600")
mylabel1 = Label(root, text="The system is trying to identify you")
mylabel1.pack()
root.update()

etats = [0, "", "tb", "nothing", 0, "nothing"]

flag2 = 0
while flag2 == 0:
    face_recognitions(etats, 1)
    if etats[1] and etats[1] != "Unknown" and etats[2] == "tb":
        flag2 = 1
    else:
        mylabel2 = Label(root, text="The connexion is not established either we could not identify you or someone else is present,"
              " try to be somewhere alone")
        mylabel2.pack()
        root.update()

mylabel = Label(root, text="Bienvenue Mr/Mme : " + etats[1])
mylabel.pack()
root.update()

HOST = '192.168.137.1'
PORT = 8888

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind((HOST, PORT))
except socket.error as err:
    print('Bind Failed, Error Code: ' + str(err[0]) + ', Message: ' + err[1])
    sys.exit()


s.listen(10)


def listen(phone_id, etats):
    str_phone_id = ''.join([phone_id])
    time_end = time.time() + tempsattente
    all_stuff_detected = []
    detected_object = []
    accelo = 0
    while time.time() < time_end:
        try:
            conn, addr = s.accept()
            received_id = addr[0]
            if str_phone_id == received_id:
                buf = conn.recv(64)
                received_object = buf.decode('ascii').split("|")
                detected_objects = received_object[0].split(",")
                if "Motion" in received_object[1]:
                    accelo += 1
                detected_object_i = []
                for obj in detected_objects :
                    detected_object_i.append(obj)
                    all_stuff_detected.append(obj)
                detected_object.append(detected_object_i)
        except:
            continue
    objects_dectetcetd, number_detected = np.unique(all_stuff_detected, return_counts=True)
    etats[0][5] = "tb"
    for i in range(len(objects_dectetcetd)):
        if objects_dectetcetd[i] in ["book"] and \
                number_detected[i] / len(detected_object) >= 0.1:
            etats[0][5] = "livre"
        elif objects_dectetcetd[i] in ["cell phone"] and \
                number_detected[i] / len(detected_object) >= 0.1:
            etats[0][5] = "tel"
        elif objects_dectetcetd[i] in ["laptop", "keyboard", "tv"] and \
                number_detected[i] / len(detected_object) >= 2:
            etats[0][5] = "pc"
        elif objects_dectetcetd[i] in ["person"] and \
                number_detected[i] / len(detected_object) >= 0.5:
            etats[0][5] = "person"
    etats[0][4] = 0
    if detected_object:
        if accelo / len(detected_object) > 0.5:
            etats[0][4] = 1
    s.close()


def connex_test():
    flag_some = 0
    while 1:
        conn, addr = s.accept()
        buf = conn.recv(64)
        if buf.decode('ascii') == "connexion_established":
            mylabel4 = Label(root, text="The connexion has been established with the phone")
            mylabel4.pack()
            root.update()
            return addr[0]
        if flag_some == 0:
            mylabel5 = Label(root, text="No connection with phone, try closing the app and opening it again.")
            flag_some = 1
            mylabel5.pack()
            root.update()


mylabel6 = Label(root, text="You can enter the mobile app now")
mylabel6.pack()
root.update()
id_phone = connex_test()


time_end = time.time() + temps_total
while time.time() < time_end:
    p1 = threading.Thread(target=speech_recognitions, args=([etats]))
    p4 = threading.Thread(target=listen, args=(id_phone, [etats]))
    p2 = threading.Thread(target=face_recognitions, args=([etats], 0))
    p3 = threading.Thread(target=object_detection, args=[etats])
    p4.start()
    p1.start()
    p1_waiting_time = time.time() + tempsattente
    p2.start()
    p3.start()
    time.sleep(20)
    root.update()
    # Leave
    if etats[2] == "abs" and etats[4] == 1:
        messagebox.showwarning("Warning!!!", "You are trying to leave !")
        root.update()
        break
    # Person detected
    elif etats[2] == 'unk' or etats[2] == 'nau' or (etats[0] == 1 and etats[5] == "person"):
        messagebox.showwarning("Warning!!!", "You are trying to cheat, a non authorized person has been detected")
        root.update()
        break
    # Object detected
    elif etats[5] == "livre" or etats[5] == "tel" or etats[5] == "pc" or etats[3] == 'tel2':
        messagebox.showwarning("Warning!!!", "You are trying to sheet, an non authorized object has been detected")
        root.update()
        break
    # Phone not adjusted
    elif etats[3] == 'tel1':
        messagebox.showwarning("Warning!!!", "Your phone is not adjusted")
        root.update()
        break


video_capture.release()
/*
 * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* code de détection des objets sur android Tensorflow prie du lien https://github.com/tensorflow/examples */

package org.tensorflow.lite.examples.detection;

import static java.lang.Math.abs;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.ImageReader.OnImageAvailableListener;
import android.os.Build;
import android.os.SystemClock;
import android.util.Size;
import android.util.TypedValue;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.RequiresApi;

import java.io.PrintWriter;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.tensorflow.lite.examples.detection.customview.OverlayView;
import org.tensorflow.lite.examples.detection.customview.OverlayView.DrawCallback;
import org.tensorflow.lite.examples.detection.env.BorderedText;
import org.tensorflow.lite.examples.detection.env.ImageUtils;
import org.tensorflow.lite.examples.detection.env.Logger;
import org.tensorflow.lite.examples.detection.tflite.Detector;
import org.tensorflow.lite.examples.detection.tflite.TFLiteObjectDetectionAPIModel;
import org.tensorflow.lite.examples.detection.tracking.MultiBoxTracker;

/**
 * An activity that uses a TensorFlowMultiBoxDetector and ObjectTracker to detect and then track
 * objects.
 */
public class DetectorActivity extends CameraActivity implements OnImageAvailableListener, SensorEventListener {
  private static final Logger LOGGER = new Logger();

  // Configuration values for the prepackaged SSD model.
  private static final int TF_OD_API_INPUT_SIZE = 300;
  private static final boolean TF_OD_API_IS_QUANTIZED = true;
  private static final String TF_OD_API_MODEL_FILE = "detect.tflite";
  private static final String TF_OD_API_LABELS_FILE = "labelmap.txt";
  private static final DetectorMode MODE = DetectorMode.TF_OD_API;
  // Minimum detection confidence to track a detection.
  private static final float MINIMUM_CONFIDENCE_TF_OD_API = 0.5f;
  private static final boolean MAINTAIN_ASPECT = false;
  private static final Size DESIRED_PREVIEW_SIZE = new Size(640, 480);
  private static final boolean SAVE_PREVIEW_BITMAP = false;
  private static final float TEXT_SIZE_DIP = 10;
  OverlayView trackingOverlay;
  private Integer sensorOrientation;

  private Detector detector;

  private long lastProcessingTimeMs;
  private Bitmap rgbFrameBitmap = null;
  private Bitmap croppedBitmap = null;
  private Bitmap cropCopyBitmap = null;

  private boolean computingDetection = false;

  private long timestamp = 0;

  private Matrix frameToCropTransform;
  private Matrix cropToFrameTransform;

  private MultiBoxTracker tracker;

  private BorderedText borderedText;


  private Socket client;
  private PrintWriter printwriter;

  private String motionexists = "";
  private int flag123 = 0;

  @Override
  public void onPreviewSizeChosen(final Size size, final int rotation) {
    final float textSizePx =
        TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, getResources().getDisplayMetrics());
    borderedText = new BorderedText(textSizePx);
    borderedText.setTypeface(Typeface.MONOSPACE);

    tracker = new MultiBoxTracker(this);

    int cropSize = TF_OD_API_INPUT_SIZE;

    try {
      detector =
          TFLiteObjectDetectionAPIModel.create(
              this,
              TF_OD_API_MODEL_FILE,
              TF_OD_API_LABELS_FILE,
              TF_OD_API_INPUT_SIZE,
              TF_OD_API_IS_QUANTIZED);
      cropSize = TF_OD_API_INPUT_SIZE;
    } catch (final IOException e) {
      e.printStackTrace();
      LOGGER.e(e, "Exception initializing Detector!");
      Toast toast =
          Toast.makeText(
              getApplicationContext(), "Detector could not be initialized", Toast.LENGTH_SHORT);
      toast.show();
      finish();
    }

    previewWidth = size.getWidth();
    previewHeight = size.getHeight();

    sensorOrientation = rotation - getScreenOrientation();
    LOGGER.i("Camera orientation relative to screen canvas: %d", sensorOrientation);

    LOGGER.i("Initializing at size %dx%d", previewWidth, previewHeight);
    rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
    croppedBitmap = Bitmap.createBitmap(cropSize, cropSize, Config.ARGB_8888);

    frameToCropTransform =
        ImageUtils.getTransformationMatrix(
            previewWidth, previewHeight,
            cropSize, cropSize,
            sensorOrientation, MAINTAIN_ASPECT);

    cropToFrameTransform = new Matrix();
    frameToCropTransform.invert(cropToFrameTransform);

    trackingOverlay = (OverlayView) findViewById(R.id.tracking_overlay);
    trackingOverlay.addCallback(
        new DrawCallback() {
          @Override
          public void drawCallback(final Canvas canvas) {
            tracker.draw(canvas);
            if (isDebug()) {
              tracker.drawDebug(canvas);
            }
          }
        });

    tracker.setFrameConfiguration(previewWidth, previewHeight, sensorOrientation);
  }
/* code prie du lien : https://www.youtube.com/watch?v=qU1woglr_yU et représente une fonction de l''envoi des messages par le socket */
  private void sendMessage(String message_sortant) {
    try {
      client = new Socket("192.168.137.1", 8888);
      printwriter = new PrintWriter(client.getOutputStream(), true);
      printwriter.write(message_sortant); // write the message to output stream
      printwriter.close();
      printwriter.flush();
      client.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  protected void processImage() {
    ++timestamp;
    final long currTimestamp = timestamp;
    trackingOverlay.postInvalidate();
    // No mutex needed as this method is not reentrant.
    if (computingDetection) {
      readyForNextImage();
      return;
    }
    computingDetection = true;
    LOGGER.i("Preparing image " + currTimestamp + " for detection in bg thread.");

    rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, 0, previewWidth, previewHeight);

    readyForNextImage();

    final Canvas canvas = new Canvas(croppedBitmap);
    canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null);
    // For examining the actual TF input.
    if (SAVE_PREVIEW_BITMAP) {
      ImageUtils.saveBitmap(croppedBitmap);
    }

    runInBackground(
        new Runnable() {
          /* code ajouté declaration des sensors */
          private SensorManager sensorManager;
          private Sensor sensor;
          @RequiresApi(api = Build.VERSION_CODES.O)
          @Override
          public void run() {
            LOGGER.i("Running detection on image " + currTimestamp);
            final long startTime = SystemClock.uptimeMillis();
            List stuff_to_send = new ArrayList();

            final List results = detector.recognizeImage(croppedBitmap);
            lastProcessingTimeMs = SystemClock.uptimeMillis() - startTime;

            cropCopyBitmap = Bitmap.createBitmap(croppedBitmap);
            final Canvas canvas = new Canvas(cropCopyBitmap);
            final Paint paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStyle(Style.STROKE);
            paint.setStrokeWidth(2.0f);
            /* etablir la connexion avec le pc */

            if (flag123 == 0) {
              sendMessage("connexion_established");
              flag123 = 1; }

            float minimumConfidence = MINIMUM_CONFIDENCE_TF_OD_API;
            switch (MODE) {
              case TF_OD_API:
                minimumConfidence = MINIMUM_CONFIDENCE_TF_OD_API;
                break;
            }

            final List mappedRecognitions =
                new ArrayList();

            for (final Detector.Recognition result : results) {
              final RectF location = result.getLocation();
              if (location != null && result.getConfidence() >= minimumConfidence) {
                canvas.drawRect(location, paint);

                cropToFrameTransform.mapRect(location);

                result.setLocation(location);
                mappedRecognitions.add(result);
                /* code ajouté rassembler les resultats détecter */

                stuff_to_send.add(result.getTitle());
              }
            }
                /* code prie du lien: https://www.youtube.com/watch?v=LsWJipo4knk :utiliser le sensor */

            sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            sensorManager.registerListener(DetectorActivity.this,sensor,sensorManager.SENSOR_DELAY_NORMAL);


                /* code ajouté envoyer le résultat détecter à chaque moment*/

            String message_sortant = String.join(",", stuff_to_send);
            message_sortant = message_sortant + "|" + motionexists;
            motionexists = "";
            sendMessage(message_sortant);



            tracker.trackResults(mappedRecognitions, currTimestamp);
            trackingOverlay.postInvalidate();

            computingDetection = false;

            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    showFrameInfo(previewWidth + "x" + previewHeight);
                    showCropInfo(cropCopyBitmap.getWidth() + "x" + cropCopyBitmap.getHeight());
                    showInference(lastProcessingTimeMs + "ms");
                  }
                });
          }
        });
  }

  @Override
  protected int getLayoutId() {
    return R.layout.tfe_od_camera_connection_fragment_tracking;
  }

  @Override
  protected Size getDesiredPreviewFrameSize() {
    return DESIRED_PREVIEW_SIZE;
  }
                /* code ajouté fontion qui jugent s'il y'a un mouvement brusque ou non */

  @Override
  public void onSensorChanged(SensorEvent event) {
    if (abs(event.values[0])>=1.5 && abs(event.values[1])>=1.5) {
      motionexists = "Motion Detected";
    }
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {

  }

  // Which detection model to use: by default uses Tensorflow Object Detection API frozen
  // checkpoints.
  private enum DetectorMode {
    TF_OD_API;
  }

  @Override
  protected void setUseNNAPI(final boolean isChecked) {
    runInBackground(
        () -> {
          try {
            detector.setUseNNAPI(isChecked);
          } catch (UnsupportedOperationException e) {
            LOGGER.e(e, "Failed to set \"Use NNAPI\".");
            runOnUiThread(
                () -> {
                  Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
                });
          }
        });
  }

  @Override
  protected void setNumThreads(final int numThreads) {
    runInBackground(() -> detector.setNumThreads(numThreads));
  }
}

External Services

Application mobile Android pour la détection des objets

On a choisit d’utiliser une application android déjà développer en java et de l’adapter avec notre besoin. 

Il s’agit d’une application de caméra qui détecte en continu les objets (boîtes englobantes et classes)
dans les images vues par la caméra arrière de l’appareil, à l’aide d’un modèle SSD MobileNet quantifié
formé sur l’ensemble de données COCO. Ces instructions vous guident tout au long de la création et de
l’exécution de la démo sur un appareil Android.

On essayera d’utiliser cette application pour détecter les objets dans la face avant du candidat, on va modifier le comportement de l’application on choisissant des objets spécifiques à interdire durant le passage d’examen (personne, document, pc, etc …)

Application desktop pour la détection des objets sur Desktop

On a choisit d’utiliser une application déjà développer en python et de l’adapter avec notre besoin
C’est un modèle de reconnaissance d’objets utilisant MobileNet et Python avec une belle interface utilisateur pour interagir avec les scripts python. On pourra facilement former des modèles et les classer. Cela fonctionne sur les bases en temps réel

On essayera d’utiliser cette application pour détecter les objets dans la face arrière du candidat, on va modifier le comportement de l’application on choisissant des objets spécifiques à interdire durant le passage d’examen.

Application desktop pour la reconnaissance faciale

Reconnaître et manipuler les visages à partir de Python ou de la ligne de commande avec la bibliothèque de reconnaissance faciale la plus simple au monde. Construit à l’aide de la reconnaissance faciale de pointe de dlib construite avec un apprentissage en profondeur. Le modèle a une précision de 99,38 % sur le benchmark étiquetés .

Cela fournit également un simple outil de ligne de commande face_recognition qui vous permet de faire la reconnaissance faciale sur un dossier d’images à partir de la ligne de commande !

On a choisit d’utiliser cette application pour pouvoir l’utiliser lors de la première connexion du candidat à l’examen.

Notre système va soit permettre à l’utilisateur de se connecter à l’examen ou pas, il se basera sur une base de donnée prédéfinis.

Application de reconnaissance vocale sur desktop avec python

Application permettant une reconnaissance vocale et de transcrire les mots prononcés en texte.

On a choisit d’utiliser cette application pour pouvoir reconnaitre les mots prononcés lors du passage de l’examen par le candidat et interdire ainsi des mots spécifiques susceptible d’être des indicatifs de triche.