Passer au contenu principal

scripte phyton

1. Introduction

Le système de détection de présence et de simulation d’activité a été conçu pour surveiller en temps réel la présence d’un utilisateur à l’aide d’une webcam. Lorsqu’un visage est détecté dans le champ de vision, le programme simule une activité (par exemple, un léger mouvement de souris et l’appui sur une touche) afin d’empêcher que l’ordinateur ne se mette en veille ou n’active l’économiseur d’écran.
Ce mécanisme est particulièrement utile dans les environnements où il est crucial de maintenir le poste actif, comme lors de présentations ou dans certains contextes professionnels.

2. Fonctionnalités Principales

  • Détection de Visage :
    Utilisation des classificateurs Haar d’OpenCV pour détecter un visage frontal et, en complément, un visage en profil. La détection est filtrée par la taille du visage pour n’agir que lorsque l’utilisateur est suffisamment proche.

  • Simulation d’Activité :
    En cas de détection d’un visage « proche » et si un intervalle défini s’est écoulé, l’application simule :

    • Un déplacement de la souris (vers la droite puis retour vers la gauche)
    • L’appui sur la touche Shift
      Cette simulation évite que l’ordinateur se mette en veille.
  • Journalisation :
    Le script écrit des messages horodatés dans le fichier camera_log.txt pour suivre l’exécution et faciliter le débogage en cas d’erreur (par exemple, en cas d’échec lors du chargement des classificateurs ou de la capture vidéo).

3. Code Source Complet

Voici le code source complet du script :

import cv2
import pyautogui
import time
import sys

# --- Configuration ---
MOVE_INTERVAL = 5          # Intervalle en secondes entre chaque simulation d'activité.
MOVE_DISTANCE = 10         # Distance en pixels pour le mouvement de la souris.
CASCADE_SCALE_FACTOR = 1.1 # Facteur d'échelle pour la détection des visages.
CASCADE_MIN_NEIGHBORS = 3  # Nombre minimum de voisins pour confirmer une détection.
MIN_FACE_AREA = 2500       # Surface minimale d'un visage pour le considérer "proche".
FRAME_SKIP = 2             # Traiter 1 frame sur 2 pour économiser les ressources.
FRAME_SLEEP = 0.1          # Délai entre le traitement de chaque frame.

def log_message(message):
    """Écrit un message horodaté dans le fichier de log 'camera_log.txt'."""
    with open("camera_log.txt", "a") as f:
        f.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")

def load_cascades():
    """
    Charge les classificateurs Haar pour la détection des visages (frontal et profil).
    Utilise les fichiers XML situés dans le dossier cv2.data.haarcascades.
    En cas d'erreur, enregistre le message dans le log et termine le programme.
    """
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    profile_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_profileface.xml')

    if face_cascade.empty():
        log_message("Erreur : Impossible de charger le classificateur pour les visages frontaux.")
        sys.exit("Erreur : Impossible de charger le classificateur pour les visages frontaux.")
    if profile_cascade.empty():
        log_message("Erreur : Impossible de charger le classificateur pour les profils de visages.")
        sys.exit("Erreur : Impossible de charger le classificateur pour les profils de visages.")

    return face_cascade, profile_cascade

def simulate_activity():
    """
    Simule un léger mouvement de la souris et une pression sur la touche 'shift'.
    Ce mouvement sert à éviter que l'ordinateur ne se mette en veille.
    """
    pyautogui.move(MOVE_DISTANCE, 0)   # Déplacement de la souris vers la droite.
    pyautogui.move(-MOVE_DISTANCE, 0)    # Retour de la souris vers la gauche.
    pyautogui.press('shift')             # Appui sur la touche 'shift'.

