apps/camera/app.py est une application utilitaire permettant de visualiser le flux vidéo d'une webcam branchée à l'ordinateur, et d'enregistrer des photos. C'est une démonstration brillante de la capacité de GrimOS à s'interfacer avec du matériel externe.
cv2 (OpenCV) : Cette application est l'une des rares à nécessiter une dépendance lourde externe. Elle utilise cv2.VideoCapture(0) pour capturer le flux matériel de la première caméra détectée par le système Linux (/dev/video0).window.after(15)), capturer l'image de la webcam, convertir ses couleurs de BGR (le format d'OpenCV) vers RGB, puis transformer cette matrice en une image compatible avec l'interface via ImageTk.PhotoImage.cap.release()) lorsque l'utilisateur ferme la fenêtre, évitant ainsi un crash matériel persistant.cv2.VideoWriter, on pourrait ajouter un bouton rouge "REC" permettant d'enregistrer des vidéos au format MP4 directement sur le disque.import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
import os
import datetime
def start(window, app_manager=None, **kwargs):
# Essayons d'importer cv2. S'il n'est pas là, on affiche un message d'erreur clair.
try:
import cv2
except ImportError:
tk.Label(window, text="La librairie OpenCV n'est pas installée.\n\nVeuillez exécuter :\nsudo apt-get install python3-opencv\n\npuis relancez l'application.", fg="red", font=("Arial", 12)).pack(expand=True)
return
top_frame = tk.Frame(window, bg="lightgray", height=40)
top_frame.pack(side="top", fill="x")
icon_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "icons")
window.icons = getattr(window, "icons", {})
if 'btn_camera' not in window.icons:
ipath = os.path.join(icon_dir, "btn_camera.png")
if os.path.exists(ipath):
window.icons['btn_camera'] = tk.PhotoImage(file=ipath)
video_container = tk.Frame(window, bg="black")
video_container.pack(fill="both", expand=True)
video_lbl = tk.Label(video_container, bg="black")
video_lbl.pack(expand=True)
try:
cap = cv2.VideoCapture(0)
except Exception as e:
messagebox.showerror("Erreur", f"Impossible d'accéder à la webcam : {e}")
return
if not cap.isOpened():
messagebox.showerror("Erreur", "Aucune webcam détectée sur /dev/video0.")
return
def update_frame():
if not window.winfo_exists():
cap.release()
return
ret, frame = cap.read()
if ret:
# OpenCV utilise BGR, ImageTk nécessite RGB
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = Image.fromarray(frame_rgb)
imgtk = ImageTk.PhotoImage(image=img)
video_lbl.imgtk = imgtk # garder la référence
video_lbl.configure(image=imgtk)
window.after(30, update_frame)
def take_photo():
ret, frame = cap.read()
if ret:
img_dir = os.path.expanduser("~/Images")
os.makedirs(img_dir, exist_ok=True)
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"photo_{timestamp}.jpg"
filepath = os.path.join(img_dir, filename)
cv2.imwrite(filepath, frame)
if app_manager and hasattr(app_manager, 'desktop'):
app_manager.desktop.show_toast(f"Photo sauvegardée :\n{filepath}")
btn_photo = tk.Button(top_frame, text=" Prendre une photo", image=window.icons.get('btn_camera'), compound="left", font=("Arial", 11, "bold"), bg="#4CAF50", fg="white", relief="flat", command=take_photo)
btn_photo.pack(side="left", padx=10, pady=5)
def on_destroy(event):
if str(event.widget) == str(window):
if cap.isOpened():
cap.release()
window.bind("<Destroy>", on_destroy)
update_frame()