web-dev-qa-db-fra.com

Quelle est la meilleure méthode pour capturer des images à partir d'un périphérique vidéo en direct pour une utilisation par une application basée sur Java?

Je suis à la recherche d'un problème de traitement d'image pour la détection de certains scénarios en temps semi-réel. Mon objectif est que la vidéo en direct arrive sous forme d'images Motion JPEG dans mon code Java d'une certaine manière .

Je connais bien le Java Media Framework et, malheureusement, je pense que nous pouvons considérer cela comme une API réellement morte. Je connais aussi (boîtes d’axe) et, même si j’aime beaucoup leur solution, j’apprécierais tout commentaire critique sur mes points d’intérêt spécifiques.

Voici comment je définis "le mieux" aux fins de cette discussion:

  • Latence - si je contrôle la caméra à l'aide de ce flux vidéo, j'aimerais si possible maintenir la latence aller-retour à moins de 100 millisecondes. Cela correspond au temps écoulé entre l'entrée de contrôle et le moment où je vois le changement visible. EDIT peu de temps après: il ne faut pas oublier non plus que le contrôle de la caméra est probablement une combinaison de manuel et d’automatique (déclencheurs d’événements). Nous devons voir ces images immédiatement, même si le flux de haute qualité est archivé séparément.
  • Coût gratuit/open source est mieux que pas gratuit.
  • Paramètres de codec ajustables - Je dois pouvoir ajuster le codec dans certaines situations. Parfois, un flux haute résolution basse résolution est en réalité plus facile à traiter.
  • "Intégration" avec Java - Dans quelle mesure cette solution est-elle liée à mon code? Est-ce que j'envoie des paquets sur un socket? Frapper les URL? Installation de combinaisons Direct3D/JNI?
  • Windows/Linux/les deux? - Je préférerais une solution agnostique pour les systèmes d’exploitation, car je dois proposer plusieurs versions de système d’exploitation, mais il peut exister une solution optimale pour l’une mais pas l’autre.

REMARQUE: je connais d’autres codecs de capture d’image/vidéo et ce n’est pas le sujet de cette question. Je suis spécifiquement not intéressé par la diffusion d’API (par exemple, MPEG4) en raison de la perte de précision des images. Cependant, s'il existe une solution à ma question qui fournit un autre flux de données à la précision d'une trame, merci de bien vouloir l'insérer.

Suite à cette question: à ce stade, je suis fortement enclin à acheter des appareils tels que les encodeurs vidéo Axis plutôt que d'essayer de capturer la vidéo dans un logiciel ou directement sur PC. Cependant, si quelqu'un a des alternatives, j'aimerais les entendre.

23
Bob Cross

Cette implémentation JavaCV fonctionne bien.

CODE:

import com.googlecode.javacv.OpenCVFrameGrabber;

import com.googlecode.javacv.cpp.opencv_core.IplImage;
import static com.googlecode.javacv.cpp.opencv_highgui.*;

public class CaptureImage {
    private static void captureFrame() {
        // 0-default camera, 1 - next...so on
        final OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
        try {
            grabber.start();
            IplImage img = grabber.grab();
            if (img != null) {
                cvSaveImage("capture.jpg", img);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        captureFrame();
    }
}

Il y a aussi poste sur le visionnage de la vidéo en direct de Camera .And configuration pour JavaCV:

Je pense que cela répondra à vos exigences.

7
gtiwari333

FMJ peut définitivement capturer une vidéo et la transformer en images MJPEG.

3
Ken Larson

En ce qui concerne la mort de JMF, êtes-vous au courant de la mise en œuvre de FMJ ? Je ne sais pas s'il s'agit de la "meilleure" solution, mais cela vaut probablement la peine d'ajouter à la discussion.

2
Greg Mattes

Ci-dessous, une implémentation très simple utilisant Cadre Marvin . En utilisant Marvin, vous pouvez facilement ajouter un traitement vidéo en temps réel. 

import javax.swing.JFrame;
import marvin.gui.MarvinImagePanel;
import marvin.image.MarvinImage;
import marvin.video.MarvinJavaCVAdapter;
import marvin.video.MarvinVideoInterface;

public class SimpleVideoTest extends JFrame implements Runnable{

    private MarvinVideoInterface    videoAdapter;
    private MarvinImage             image;
    private MarvinImagePanel        videoPanel;

    public SimpleVideoTest(){
        super("Simple Video Test");

        // Create the VideoAdapter and connect to the camera
        videoAdapter = new MarvinJavaCVAdapter();
        videoAdapter.connect(0);

        // Create VideoPanel
        videoPanel = new MarvinImagePanel();
        add(videoPanel);

        // Start the thread for requesting the video frames 
        new Thread(this).start();

        setSize(800,600);
        setVisible(true);
    }

    public static void main(String[] args) {
        SimpleVideoTest t = new SimpleVideoTest();
        t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void run() {
        while(true){
            // Request a video frame and set into the VideoPanel
            image = videoAdapter.getFrame();
            videoPanel.setImage(image);
        }
    }
}

Autre exemple exemple appliquant plusieurs algorithmes pour le traitement vidéo en temps réel.

Ceci est mon implémentation JavaCV avec une sortie vidéo haute résolution et aucune baisse notable de la cadence que d’autres solutions (c’est seulement lorsque ma webcam se recentre, que je remarque une légère baisse, mais pendant un moment).

import Java.awt.image.BufferedImage;
import Java.io.File;

import javax.swing.JFrame;

import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.OpenCVFrameRecorder;
import com.googlecode.javacv.cpp.opencv_core.IplImage;

public class Webcam implements Runnable {

    IplImage image;
    static CanvasFrame frame = new CanvasFrame("Web Cam");
    public static boolean running = false;

    public Webcam()
    {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void run()
    {
        try
        {
            grabber.setImageWidth(800);
            grabber.setImageHeight(600);
            grabber.start();
            while (running)
            {
                IplImage cvimg = grabber.grab();
                BufferedImage image;
                if (cvimg != null)
                {
                    // opencv_core.cvFlip(cvimg, cvimg, 1); // mirror
                    // show image on window
                    image = cvimg.getBufferedImage();
                    frame.showImage(image);
                }
            }
            grabber.stop();
            frame.dispose();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String... args)
    {
        Webcam webcam = new Webcam();
        webcam.start();
    }

    public void start()
    {
        new Thread(this).start();
        running = true;
    }

    public void stop()
    {
        running = false;
    }
}
0
syb0rg