Existe-t-il un moyen avec Python (peut-être avec OpenCV ou PIL) de saisir en continu des images de tout ou partie de l’écran, au moins à 15 ips ou plus? Je l'ai vu faire dans d'autres langues, donc en théorie cela devrait être possible.
Je n'ai pas besoin de sauvegarder les données d'image dans un fichier. En fait, je veux juste qu'il émette un tableau contenant les données RVB brutes (comme dans un tableau numpy ou quelque chose du genre), car je vais juste le prendre et l'envoyer à un grand écran LED (probablement après le redimensionner).
Il existe une autre solution avec mss qui fournit un taux de trame bien meilleur (Testé sur un Macbook Pro avec MacOS Sierra)
import numpy as np
import cv2
from mss import mss
from PIL import Image
mon = {'top': 160, 'left': 160, 'width': 200, 'height': 200}
sct = mss()
while 1:
sct.get_pixels(mon)
img = Image.frombytes('RGB', (sct.width, sct.height), sct.image)
cv2.imshow('test', np.array(img))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
Vous devrez utiliser ImageGrab from Pillow (PIL) Library et convertir la capture en tableau numpy. Lorsque vous avez le tableau, vous pouvez faire ce que vous voulez en utilisant opencv. J'ai converti la capture en couleur grise et utilisé imshow () à titre de démonstration.
Voici un code rapide pour vous aider à démarrer:
from PIL import ImageGrab
import numpy as np
import cv2
img = ImageGrab.grab(bbox=(100,10,400,780)) #bbox specifies specific region (bbox= x,y,width,height *starts top-left)
img_np = np.array(img) #this is the array obtained from conversion
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
cv2.imshow("test", frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
vous pouvez y brancher un tableau avec la fréquence qui vous convient pour continuer à capturer des images. Après cela, il vous suffit de décoder les cadres. n'oubliez pas d'ajouter avant la boucle:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
vid = cv2.VideoWriter('output.avi', fourcc, 6, (640,480))
et dans la boucle, vous pouvez ajouter:
vid.write(frame) #the edited frame or the original img_np as you please
METTRE À JOUR
le résultat final ressemble à quelque chose comme ceci (Si vous voulez obtenir un flux d’images, c’est-à-dire stocker en vidéo simplement une démonstration de l’utilisation d’opencv sur l’écran capturé):
from PIL import ImageGrab
import numpy as np
import cv2
while(True):
img = ImageGrab.grab(bbox=(100,10,400,780)) #bbox specifies specific region (bbox= x,y,width,height)
img_np = np.array(img)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
cv2.imshow("test", frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
J'espère que cela pourra aider
J'ai essayé tout ce qui précède, mais cela ne m'a pas donné la mise à jour de l'écran en temps réel… .. Vous pouvez essayer ceci. Ce code est testé et fonctionne avec succès, il vous donne également une bonne sortie en fps. Vous pouvez également en juger par chaque temps de boucle nécessaire.
import numpy as np
import cv2
from PIL import ImageGrab as ig
import time
last_time = time.time()
while(True):
screen = ig.grab(bbox=(50,50,800,640))
print('Loop took {} seconds',format(time.time()-last_time))
cv2.imshow("test", np.array(screen))
last_time = time.time()
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
Vous pouvez essayer ceci =>
import mss
import numpy
with mss.mss() as sct:
monitor = {'top': 40, 'left': 0, 'width': 800, 'height': 640}
img = numpy.array(sct.grab(monitor))
print(img)
sur la base de ce post et d’autres posts, j’ai réalisé quelque chose comme ceci… .. Il prend une capture d’écran et écrit dans un fichier vidéo sans enregistrer l’image.
import cv2
import numpy as np
import os
import pyautogui
output = "video.avi"
img = pyautogui.screenshot()
img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
#get info from img
height, width, channels = img.shape
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output, fourcc, 20.0, (width, height))
while(True):
try:
img = pyautogui.screenshot()
image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
out.write(img)
StopIteration(0.5)
except KeyboardInterrupt:
break
out.release()
cv2.destroyAllWindows()
Avec toutes les solutions ci-dessus, je ne pouvais pas obtenir une fréquence d'images utilisable avant d'avoir modifié mon code de la manière suivante:
import numpy as np
import cv2
from mss import mss
from PIL import Image
bbox = {'top': 100, 'left': 0, 'width': 400, 'height': 300}
sct = mss()
while 1:
sct_img = sct.grab(bbox)
cv2.imshow('screen', np.array(sct_img))
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
Avec cette solution, j'obtiens facilement plus de 20 images/seconde.
Pour référence, vérifiez ce lien: https://python-mss.readthedocs.io/examples.html
J'ai essayé ImageGrab
à partir de PIL
et il m'a donné 20 images par seconde, ce qui est correct, mais l'utilisation des bibliothèques win32 m'a permis d'obtenir + 40 images par seconde, ce qui est incroyable!
J'ai utilisé this code de Frannecklp mais cela ne fonctionnait pas très bien, donc je devais le modifier:
-Premier pip install pywin32
en cas d'utilisation des bibliothèques
-importez les bibliothèques comme ceci à la place:
import cv2
import numpy as np
from win32 import win32gui
from pythonwin import win32ui
from win32.lib import win32con
from win32 import win32api
pour obtenir un simple écran d'image, faites:
from grab_screen import grab_screen
import cv2
img = grab_screen()
cv2.imshow('frame',img)
et pour obtenir des cadres:
while(True):
#frame = grab_screen((0,0,100,100))
frame = grab_screen()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q') or x>150:
break