Je développe un module Python, avec OpenCV, qui se connecte à un flux RTSP pour effectuer un prétraitement sur la vidéo (principalement, réduction des fps et de la résolution), puis le stocker dans le système de fichiers.

Mais, même après avoir essayé plusieurs codecs, à la recherche de développements similaires... Je me retrouve toujours avec une vidéo vide. J'ai vu cet autre fil (cv::VideoWriter génère une vidéo illisible), qui peut être similaire, mais a été développé sur C++.

Quelqu'un a-t-il travaillé là-dessus? J'utilise normalement un exemple de flux RTSP comme référence, tel que rtsp: //freja.hiof.no: 1935 / rtplive / definst /hessdalen03.stream, et je peux recevoir et même regarder le flux de VLC correctement .

J'ai vu pas mal de discussions discuter de la façon de capturer une vidéo à partir d'un flux RTSP, ou comment travailler avec les classes VideoWriters et VideoReaders et les fichiers vidéo, mais presque rien combinant les deux.

Toute aide serait très appréciée :) Merci !!


Édition 1: exemple de code utilisé pour stocker les images.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2
import numpy

# Test frame.
width, height = 400, 300
width_2, height_2 = int(width / 2), int(height / 2)
frame = numpy.zeros((height, width, 3), numpy.uint8)
cv2.rectangle(frame, (0, 0), (width_2, height_2), (255, 0, 0), cv2.FILLED)
cv2.rectangle(frame, (width_2, height_2), (width, height), (0, 255, 0), cv2.FILLED)

frames = [frame for _ in range(100)]
fps = 25

# Define the codec.
#fourcc = cv2.VideoWriter_fourcc(*'X264')
#fourcc = cv2.VideoWriter_fourcc(*'XVID')
fourcc = cv2.VideoWriter_fourcc(*'MJPG')

# Create VideoWriter object
out = cv2.VideoWriter(filename='video.avi',
                      fourcc=fourcc,
                      apiPreference=cv2.CAP_FFMPEG,
                      fps=float(fps),
                      frameSize=(width, height),
                      isColor=True)

result = 0
for frame in frames:
    result += 0 if out.write(frame) is None else 1
print(result)

out.release()

Edit 2: Solution

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2
import numpy

# Test frame.
width, height = 400, 300
width_2, height_2 = int(width / 2), int(height / 2)

frame1 = numpy.zeros((height, width, 3), numpy.uint8)
cv2.rectangle(frame1, (0, 0), (width_2, height_2), (255, 0, 0), cv2.FILLED)
cv2.rectangle(frame1, (width_2, height_2), (width, height), (0, 255, 0), cv2.FILLED)
cv2.imwrite('frame1.jpg', frame1)

frame2 = numpy.zeros((height, width, 3), numpy.uint8)
cv2.rectangle(frame2, (width_2, 0), (width, height_2), (255, 0, 0), cv2.FILLED)
cv2.rectangle(frame2, (0, height_2), (width_2, height), (0, 255, 0), cv2.FILLED)
cv2.imwrite('frame2.jpg', frame2)

range1 = [frame1 for _ in range(10)]
range2 = [frame2 for _ in range(10)]
frames = range1 + range2 + range1 + range2 + range1
fps = 2

# Define the codec.
fourcc = cv2.VideoWriter_fourcc(*'MJPG')

# Create VideoWriter object
out = cv2.VideoWriter('video.avi', fourcc, float(fps), (width, height))

for frame in frames:
    out.write(frame)

out.release()
8
rafamartinc 13 mars 2019 à 14:54

1 réponse

Meilleure réponse

Voici un widget de flux RTSP vers vidéo. Je recommanderais de créer un autre thread pour obtenir les images que cv2.VideoCapture.read() bloque. Cela peut être coûteux et provoquer une latence car le thread principal doit attendre d'avoir obtenu une trame. En plaçant cette opération dans un thread séparé qui se concentre uniquement sur la capture d'images et le traitement / enregistrement des images dans le thread principal, cela améliore considérablement les performances. Vous pouvez également expérimenter avec d'autres codecs, mais l'utilisation de MJPG devrait être sûre car elle est intégrée à OpenCV. J'ai utilisé mon flux de caméras IP et enregistré les images dans output.avi. Assurez-vous de remplacer rtsp_stream_link par votre propre lien de flux RTSP. :)

Output Video Screenshot

from threading import Thread
import cv2

class RTSPVideoWriterObject(object):
    def __init__(self, src=0):
        # Create a VideoCapture object
        self.capture = cv2.VideoCapture(src)

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
        self.output_video = cv2.VideoWriter('output.avi', self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def show_frame(self):
        # Display frames in main program
        if self.status:
            cv2.imshow('frame', self.frame)

        # Press Q on keyboard to stop recording
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            self.output_video.release()
            cv2.destroyAllWindows()
            exit(1)

    def save_frame(self):
        # Save obtained frame into video output file
        self.output_video.write(self.frame)

if __name__ == '__main__':
    rtsp_stream_link = 'your stream link!'
    video_stream_widget = RTSPVideoWriterObject(rtsp_stream_link)
    while True:
        try:
            video_stream_widget.show_frame()
            video_stream_widget.save_frame()
        except AttributeError:
            pass
5
nathancy 21 mars 2019 à 20:16