2
votes

Capture d'une seule image à partir d'un flux vidéo rtsp H.264

J'essaie de capturer une seule image à la demande à partir d'une image vidéo RTSP H.264. J'utilise OpenCV avec Python fonctionnant sur un Raspberry Pi.

D'après ce que je comprends, vous ne pouvez pas simplement capturer une image, mais plutôt lire en permanence le flux d'images de la vidéo et supprimer tout sauf celle que vous voulez occasionnellement. Ceci est très coûteux en calcul et consomme environ 25% du processeur sur un Pi pour ne rien faire d'autre que lire et supprimer les images vidéo rtsp 1280x720 15 ips H.264.

Y a-t-il un autre moyen? Je suis flexible et je peux également utiliser GStreamer, FFMPEG ou tout autre élément plus efficace en termes de calcul.


0 commentaires

3 Réponses :


2
votes

La raison pour laquelle vous devez lire le flux est que H.264 a plusieurs types de cadres (voir https : //en.wikipedia.org/wiki/Video_compression_picture_types ) et les trames P et B ont besoin du contexte pour être décodées. Seules les images I (également appelées images clés) peuvent être décodées de manière autonome.

Si vous voulez lire des images vraiment arbitraires, vous pouvez analyser (et non décoder) le flux, et tout conserver depuis la dernière image I. Lorsque votre déclencheur arrive, vous décodez le flux depuis la dernière image I et jusqu'au point actuel.

Si vous n'avez pas besoin d'être très précis, vous pouvez simplement stocker la dernière image I et la décoder à la demande. Ce sera très rapide, mais cela signifie que vous pouvez obtenir une image au mauvais moment.

Enfin, à quelle fréquence ces images clés sont-elles diffusées? Cela dépend de la source. Par exemple, la webcam C920 les génère environ toutes les 5 secondes par défaut, mais cet intervalle peut être changé de 1 à 30 secondes (je pense que c'était il y a quelque temps)


1 commentaires

Je suis conscient de la façon dont H.264 compresse les données, mais j'ai oublié que l'espacement des images I peut être important et doit être pris en compte. Merci d'avoir soulevé ce point.



2
votes

Je faisais quelque chose de similaire. Voici mon code:

def CaptureFrontCamera():
    _bytes = bytes()
    stream = urllib.request.urlopen('http://192.168.0.51/video.cgi?resolution=1920x1080')
    while True:
        _bytes += stream.read(1024)
        a = _bytes.find(b'\xff\xd8')
        b = _bytes.find(b'\xff\xd9')
        if a != -1 and b != -1:
            jpg = _bytes[a:b+2]
            _bytes = _bytes[b+2:]
            filename = '/home/pi/capture.jpeg'
            i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
            cv2.imwrite(filename, i)
            return filename


3 commentaires

Cela semble prometteur, mais je n'ai pas été en mesure de le faire avec un flux vidéo rtsp (plutôt que http). Des pensées?


Votre lien fait référence à l'utilisation de cv2.VideoCapture () pour lire les flux rtsp, ce que je fais maintenant. Le problème est que read () consomme une tonne de puissance de traitement et donne une image dont je n'ai pas besoin 99% du temps. Idéalement, je veux qu'il ingère le flux d'octets et ne construise l'image que lorsque cela est nécessaire.


Désolé, je ne peux pas vous aider davantage. Je suis assez novice en traitement d'image. J'espère que vous trouverez une solution.



0
votes

Pour répondre à ma propre question. Au lieu d'utiliser read ():

cap = cv2.VideoCapture('rtsp_url')

def captureimages():
    while True:
        cap.grab()

s = threading.Thread(target=captureimages)
s.start()

if takepic == True:
    picture = cap.retrieve()

Il est plus efficace de le découper en grab () et retrieve (). Pas une solution parfaite, mais meilleure:

cap = cv2.VideoCapture('rtsp_url')

def captureimages():
    while True:
        image = cap.read()

s = threading.Thread(target=captureimages)
s.start()

if takepic == True:
    picture = image.copy()


0 commentaires