def main():
    # Journalisation du démarrage du programme.
    log_message("Démarrage du programme")
    
    # Chargement des classificateurs Haar.
    face_cascade, profile_cascade = load_cascades()

    # Initialisation de la capture vidéo via la caméra par défaut.
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        log_message("Erreur : Impossible d'ouvrir la caméra")
        sys.exit("Erreur : Impossible d'ouvrir la caméra")
    else:
        log_message("Caméra ouverte avec succès")

    # Réduction de la résolution pour améliorer les performances.
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

    last_move_time = time.time()
    frame_count = 0

    try:
        while True:
            ret, frame = cap.read()
            if not ret:
                log_message("Erreur lors de la capture de l'image")
                break

            frame_count += 1

            # Traiter uniquement 1 frame sur FRAME_SKIP pour réduire la charge CPU.
            if frame_count % FRAME_SKIP != 0:
                time.sleep(FRAME_SLEEP)
                continue

            # Conversion de l'image en niveaux de gris pour la détection.
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

            # Détection des visages (frontal et profil).
            faces = face_cascade.detectMultiScale(gray, scaleFactor=CASCADE_SCALE_FACTOR, minNeighbors=CASCADE_MIN_NEIGHBORS)
            profiles = profile_cascade.detectMultiScale(gray, scaleFactor=CASCADE_SCALE_FACTOR, minNeighbors=CASCADE_MIN_NEIGHBORS)

            face_detected_close = False

            # Vérification des visages frontaux.
            for (x, y, w, h) in faces:
                if w * h >= MIN_FACE_AREA:
                    face_detected_close = True
                    break

            # Si aucun visage frontal n'est détecté, vérification des profils.
            if not face_detected_close:
                for (x, y, w, h) in profiles:
                    if w * h >= MIN_FACE_AREA:
                        face_detected_close = True
                        break

            # Si un visage "proche" est détecté et que l'intervalle requis est écoulé, simuler l'activité.
            current_time = time.time()
            if face_detected_close and (current_time - last_move_time >= MOVE_INTERVAL):
                log_message("Visage détecté, simulation d'activité déclenchée.")
                simulate_activity()
                last_move_time = current_time

            time.sleep(FRAME_SLEEP)

    except KeyboardInterrupt:
        log_message("Interruption par l'utilisateur.")
    finally:
        cap.release()
        cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

4. Compilation en Exécutable (.exe) avec PyInstallerPyInstallerb

Pour que votre script puisse être utilisé sans dépendre de Python installé sur le poste final, vous pouvez le compiler en un exécutable (.exe) grâce à PyInstaller.

4.1. Pré-requis pour PyInstaller

  • Assurez-vous d'avoir installé PyInstaller. Vous pouvez l'installer via pip :
    pip install pyinstaller

4.2. Problème Spécifique : Inclusion des Fichiers de Cascade

Lorsqu'on exécute le script en Python, OpenCV utilise le dossier défini par cv2.data.haarcascades pour trouver les fichiers XML de détection.
Lors de la compilation avec PyInstaller, ces fichiers ne sont pas automatiquement inclus.
Si ces fichiers ne sont pas présents dans l'exécutable, vous obtiendrez l'erreur suivante dans votre log :

Erreur : Impossible de charger le classificateur pour les visages frontaux.

4.3. Solution : Utiliser l'Option --add-data

  1. Compiler avec PyInstaller en incluant le dossier des cascades :

    Ouvrez une invite de commande dans le répertoire contenant votre script et exécutez (en adaptant le chemin source) :

    pyinstaller --noconsole --onefile --add-data "C:\Users\g.gasser\AppData\Local\Programs\Python\Python313\Lib\site-packages\cv2\data;cv2\data" "camera (1).py"

    Explications :

    • --noconsole : L'exécutable ne crée pas de fenêtre de console.
    • --onefile : Génère un seul fichier exécutable.
    • --add-data "source;destination" :
      • source : Le chemin réel vers le dossier contenant les fichiers de cascade.
      • destination : Le nom du dossier dans l'exécutable (ici, nous utilisons cv2\data pour que cv2.data.haarcascades pointe correctement vers ces fichiers).
    • Le nom du script "camera (1).py" est entre guillemets pour gérer les espaces et parenthèses
  2. Vérifier le résultat :

    Une fois la compilation terminée, le fichier exécutable se trouve dans le dossier dist. Vous pouvez le lancer.
    Pour vérifier que tout fonctionne correctement, consultez le fichier camera_log.txt qui doit indiquer que la caméra a été ouverte et que le classificateur a été chargé sans erreur.