Advertisement
Paullux

Untitled

Jun 20th, 2023
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.29 KB | None | 0 0
  1. import os
  2. import platform
  3. import queue
  4. import random
  5. import sys
  6. import time
  7. import cv2
  8. import numpy as np
  9. import pyvirtualcam
  10. import threading
  11. from PIL import Image, ImageDraw, ImageFont
  12. from PyQt6.QtCore import Qt, QObject, pyqtSignal, QTimer
  13. from PyQt6.QtGui import QCloseEvent, QIcon, QImage, QKeyEvent, QPixmap, QColor, QPainter, QFont, QFontDatabase
  14. from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QComboBox, QPushButton
  15.  
  16. global columns_launched_queue, frame_queue, ascii_image_result_queue, rain_ascii_image_queue, drop_of_water_image_ascii_queue, virtual_frame_queue, running
  17.  
  18. class CameraApp(QMainWindow):
  19. cameraSelected = pyqtSignal(int)
  20. def __init__(self, matrix):
  21. self.matrix = matrix
  22. super().__init__()
  23. self.init_ui()
  24.  
  25. if getattr(sys, 'frozen', False):
  26. import pyi_splash
  27.  
  28. # Fermeture du splash screen
  29. pyi_splash.update_text('UI Loaded ...')
  30. pyi_splash.close()
  31.  
  32. print("entre dans la init de CameraApp")
  33. self.cap = None
  34. self.timer = QTimer()
  35.  
  36. def init_ui(self):
  37. print("entre dans init_ui()")
  38. self.setWindowTitle("CameraSelector")
  39. self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.FramelessWindowHint)
  40. self.wd = sys._MEIPASS if getattr(sys, 'frozen', False) else ''
  41. self.setWindowIcon(QIcon(os.path.join(self.wd, "icon-32.png")))
  42. self.layout = QVBoxLayout()
  43. self.central_widget = QWidget()
  44. self.camera_selector = QComboBox()
  45. self.camera_selector.addItem("Caméra non choisie")
  46. self.populate_camera_selector()
  47.  
  48. self.label = QLabel("Sélectionnez une caméra pour commencer")
  49.  
  50. # Créez le bouton et connectez-le à la méthode open_matrix_window
  51. self.open_matrix_button = QPushButton("Ouvrir Matrix")
  52. self.open_matrix_button.clicked.connect(self.camera_chosen)
  53.  
  54. # Ajoutez le bouton à votre interface utilisateur
  55. self.layout.addWidget(self.camera_selector)
  56. self.layout.addWidget(self.label)
  57. self.layout.addWidget(self.open_matrix_button)
  58. self.central_widget.setLayout(self.layout)
  59. self.setCentralWidget(self.central_widget)
  60.  
  61. def camera_chosen(self):
  62. index = self.camera_selector.currentIndex()
  63. if index == 0:
  64. self.label.setText("Veuillez choisir une caméra.") # Utilise setText pour mettre à jour le texte du QLabel
  65. return
  66. if self.cap is not None:
  67. self.cap.release()
  68. camera_names, camera_indices = self.get_available_cameras()
  69. camera_name = camera_names[index - 1]
  70. index = camera_indices[index - 1]
  71. self.label.setText(f"Matrix Launched with {camera_name}")
  72. self.cameraSelected.emit(index) # Émettre le signal avec l'index de la caméra sélectionnée
  73. self.close()
  74. print("Matrix Launched")
  75.  
  76. def populate_camera_selector(self):
  77. print("entre dans populate_camera_selector()")
  78. camera_names, camera_indices = self.get_available_cameras()
  79. for name, index in zip(camera_names, camera_indices):
  80. self.camera_selector.addItem(f"{name} (Index: {index})", index)
  81. pass
  82.  
  83. def get_available_cameras(self):
  84. print("entre dans get_available_cameras()")
  85. if sys.platform.startswith("linux"):
  86. camera_names, camera_indices = self.get_cameras_linux()
  87. elif sys.platform.startswith("win32"):
  88. camera_names, camera_indices = self.get_cameras_windows()
  89. elif sys.platform.startswith("darwin"): #macOS
  90. camera_names, camera_indices = self.get_cameras_mac()
  91. else:
  92. print("Plateforme non prise en charge")
  93. camera_names, camera_indices = [], []
  94.  
  95. return camera_names, camera_indices
  96.  
  97.  
  98. def get_cameras_mac(self):
  99. print("entre dans get_cameras_mac()")
  100. try:
  101. import Quartz
  102. except ImportError:
  103. print("Installez pyobjc avec 'pip install pyobjc'")
  104. return {}
  105.  
  106. camera_indices = []
  107. camera_names = []
  108.  
  109. for index, device in enumerate(Quartz.IORegistryIteratorCreateForMatchingService(Quartz.kIOMasterPortDefault, Quartz.CFDictionaryCreate(None, (Quartz.kIOUSBDeviceClassName,), (True,), 1))):
  110. camera_name = Quartz.IORegistryEntryGetName(device)
  111. if "infrared" in camera_name.lower() or "ir" in camera_name.lower():
  112. continue # Ignore the infrared camera
  113. camera_names.append(camera_name)
  114. camera_indices.append(index)
  115. return camera_names, camera_indices
  116.  
  117. def get_cameras_windows(self):
  118. print("entre dans get_cameras_windows()")
  119. try:
  120. from pygrabber.dshow_graph import FilterGraph
  121.  
  122. except ImportError:
  123. print("Installez pygrabber avec 'pip install pygrabber'")
  124. return {}
  125.  
  126. camera_indices = []
  127. camera_names = []
  128.  
  129. # Get a list of all connected HID devices
  130. devices = FilterGraph().get_input_devices()
  131.  
  132. camera_names, camera_indices = [], []
  133.  
  134.  
  135. for device_index, device_name in enumerate(devices):
  136. camera_names.append(device_name)
  137. camera_indices.append(device_index)
  138. return camera_names, camera_indices
  139.  
  140.  
  141. def get_cameras_linux(self):
  142. try:
  143. from v4l2py import Device
  144. except ImportError:
  145. print("Installez v4l2py avec 'pip install v4l2py'")
  146. return {}
  147.  
  148. devices = []
  149. camera_names = []
  150. camera_indices = []
  151. index = 0
  152.  
  153. while True:
  154. try:
  155. cap = cv2.VideoCapture(index)
  156. if cap.isOpened():
  157. devices.append(index)
  158. cap.release()
  159. else:
  160. print(f"Avertissement: Impossible d'ouvrir la caméra {index}")
  161. time.sleep(0.1)
  162. index += 1
  163. if index > 9:
  164. break
  165. except Exception as e:
  166. print(f"Erreur lors de l'ouverture des caméras: {e}")
  167. break
  168.  
  169. for index in devices:
  170. print(f"Récupération des informations de la caméra {index}")
  171. try:
  172. with Device.from_id(index) as cam:
  173. cam.open()
  174. camera_name = cam.info.card
  175. if camera_name not in camera_names:
  176. camera_names.append(camera_name)
  177. camera_indices.append(index)
  178. cam.close()
  179. except Exception as e:
  180. print(f"Erreur lors de l'accès à la caméra {index}: {e}")
  181.  
  182. return camera_names, camera_indices
  183.  
  184.  
  185. def closeEvent(self, event):
  186. print("entre dans closeEvent()")
  187. if self.timer.isActive():
  188. self.timer.stop()
  189.  
  190.  
  191. class Communicator(QObject):
  192. update_image_label_signal = pyqtSignal(QImage)
  193. def __init__(self, parent=None):
  194. super().__init__(parent)
  195.  
  196.  
  197. class Matrix(QMainWindow):
  198. def __init__(self):
  199. super().__init__()
  200. self.threads = []
  201.  
  202. self.wd = sys._MEIPASS if getattr(sys, 'frozen', False) else ''
  203. self.font_path = os.path.join(self.wd, '.', 'mtx.ttf')
  204.  
  205. global columns_launched_queue, frame_queue, ascii_image_result_queue, rain_ascii_image_queue, drop_of_water_image_ascii_queue, virtual_frame_queue, running
  206.  
  207. # Créez une file d'attente pour chaque variable partagée
  208. columns_launched_queue = queue.Queue()
  209. frame_queue = queue.Queue()
  210. ascii_image_result_queue = queue.Queue()
  211. rain_ascii_image_queue = queue.Queue()
  212. drop_of_water_image_ascii_queue = queue.Queue()
  213. virtual_frame_queue = queue.Queue()
  214. self.queues = [columns_launched_queue, frame_queue, ascii_image_result_queue, rain_ascii_image_queue, drop_of_water_image_ascii_queue, virtual_frame_queue]
  215.  
  216. running = True
  217.  
  218. self.communicator = Communicator()
  219.  
  220. if sys.platform == 'win32':
  221. import ctypes
  222. winVer = platform.win32_ver(release='')[0]
  223. try:
  224. if int(winVer) >= 10:
  225. ctypes.windll.shcore.SetProcessDpiAwareness(2)
  226. elif int(winVer) == 8:
  227. ctypes.windll.shcore.SetProcessDpiAwareness(1)
  228. else:
  229. ctypes.windll.user32.SetProcessDPIAware()
  230. except (ImportError, AttributeError, OSError):
  231. pass
  232.  
  233. self.counter = 0
  234. self.timer = QTimer(self)
  235. self.image_label = QLabel()
  236. self.timer.timeout.connect(self.update_counter)
  237. self.timer.start(1000)
  238.  
  239. # Définition des caractères à utiliser pour l'ASCII art
  240. #characters = ' ú.ù,:öøýü×Öų·ÈØÙÍб´¶¹º¼Â²ÇËÒÓ¾Ú'
  241.  
  242. self.rain_intensity = 0.5
  243. self.image_updated = ""
  244.  
  245. width, height = 854, 480
  246.  
  247. self.ascii_font_size_width = 20
  248. self.ascii_font_size_height = self.ascii_font_size_width * 9 / 16
  249.  
  250. self.font_path = os.path.join(self.wd, 'mtx.ttf')
  251. self.canvas_image = Image.new('RGB', (width, height), 'black')
  252. self.draw = ImageDraw.Draw(self.canvas_image)
  253. self.font = ImageFont.truetype(self.font_path, self.ascii_font_size_width)
  254.  
  255. # Variables partagées entre les threads
  256. self.ascii_image = ""
  257. ascii_image_result, rain_ascii_image, rain_ascii_image_result, drop_of_water_image_ascii = "", "","", ""
  258. # initialisation des ascii art
  259. for line in range(0, 106):
  260. for column in range(0, 106):
  261. ascii_image_result += ' '
  262. rain_ascii_image += ' '
  263. rain_ascii_image_result += ' '
  264. drop_of_water_image_ascii += ' '
  265. ascii_image_result += '\n'
  266. rain_ascii_image += '\n'
  267. rain_ascii_image_result += '\n'
  268. drop_of_water_image_ascii += '\n'
  269.  
  270. def update_counter(self):
  271. print("entre dans update_counter()\n")
  272. self.counter += 1
  273. self.counter_string = str(self.counter)
  274.  
  275. if random.randint(0, 9) % 2 == 0:
  276. self.counter_string = self.counter_string.replace("0", "¦")
  277. if random.randint(0, 9) % 2 == 0:
  278. self.counter_string = self.counter_string.replace("1","§")
  279. if random.randint(0, 9) % 2 == 0:
  280. self.counter_string = self.counter_string.replace("2", "¨")
  281. if random.randint(0, 9) % 2 == 0:
  282. self.counter_string = self.counter_string.replace("3", "©")
  283. if random.randint(0, 9) % 2 == 0:
  284. self.counter_string = self.counter_string.replace("4", "ª")
  285. if random.randint(0, 9) % 2 == 0:
  286. self.counter_string = self.counter_string.replace("5", "«")
  287. if random.randint(0, 9) % 2 == 0:
  288. self.counter_string = self.counter_string.replace("6", "¬")
  289. if random.randint(0, 9) % 2 == 0:
  290. self.counter_string = self.counter_string.replace("8", "®")
  291. if random.randint(0, 9) % 2 == 0:
  292. self.counter_string = self.counter_string.replace("9", "¯")
  293.  
  294.  
  295. pixmap = QPixmap(854, 480) # Créez un QPixmap de la taille souhaitée
  296. pixmap.fill(QColor(0,0,0)) # Remplissez-le avec une couleur transparente
  297.  
  298. painter = QPainter(pixmap)
  299.  
  300. font_id = QFontDatabase.addApplicationFont(self.font_path)
  301. if font_id < 0: print("Error")
  302. families = QFontDatabase.applicationFontFamilies(font_id)
  303. painter.setFont(QFont(families[0], 40))
  304. painter.setPen(QColor("#008800"))
  305.  
  306. self.counter_txt = "C O M P T E U R : "
  307.  
  308. if random.randint(0, 9) % 2 == 0:
  309. self.counter_txt = self.counter_txt.replace("C", "Ý")
  310. if random.randint(0, 9) % 2 == 0:
  311. self.counter_txt = self.counter_txt.replace("M", "ç")
  312. if random.randint(0, 9) % 2 == 0:
  313. self.counter_txt = self.counter_txt.replace("P", "ê")
  314. if random.randint(0, 9) % 2 == 0:
  315. self.counter_txt = self.counter_txt.replace("T", "î")
  316. if random.randint(0, 9) % 2 == 0:
  317. self.counter_txt = self.counter_txt.replace("E", "ß")
  318. if random.randint(0, 9) % 2 == 0:
  319. self.counter_txt = self.counter_txt.replace("U", "ï")
  320. if random.randint(0, 9) % 2 == 0:
  321. self.counter_txt = self.counter_txt.replace("R", "ì")
  322.  
  323.  
  324. print(self.counter_txt + self.counter_string)
  325.  
  326. painter.drawText(pixmap.rect(), Qt.AlignmentFlag.AlignCenter, self.counter_txt + self.counter_string)
  327.  
  328. painter.end()
  329. if random.randint(0, 9) % 3 == 0:
  330. pass #self.image_label.setPixmap(pixmap)
  331.  
  332.  
  333. def update_image_label(self, qimage):
  334. self.image_label.setPixmap(QPixmap.fromImage(qimage))
  335.  
  336. def setCameraIndex(self, index):
  337. global cap
  338. print("entre dans setCameraIndex()\n")
  339. print(f"Caméra sélectionnée : {index}")
  340. self.camera_index = index
  341. print(f"Setting camera with index {self.camera_index}")
  342.  
  343. # Create a new instance of cv2.VideoCapture with the selected camera index
  344. # Open the camera
  345. if platform.system() == 'Windows':
  346. self.cap = cv2.VideoCapture(self.camera_index, cv2.CAP_DSHOW)
  347. else:
  348. self.cap = cv2.VideoCapture(self.camera_index)
  349.  
  350. self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 854)
  351. self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
  352. self.capture_fps = 30
  353. cap = self.cap
  354.  
  355. self.initUI()
  356.  
  357.  
  358. def launch_threads(self):
  359. print("entre dans launch_multithread()\n")
  360. self.methods = [
  361. self.capture_frame,
  362. self.update_ascii_image,
  363. self.create_rain_drops,
  364. self.send_to_virtual_camera,
  365. self.create_virtual_camera
  366. ]
  367.  
  368. # Lancement des threads
  369. count = 1
  370. for method in self.methods:
  371. thread = threading.Thread(target=method)
  372. thread.start()
  373. print(f"Lancement de {method.__name__} dans le thread {count}\n")
  374. self.threads.append(thread)
  375. count += 1
  376.  
  377.  
  378. def stop(self):
  379. print("entre dans stop()\n")
  380. global running
  381. running = False
  382. for queue in self.queues:
  383. for _ in range(3):
  384. queue.put(None)
  385. queue.queue.clear()
  386. #print("Toutes les Files d'Attentes ont étées vidées\n")
  387. for thread in self.threads:
  388. thread.join(timeout=.25)
  389. time.sleep(.251)
  390. #print("Tous les Multiples Threads ont étés arrêtées\n")
  391. sys.exit(0)
  392.  
  393. def initUI(self):
  394. print("entre dans initUI()\n")
  395. self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.FramelessWindowHint)
  396. self.wd = sys._MEIPASS if getattr(sys, 'frozen', False) else ''
  397. # Appliquez le layout au widget central
  398. self.window_icon = QIcon(os.path.join(self.wd, "icon-32.png"))
  399. self.setWindowIcon(self.window_icon)
  400. self.setWindowTitle("Matrix")
  401. self.setGeometry(300, 300, 854, 480)
  402.  
  403. # Créez une instance de QWidget
  404. self.central_widget = QWidget()
  405. # Définissez le widget central
  406. self.setCentralWidget(self.central_widget)
  407.  
  408.  
  409. # Utilisez le QWidget central comme parent pour le QVBoxLayout
  410. self.layout = QVBoxLayout(self.central_widget)
  411.  
  412. # Instanciez QLabel et assignez-le à self.image_label
  413. self.image_label = QLabel()
  414.  
  415. # Créez une QPixmap vide de taille 854x480
  416. pixmap = QPixmap(854, 480)
  417. pixmap.fill(QColor(0, 0, 0))
  418.  
  419. # Attribuez la QPixmap au QLabel
  420. self.image_label.setPixmap(pixmap)
  421.  
  422. # Ajoutez le QLabel image_label au layout
  423. self.layout.addWidget(self.image_label)
  424.  
  425. # self.setLayout(self.layout)
  426.  
  427. #self.launch_multithread()
  428. self.show()
  429. self.camera_app = CameraApp(self)
  430. self.camera_app.close()
  431.  
  432. def closeEvent(self, event: QCloseEvent):
  433. global running
  434. print("entre dans closeEvent()\n")
  435. running = False
  436. for queue in self.queues:
  437. for _ in range(3):
  438. queue.put(None)
  439. queue.queue.clear()
  440. #print("Toutes les Files d'Attentes ont étées vidées\n")
  441. for thread in self.threads:
  442. thread.join(timeout=.25)
  443. time.sleep(.251)
  444. #print("Tous les Multiples Threads ont étés arrêtées\n")
  445. sys.exit(0)
  446.  
  447. def keyPressEvent(self, event: QKeyEvent):
  448. global running
  449. print("entre dans keyPressEvent()\n")
  450. if event.key() == Qt.Key.Key_Escape:
  451. running = False
  452. self.stop()
  453. self.closeEvent()
  454. else:
  455. super(Matrix, self).keyPressEvent(event)
  456.  
  457. # Fonction pour convertir une intensité en caractère ASCII
  458. def get_character(self, intensity):
  459. characters = ' ú.ù,:öøýü×Öų·ÈØÙÍб´¶¹º¼Â²ÇËÒÓ¾Ú'
  460. num_levels = len(characters)
  461. level = intensity * (num_levels - 1) // 255
  462. return characters[level]
  463.  
  464. # Fonction pour convertir une image en ASCII artq
  465. def image_to_ascii(self, image):
  466. ascii_font_size_width = 8
  467. ascii_font_size_height = ascii_font_size_width * 9 / 16
  468. ratio = 1.725
  469. try:
  470. if len(image.shape) > 2 and image.shape[2] == 3:
  471. gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  472. else:
  473. gray_image = image
  474. resized_image = cv2.resize(gray_image, (int(gray_image.shape[1] / (ratio * ascii_font_size_height)), int(gray_image.shape[0] / (ratio * ascii_font_size_width))))
  475. ascii_image = ""
  476. for i in range(resized_image.shape[0]):
  477. for j in range(resized_image.shape[1]):
  478. intensity = resized_image[i][j]
  479. ascii_image += self.get_character(intensity)
  480. ascii_image += "\n"
  481. return ascii_image
  482. except Exception as e:
  483. print(f"Erreur dans image_to_ascii: {e}")
  484.  
  485. # créer l'effets de pluie
  486. def create_rain_drops(self):
  487. global rain_ascii_image_queue, drop_of_water_image_ascii_queue, running
  488. print("on rentre dans rain_drops()")
  489. drop_positions = np.zeros(854, dtype=int)
  490. drop_of_water_image = np.zeros((480, 854), dtype=np.uint8)
  491. blank_image = np.zeros((480, 854), dtype=np.uint8)
  492. drop_columns = []
  493. try:
  494. while running:
  495. if len(drop_columns) < 80:
  496. column = random.randint(0, blank_image.shape[1] - 1)
  497. drop_columns.append(column)
  498. drop_positions[column] = 0
  499. for column in drop_columns:
  500. row = drop_positions[column]
  501. if row >= blank_image.shape[0] - 1:
  502. drop_columns.remove(column)
  503. for row_to_erase in range(0, row):
  504. if row_to_erase < 480:
  505. blank_image[row_to_erase][column] = 0
  506. else:
  507. row += 1
  508. drop_positions[column] = row
  509. for row_line in range(0, row):
  510. blank_image[row_line][column] = 255
  511. row_drop = row + 2
  512. if row_drop < 480:
  513. for row_erase in range(0, row_drop):
  514. drop_of_water_image[row_erase][column] = 0
  515. for row_create in range(row_drop-2, row_drop + 5):
  516. if row_create < 480:
  517. drop_of_water_image[row_create][column] = 255
  518.  
  519. rain_ascii_image = self.image_to_ascii(blank_image)
  520. drop_of_water_image_ascii = self.image_to_ascii(drop_of_water_image)
  521.  
  522. drop_of_water_image_ascii_queue.put(drop_of_water_image_ascii)
  523. rain_ascii_image_queue.put(rain_ascii_image)
  524.  
  525. except Exception as e:
  526. print(f"Erreur dans create_rain_drops: {e}")
  527.  
  528. # Fonction pour mettre à jour l'image capturée
  529. def capture_frame(self):
  530. global frame_queue, cap, running
  531. print("entre dans capture_frame()\n" + str(running))
  532. wd = sys._MEIPASS if getattr(sys, 'frozen', False) else ''
  533. width, height = 854, 480
  534. logo = cv2.imread(os.path.join(wd, 'MatrixLogo.png'))
  535. size1, size2 = 854, 150
  536. logo = cv2.resize(logo, (size1, size2))
  537. message = True
  538. get_camera = False
  539. while running:
  540. try:
  541. if not (cap is None) and not get_camera:
  542. capture = cap
  543. print(f"Dans capture_frame: La camera est définit")
  544. get_camera = True
  545. ret, frame = capture.read()
  546. f = frame
  547. if ret:
  548. # Redimensionner l'image capturée pour qu'elle s'adapte aux dimensions du canevas
  549. resized_frame = cv2.resize(f, (width, height))
  550. # Créer un canevas vide
  551. canvas = np.zeros((height, width, 3), dtype=np.uint8)
  552. # Calculer les coordonnées pour placer le logo au centre du canevas
  553. logo_x = int((width - size1) / 2)
  554. logo_y = 0
  555. # Dessiner le logo sur le canevas
  556. canvas[logo_y:logo_y+size2, logo_x:logo_x+size1] = logo
  557. # Combiner le canevas avec l'image capturée redimensionnée
  558. combined_frame = cv2.addWeighted(resized_frame, .5, canvas, 1, 0)
  559.  
  560. frame = combined_frame
  561. frame_queue.put(frame)
  562.  
  563. except Exception as e:
  564. if message:
  565. print(f"Erreur dans capture_frame: {e}")
  566. message = False
  567.  
  568. # Fonction pour mettre à jour l'image ASCII
  569. def update_ascii_image(self):
  570. global frame_queue, ascii_image_result_queue, running
  571. frame = None
  572. try:
  573. print("entre dans update_ascii_image()\n")
  574. while running:
  575. if not frame_queue.empty():
  576. while not frame_queue.empty() and sys.platform.startswith("linux"):
  577. frame = frame_queue.get()
  578. if not sys.platform.startswith("linux"):
  579. frame = frame_queue.get()
  580. else:
  581. pass
  582. f = frame
  583. if f is not None:
  584. y_image = self.image_to_ascii(f)
  585. ascii_image_result = y_image
  586. ascii_image_result_queue.put(ascii_image_result)
  587. time.sleep(0.001)
  588. except Exception as e:
  589. print(f"Erreur dans update_ascii_image: {e}")
  590.  
  591. def send_to_virtual_camera(self):
  592. global ascii_image_result_queue, rain_ascii_image_queue, drop_of_water_image_ascii_queue, virtual_frame_queue, running
  593. width, height = 854, 480
  594. ascii_font_size_width = 16
  595. wd = sys._MEIPASS if getattr(sys, 'frozen', False) else ''
  596. font_path = os.path.join(wd, '.', 'mtx.ttf')
  597.  
  598. # Initialisez les variables avec des valeurs par défaut
  599. ascii_image_result = ""
  600. rain_ascii_image = ""
  601. drop_of_water_image_ascii = ""
  602.  
  603. try:
  604. print("entre dans send_to_virtual_camera()\n" + str(running))
  605. while running:
  606. if not ascii_image_result_queue.empty():
  607. while not ascii_image_result_queue.empty() and sys.platform.startswith("linux"):
  608. ascii_image_result = ascii_image_result_queue.get()
  609. if not sys.platform.startswith("linux"):
  610. ascii_image_result = ascii_image_result_queue.get()
  611. else:
  612. pass
  613.  
  614. if not drop_of_water_image_ascii_queue.empty():
  615. drop_of_water_image_ascii = drop_of_water_image_ascii_queue.get()
  616. else:
  617. pass
  618.  
  619. if not rain_ascii_image_queue.empty():
  620. rain_ascii_image = rain_ascii_image_queue.get()
  621. else:
  622. pass
  623.  
  624. canvas_image = Image.new('RGB', (width, height), 'black')
  625. draw = ImageDraw.Draw(canvas_image)
  626. font = ImageFont.truetype(font_path, ascii_font_size_width)
  627. draw.text((0, 0), ascii_image_result, fill='#006600', font=font)
  628. draw.text((0, 0), rain_ascii_image, fill='#00ff00', font=font)
  629. draw.text((0, 0), drop_of_water_image_ascii, fill='white', font=font)
  630. virtual_frame = cv2.cvtColor(np.array(canvas_image), cv2.COLOR_RGB2BGR)
  631.  
  632. rgb_image = cv2.cvtColor(virtual_frame, cv2.COLOR_BGR2RGB)
  633. h, w, ch = rgb_image.shape
  634. bytes_per_line = ch * w
  635. qimage = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
  636.  
  637. self.communicator = Communicator()
  638. self.communicator.update_image_label_signal.emit(qimage)
  639.  
  640. virtual_frame = virtual_frame
  641. virtual_frame_queue.put(virtual_frame)
  642. except Exception as e:
  643. print(f"Erreur dans send_to_virtual_camera: {e}")
  644.  
  645.  
  646. def create_virtual_camera(self):
  647. global virtual_frame_queue, running
  648. print("entre dans create_virtual_camera()\n")
  649. virtual_frame = np.zeros((480, 854, 3), dtype=np.uint8)
  650. old_virtual_frame = virtual_frame
  651. while running:
  652. try:
  653. if sys.platform.startswith("linux"):
  654. with pyvirtualcam.Camera(width=854, height=480, fps=30, device='/dev/video4') as cam:
  655. if not virtual_frame_queue.empty():
  656. while not virtual_frame_queue.empty() and sys.platform.startswith("linux"):
  657. virtual_frame = virtual_frame_queue.get()
  658. cam.send(virtual_frame)
  659. cam.sleep_until_next_frame()
  660. else:
  661. virtual_frame = old_virtual_frame
  662. cam.send(virtual_frame)
  663. cam.sleep_until_next_frame()
  664. # raise ValueError("virtual_frame n'est pas encore disponible")
  665. elif sys.platform.startswith("win32"):
  666. with pyvirtualcam.Camera(854, 480, 50) as cam:
  667. if not virtual_frame_queue.empty():
  668. virtual_frame = virtual_frame_queue.get()
  669. cam.send(virtual_frame)
  670. cam.sleep_until_next_frame()
  671. else:
  672. virtual_frame = old_virtual_frame
  673. cam.send(virtual_frame)
  674. cam.sleep_until_next_frame()
  675. #raise ValueError("virtual_frame n'est pas encore disponible")
  676. old_virtual_frame = virtual_frame
  677. elif sys.platform.startswith("darwin"):
  678. with pyvirtualcam.Camera(854, 480, 30) as cam:
  679. if not virtual_frame_queue.empty():
  680. while not virtual_frame_queue.empty():
  681. virtual_frame = virtual_frame_queue.get()
  682. cam.send(virtual_frame)
  683. cam.sleep_until_next_frame()
  684. else:
  685. virtual_frame = old_virtual_frame
  686. cam.send(virtual_frame)
  687. cam.sleep_until_next_frame()
  688. #raise ValueError("virtual_frame n'est pas encore disponible")
  689. old_virtual_frame = virtual_frame
  690. except Exception as e:
  691. print(f"Erreur dans create_virtual_camera: {e}")
  692. pass
  693.  
  694. if __name__ == "__main__":
  695. app = QApplication([])
  696. matrix = Matrix()
  697. camera_app = CameraApp(matrix)
  698. communicator = Communicator()
  699. camera_app.cameraSelected.connect(matrix.setCameraIndex)
  700. communicator.update_image_label_signal.connect(matrix.update_image_label)
  701. camera_app.show()
  702. matrix.launch_threads() # Appel de la méthode de lancement des threads
  703. app.exec()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement