web-dev-qa-db-fra.com

Comment traiter les images d’une vidéo, image par image, en streaming vidéo à l’aide de Opencv python

Je suis débutant dans OpenCV. Je souhaite effectuer un traitement d'image sur les images d'une vidéo en cours de téléchargement sur mon serveur. Je veux juste lire les cadres disponibles et les écrire dans un répertoire. Et attendez qu'une autre partie de la vidéo soit téléchargée et écrivez les images dans le répertoire. Et je devrais attendre que chaque image soit complètement téléchargée, puis l'écrire dans un fichier.

Pouvez-vous me dire comment puis-je le faire avec OpenCV (Python)?

Edit 1: J'ai écrit ce code pour capturer la vidéo à partir d'un fichier, tandis que de nouvelles données sont ajoutées à la fin du fichier. En d'autres termes, le fichier out.mp4 N'est pas une vidéo complète et un autre programme écrit de nouvelles images dessus. Ce que je vais faire, c'est attendre que l'autre programme écrive de nouvelles images, puis les lise et les affiche.

Voici mon code:

import cv2
cap = cv2.VideoCapture("./out.mp4")

while True:
    if cap.grab():
        flag, frame = cap.retrieve()
        if not flag:
            continue
        else:
            cv2.imshow('video', frame)
    if cv2.waitKey(10) == 27:
        break

Le problème est donc l'appel cap.grab()! quand il n'y a pas de cadre, il retournera False! Et il ne capturera plus d'images, même si j'attends longtemps.

38
Mehran

Après avoir lu la documentation de VideoCapture . Je pensais que vous pouviez dire à VideoCapture, quelle image traiter lors de notre prochain appel à VideoCapture.read() (ou VideoCapture.grab() ).

Le problème est que lorsque vous voulez read() une image qui n'est pas prête, l'objet VideoCapture reste bloqué sur cette image et ne continue jamais. Vous devez donc le forcer à recommencer à partir du cadre précédent.

Voici le code

import cv2

cap = cv2.VideoCapture("./out.mp4")
while not cap.isOpened():
    cap = cv2.VideoCapture("./out.mp4")
    cv2.waitKey(1000)
    print "Wait for the header"

pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
while True:
    flag, frame = cap.read()
    if flag:
        # The frame is ready and already captured
        cv2.imshow('video', frame)
        pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
        print str(pos_frame)+" frames"
    else:
        # The next frame is not ready, so we try to read it again
        cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1)
        print "frame is not ready"
        # It is better to wait for a while for the next frame to be ready
        cv2.waitKey(1000)

    if cv2.waitKey(10) == 27:
        break
    if cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
        # If the number of captured frames is equal to the total number of frames,
        # we stop
        break
46
Mehran

utilisez ceci -

import cv2
cap = cv2.VideoCapture('path of video file')
count = 0
while cap.isOpened():
    ret,frame = cap.read()
    cv2.imshow('window-name',frame)
    cv2.imwrite("frame%d.jpg" % count, frame)
    count = count + 1
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break


cap.release()
cv2.destroyAllWindows()  # destroy all the opened windows
12
prtkp

Selon les dernières mises à jour pour OpenCV 3.0 et versions ultérieures, vous devez modifier le Property Identifiers comme suit dans le code de Mehran:

cv2.cv.CV_CAP_PROP_POS_FRAMES

à

cv2.CAP_PROP_POS_FRAMES

et de même pour cv2.CAP_PROP_POS_FRAME_COUNT.

J'espère que ça aide.

8
srihegde

Dans la documentation d'openCV, il existe un exemple pour obtenir une vidéo image par image. Il est écrit en c ++ mais il est très facile de porter l’exemple sur python - vous pouvez rechercher chaque documentation de fumction pour savoir comment l’appeler en python.

#include "opencv2/opencv.hpp"

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    Mat edges;
    namedWindow("edges",1);
    for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        cvtColor(frame, edges, CV_BGR2GRAY);
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
        Canny(edges, edges, 0, 30, 3);
        imshow("edges", edges);
        if(waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}
7
zenpoy

Voici comment je commencerais à résoudre ceci:

  1. Créer un graveur vidéo:

    import cv2.cv as cv
    videowriter = cv.CreateVideoWriter( filename, fourcc, fps, frameSize)
    

    Vérifiez ici les paramètres valides

  2. Boucle pour récupérer [1] et écrire les cadres:

    cv.WriteFrame( videowriter, frame )
    

    doc WriteFrame

[1] zenpoy a déjà pointé dans la bonne direction. Vous devez juste savoir que vous pouvez récupérer des images depuis une webcam ou un fichier :-)

J'espère que j'ai bien compris les exigences.

2
Robert Caspary

La seule solution que j'ai trouvée n'est pas de définir l'index sur une image précédente et d'attendre (puis OpenCV arrête de lire les images, de toute façon), mais d'initialiser la capture une fois de plus. Donc, ça ressemble à ça:

cap = cv2.VideoCapture(camera_url)
while True:
    ret, frame = cap.read()

    if not ret:
        cap = cv.VideoCapture(camera_url)
        continue

    # do your processing here

Et ça marche parfaitement!

2
Alexander Lysenko