Paullux

Untitled

Jun 11th, 2023
42
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.90 KB | None | 0 0
  1. import sys
  2. import os
  3. import platform
  4. import time
  5. import threading
  6. import queue
  7. import random
  8.  
  9. import cv2
  10. import numpy as np
  11. import pyvirtualcam
  12.  
  13. from PIL import Image, ImageDraw, ImageFont
  14.  
  15. if sys.platform == 'win32':
  16. import ctypes
  17. winVer = platform.win32_ver(release='')[0]
  18. try:
  19. if int(winVer) >= 10:
  20. ctypes.windll.shcore.SetProcessDpiAwareness(2)
  21. elif int(winVer) == 8:
  22. ctypes.windll.shcore.SetProcessDpiAwareness(1)
  23. else:
  24. ctypes.windll.user32.SetProcessDPIAware()
  25. except (ImportError, AttributeError, OSError):
  26. pass
  27.  
  28. # Initialisez les variables globales ici
  29. running = True
  30. ascii_image = ""
  31.  
  32. # Définition des caractères à utiliser pour l'ASCII art
  33. characters = ' ú.ù,:öøýü×Öų·ÈØÙÍб´¶¹º¼Â²ÇËÒÓ¾Ú'
  34. wd = sys._MEIPASS if getattr(sys, 'frozen', False) else ''
  35. logo = cv2.imread(os.path.join(wd, '.', 'MatrixLogo.png'))
  36. size1, size2 = 1280, 301
  37. logo = cv2.resize(logo, (size1, size2))
  38.  
  39. running = True
  40. camera = 0 # À modifier si ne fonctionne pas
  41. frame_lock = threading.Lock()
  42. ascii_image_lock = threading.Lock()
  43.  
  44. rain_intensity = 0.5
  45. last_ascii_image, rain_ascii_image = "", ""
  46. columns_to_erase_queue = queue.Queue()
  47. columns_launched_queue = queue.Queue()
  48. image_updated = ""
  49.  
  50. ascii_font_size_width = 20
  51. ascii_font_size_height = ascii_font_size_width * 9 / 16
  52.  
  53. width = 1280
  54. height = 720
  55. font_path = os.path.join(wd, 'mtx.ttf')
  56. canvas_image = Image.new('RGB', (width, height), 'black')
  57. draw = ImageDraw.Draw(canvas_image)
  58. font = ImageFont.truetype(font_path, ascii_font_size_width)
  59.  
  60. stop = threading.Event()
  61. frame, ascii_image, rain_ascii_image, rain_ascii_image_result, drop_of_water_image_ascii, erase_rain_ascii_image = None, "", "", "", "", ""
  62. ascii_column = 0
  63. ascii_row = 0
  64.  
  65. # initialisation des ascii art
  66. for line in range(0, 106):
  67. for column in range(0, 106):
  68. ascii_image += ' '
  69. rain_ascii_image += ' '
  70. rain_ascii_image_result += ' '
  71. drop_of_water_image_ascii += ' '
  72. erase_rain_ascii_image += ' '
  73. ascii_image += '\n'
  74. rain_ascii_image += '\n'
  75. rain_ascii_image_result += '\n'
  76. drop_of_water_image_ascii += '\n'
  77. erase_rain_ascii_image += '\n'
  78.  
  79. # Fonction pour convertir une intensité en caractère ASCII
  80. def get_character(intensity):
  81. global characters
  82. characters = characters
  83. num_levels = len(characters)
  84. level = intensity * (num_levels - 1) // 255
  85. return characters[level]
  86.  
  87. # Fonction pour convertir une image en ASCII art
  88. def image_to_ascii(image):
  89. global ascii_font_size_width, ascii_font_size_height
  90. if len(image.shape) > 2 and image.shape[2] == 3:
  91. gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  92. else:
  93. gray_image = image
  94. resized_image = cv2.resize(gray_image, (int(gray_image.shape[1] / (0.88 * ascii_font_size_height)), int(gray_image.shape[0] / (0.88 * ascii_font_size_width))))
  95. ascii_image = ""
  96. for i in range(resized_image.shape[0]):
  97. for j in range(resized_image.shape[1]):
  98. intensity = resized_image[i][j]
  99. ascii_image += get_character(intensity)
  100. ascii_image += "\n"
  101. return ascii_image
  102.  
  103. #créer l'effets de pluie
  104. def create_rain_drops(resized_image, drop_positions):
  105. global running, last_ascii_image, rain_ascii_image
  106. drop_columns = [] # Liste des colonnes pour les gouttes de pluie
  107. while running:
  108. # Générer une nouvelle goutte de pluie
  109. if len(drop_columns) < 80:
  110. column = random.randint(0, resized_image.shape[1] - 1) # Choix aléatoire de la colonne
  111. drop_columns.append(column)
  112. drop_positions[column] = 0 # Initialiser la position de la goutte à la ligne supérieure
  113. # Mettre à jour les positions des gouttes de pluie
  114. for column in drop_columns:
  115. row = drop_positions[column]
  116. # Réinitialiser la colonne à zéro pour effacer la goutte précédente
  117. if row >= resized_image.shape[0] - 1:
  118. drop_columns.remove(column)
  119. columns_to_erase_queue.put((column, row)) # Ajouter la colonne à effacer à la liste
  120. for row_to_erase in range(0, drop_positions[column]):
  121. resized_image[row_to_erase][column] = 0
  122. else:
  123. row += 1 # Descendre la goutte d'une ligne
  124. drop_positions[column] = row # Mettre à jour la position de la goutte
  125. # Mettre à jour l'image avec la goutte de pluie
  126. resized_image[row][column] = 255 # Intensité maximale
  127. # Ajouter uniquement les colonnes dans la queue
  128. columns_launched_queue.put((column, row))
  129. # Mettre à jour l'affichage de l'ASCII art dans la fenêtre tkinter
  130. a_image = image_to_ascii(resized_image)
  131. with ascii_image_lock:
  132. global ascii_image
  133. rain_ascii_image = a_image
  134. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  135. running = False
  136. break
  137. if cv2.waitKey(1) & 0xFF == ord('q'):
  138. running = False
  139. break
  140.  
  141. def create_rain_drop_of_water(drop_of_water_image, columns_launched_queue):
  142. global running, drop_of_water_image_ascii, rain_ascii_image
  143. max_rows = {}
  144. while running:
  145. while not columns_launched_queue.empty():
  146. # Mettre à jour les positions des gouttes de pluie
  147. column, row = columns_launched_queue.get()
  148. if column in max_rows:
  149. max_rows[column] = max(max_rows[column], row)
  150. else:
  151. max_rows[column] = row
  152.  
  153. # Initialiser drop_of_water_image avec des zéros
  154. drop_of_water_image = np.zeros_like(drop_of_water_image)
  155.  
  156. with ascii_image_lock:
  157. for column, row in max_rows.items():
  158. drop_of_water_image[row][column] = 255
  159. # Mettre à jour l'affichage de l'ASCII art dans la fenêtre tkinter
  160. drop_of_water_image_ascii = image_to_ascii(drop_of_water_image)
  161. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  162. running = False
  163. break
  164. if cv2.waitKey(1) & 0xFF == ord('q'):
  165. running = False
  166. break
  167.  
  168. # Effacer progressivement la pluie
  169. def erase_rain_columns():
  170. global running, last_ascii_image, columns_launched_queue, erase_rain_ascii_image, erase_rain_image, drop_positions, resized_image
  171. while running:
  172. if not columns_to_erase_queue.empty():
  173. while not columns_to_erase_queue.empty():
  174. column, row = columns_to_erase_queue.get()
  175. for row_to_erase in range(0, height):
  176. erase_rain_image[row_to_erase][column] = resized_image[row_to_erase][column]
  177. with ascii_image_lock:
  178. erase_rain_ascii_image = image_to_ascii(erase_rain_image)
  179. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  180. running = False
  181. break
  182. if cv2.waitKey(1) & 0xFF == ord('q'):
  183. running = False
  184. break
  185.  
  186.  
  187. # Fonction pour mettre à jour l'image capturée
  188. def capture_frame(ret, f):
  189. global frame, running, capture
  190. while running:
  191. ret, f = capture.read()
  192. if ret:
  193. # Redimensionner l'image capturée pour qu'elle s'adapte aux dimensions du canevas
  194. resized_frame = cv2.resize(f, (1280, 720))
  195. # Créer un canevas vide
  196. canvas = np.zeros((720, 1280, 3), dtype=np.uint8)
  197. # Calculer les coordonnées pour placer le logo au centre du canevas
  198. logo_x = int((1280 - size1) / 2)
  199. logo_y = 0
  200. # Dessiner le logo sur le canevas
  201. canvas[logo_y:logo_y+size2, logo_x:logo_x+size1] = logo
  202. # Combiner le canevas avec l'image capturée redimensionnée
  203. combined_frame = cv2.addWeighted(resized_frame, .5, canvas, 1, 0)
  204. with frame_lock:
  205. frame = combined_frame
  206. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  207. running = False
  208. break
  209. if cv2.waitKey(1) & 0xFF == ord('q'):
  210. running = False
  211. break
  212.  
  213. # Fonction pour mettre à jour l'image ASCII
  214. def update_ascii_image():
  215. global running, ascii_image
  216. while running and not stop.is_set():
  217. with frame_lock:
  218. f = frame
  219. if f is not None:
  220. a_image = image_to_ascii(f)
  221. with ascii_image_lock:
  222. ascii_image = a_image
  223.  
  224. time.sleep(0.001) # Temps d'attente arbitraire
  225. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  226. running = False
  227. break
  228. if cv2.waitKey(1) & 0xFF == ord('q'):
  229. running = False
  230. break
  231.  
  232. def image_fusion():
  233. global running, characters, ascii_image_result, rain_ascii_image, drop_of_water_image_ascii, rain_ascii_image_result, erase_rain_ascii_image
  234. while running:
  235. with ascii_image_lock:
  236. ascii_image_cut = ascii_image.split("\n")
  237. rain_ascii_image_cut = rain_ascii_image.split("\n")
  238. drop_of_water_ascii_image_cut = drop_of_water_image_ascii.split("\n")
  239. erase_rain_ascii_image_cut = erase_rain_ascii_image.split("\n")
  240. ascii_image_intermediate = []
  241. rain_ascii_image_intermediate = []
  242. for i in range(len(ascii_image_cut)):
  243. ascii_image_cut_line = list(ascii_image_cut[i])
  244. rain_ascii_image_cut_line = list(rain_ascii_image_cut[i])
  245. drop_of_water_ascii_image_cut_line = list(drop_of_water_ascii_image_cut[i])
  246. erase_rain_ascii_image_cut_line = list(erase_rain_ascii_image_cut)
  247. for j in range(len(rain_ascii_image_cut_line)):
  248. if j < len(ascii_image_cut_line) and j < len(rain_ascii_image_cut_line) and j < len(drop_of_water_ascii_image_cut_line) and j < len(erase_rain_ascii_image_cut_line):
  249. if (rain_ascii_image_cut_line[j] != ' ' and rain_ascii_image_cut_line[j] in characters):
  250. if drop_of_water_ascii_image_cut_line[j] != ' ':
  251. ascii_image_cut_line[j] = ' '
  252. else:
  253. rain_ascii_image_cut_line[j] = ascii_image_cut_line[j]
  254. ascii_image_cut_line[j] = ' '
  255. ascii_image_intermediate.append("".join(ascii_image_cut_line))
  256. rain_ascii_image_intermediate.append("".join(rain_ascii_image_cut_line))
  257. ascii_image_result = "\n".join(ascii_image_intermediate)
  258. rain_ascii_image_result = "\n".join(rain_ascii_image_intermediate)
  259. time.sleep(0.001)
  260. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  261. running = False
  262. break
  263. if cv2.waitKey(1) & 0xFF == ord('q'):
  264. running = False
  265. break
  266.  
  267. def send_to_virtual_camera():
  268. global running, ascii_image_result, drop_of_water_image_ascii, wd, buffer, image_updated, virtual_frame, ascii_font_size_width, width, height, font_path, canvas_image, draw, font, erase_rain_ascii_image
  269. while running:
  270. # Capture the content of the canvas as an image
  271. canvas_image = Image.new('RGB', (width, height), 'black')
  272. draw = ImageDraw.Draw(canvas_image)
  273. font = ImageFont.truetype(font_path, ascii_font_size_width)
  274. draw.text((0, 0), ascii_image_result, fill='#008800', font=font)
  275. draw.text((0, 0), rain_ascii_image_result, fill='#00ff00', font=font)
  276. hex_vars = ['f', 'e', 'd', 'c', 'b', 'a', '9', '8']
  277. for hex_var in hex_vars:
  278. draw.text((0, 0), erase_rain_ascii_image, fill='#00'+ hex_var + hex_var + '00', font=font)
  279. time.sleep(0.01)
  280. draw.text((0, 0), drop_of_water_image_ascii, fill='white', font=font)
  281. virtual_frame = cv2.cvtColor(np.array(canvas_image), cv2.COLOR_RGB2BGR)
  282.  
  283. # Affichez la miniature dans la fenêtre créée précédemment
  284. cv2.imshow("Matrix rain", virtual_frame)
  285.  
  286. # Vérifiez si la fenêtre a été fermée en utilisant le bouton en croix
  287. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  288. running = False
  289. break
  290.  
  291. # Attendez une touche pour quitter
  292. if cv2.waitKey(1) & 0xFF == ord('q'):
  293. running = False
  294. break
  295.  
  296. # Fermez la fenêtre et libérez les ressources
  297. cv2.destroyAllWindows()
  298.  
  299.  
  300. def create_virtual_camera():
  301. global running, virtual_frame
  302. width = 1280
  303. height = 720
  304. with pyvirtualcam.Camera(width, height, 30) as cam:
  305. while running:
  306. # Redimensionne l'image pour qu'elle corresponde à la taille de la caméra virtuelle
  307. resized_frame = cv2.resize(virtual_frame, (width, height))
  308. cam.send(resized_frame)
  309. cam.sleep_until_next_frame()
  310. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  311. running = False
  312. break
  313. if cv2.waitKey(1) & 0xFF == ord('q'):
  314. running = False
  315. break
  316.  
  317. # Ouverture de la caméra
  318. if platform.system() == 'Windows':
  319. capture = cv2.VideoCapture(camera,cv2.CAP_DSHOW)
  320. elif platform.system() == 'Linux':
  321. capture = cv2.VideoCapture(camera)
  322.  
  323. capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
  324. capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
  325. ret, f = capture.read()
  326.  
  327. if getattr(sys, 'frozen', False):
  328. import pyi_splash
  329. # Fermeture du splash screen
  330. pyi_splash.update_text('UI Loaded ...')
  331. pyi_splash.close()
  332.  
  333. # Variables partagées entre les threads
  334. frame = None
  335. ascii_image = ""
  336.  
  337. # Affichage de l'image
  338. cv2.namedWindow("Matrix rain", cv2.WINDOW_NORMAL)
  339. cv2.resizeWindow("Matrix rain", 1280, 720)
  340. cv2.imshow("Matrix rain", f)
  341.  
  342. buffer_thread_event = threading.Event()
  343.  
  344. # Lancement des threads
  345. capture_thread = threading.Thread(target=capture_frame, args=(ret, f))
  346. ascii_thread = threading.Thread(target=update_ascii_image)
  347. image_fusion_thread = threading.Thread(target=image_fusion)
  348.  
  349. resized_image = np.zeros((720, 1280), dtype=np.uint8)
  350. drop_of_water_image = resized_image
  351. erase_rain_image = resized_image
  352. virtual_frame = cv2.cvtColor(np.array(resized_image), cv2.COLOR_RGB2BGR)
  353. drop_positions = np.zeros(1280, dtype=int)
  354.  
  355. create_rain_drops_thread = threading.Thread(target=create_rain_drops, args=(resized_image, drop_positions))
  356. create_rain_drop_of_water_thread = threading.Thread(target=create_rain_drop_of_water, args=(drop_of_water_image, columns_launched_queue))
  357. erase_rain_columns_thread = threading.Thread(target=erase_rain_columns, args=())
  358.  
  359. running = True
  360. image_updated = False
  361. buffer = None
  362.  
  363. send_virtual_camera_thread = threading.Thread(target=send_to_virtual_camera)
  364. create_virtual_camera_thread = threading.Thread(target=create_virtual_camera)
  365.  
  366. threads = [capture_thread, ascii_thread, image_fusion_thread, create_rain_drops_thread, create_rain_drop_of_water_thread, erase_rain_columns_thread, send_virtual_camera_thread, create_virtual_camera_thread]
  367.  
  368. for thread in threads:
  369. thread.daemon = True
  370. thread.start()
  371.  
  372. # Boucle principale
  373. while True:
  374. # Attendez un court délai
  375. time.sleep(0.01)
  376.  
  377. # Boucle principale de l'application
  378. if cv2.getWindowProperty("Matrix rain", cv2.WND_PROP_VISIBLE) < 1:
  379. running = False
  380. break
  381. if cv2.waitKey(1) & 0xFF == ord('q'):
  382. running = False
  383. break
  384.  
  385. # Libération des ressources
  386. capture.release()
  387. cv2.destroyAllWindows()
  388. # Arrêt propre du programme
  389. running = False
  390. stop.set()
  391.  
  392. for thread in threads:
  393. thread.join(timeout=1.0)
  394. time.sleep(1.001)
  395.  
  396. sys.exit(0)
Advertisement
Add Comment
Please, Sign In to add comment