webentwicklung-frage-antwort-db.com.de

Was ist die beste Methode, um Bilder von einem Live-Videogerät zur Verwendung durch eine Java-basierte Anwendung aufzunehmen?

Ich beschäftige mich mit einem Bildverarbeitungsproblem für die Erkennung bestimmter Szenarien in Halb-Echtzeit. Mein Ziel ist es, dass das Live-Video als Motion JPEG-Frames in meinem Java-Code ankommt irgendwie .

Ich bin mit dem Java Media Framework vertraut und leider können wir dies als eine praktisch tote API betrachten. Ich kenne mich auch mit Achsenboxen aus, und obwohl mir deren Lösung wirklich gefällt, würde ich mich über jedes kritische Feedback zu meinen speziellen Interessengebieten freuen.

So definiere ich "am besten" für den Zweck dieser Diskussion:

  • Latenz - Wenn ich die Kamera mithilfe dieses Videostreams steuere, möchte ich die Latenz für Hin- und Rückfahrt nach Möglichkeit auf weniger als 100 Millisekunden beschränken. Das ist die Zeit zwischen meiner Steuereingabe und dem Zeitpunkt, an dem ich die sichtbare Änderung sehe. Einige Zeit später BEARBEITEN: Eine weitere zu beachtende Sache ist, dass die Kamerasteuerung wahrscheinlich eine Kombination aus manuell und automatisch ist (Ereignisauslöser). Wir müssen diese Bilder sofort sehen, auch wenn der qualitativ hochwertige Feed separat archiviert wird.
  • Kostenfrei/Open Source ist besser als nicht kostenlos.
  • Einstellbare Codec-Parameter - Ich muss den Codec für bestimmte Situationen einstellen können. Manchmal ist ein Stream mit hoher Geschwindigkeit und niedriger Auflösung tatsächlich einfacher zu verarbeiten.
  • "Integration" mit Java - Wie viel Mühe macht es, diese Lösung mit meinem Code zu verknüpfen? Sende ich Pakete über einen Socket? URLs treffen? Direct3D/JNI-Kombinationen installieren?
  • Windows/Linux/beides? - Ich würde eine betriebssystemunabhängige Lösung vorziehen, weil ich mehrere Betriebssystemvarianten unterstützen muss, aber es gibt möglicherweise eine Lösung, die für die eine, aber nicht für die andere, optimal ist.

HINWEIS: Mir sind andere Codecs für die Bild-/Videoaufnahme bekannt, und das steht nicht im Mittelpunkt dieser Frage. Ich bin speziell nicht an Streaming-APIs (z. B. MPEG4) interessiert, da die Bildgenauigkeit abnimmt. Wenn es jedoch eine Lösung für meine Frage gibt, die einen anderen rahmengenauen Datenstrom liefert, melden Sie sich bitte an.

Follow-up zu dieser Frage: An dieser Stelle bin ich sehr geneigt, Geräte wie den Axis-Video-Encoder zu kaufen anstatt zu versuchen, das Video in Software oder direkt auf dem PC aufzunehmen. Wenn jemand Alternativen hat, würde ich sie gerne hören.

23
Bob Cross

Diese JavaCV-Implementierung funktioniert einwandfrei.

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();
    }
}

Es gibt auch post zum Ansehen von Live-Videos von der Kamera. Und Konfiguration für JavaCV:

Ich denke, das wird Ihre Anforderungen erfüllen.

7
gtiwari333

FMJ kann definitiv Videos aufnehmen und in MJPEG-Frames umwandeln.

3
Ken Larson

Haben Sie Kenntnis von der Umsetzung von FMJ in Bezug auf die Unfähigkeit von JMF ? Ich weiß nicht, ob es sich um die "beste" Lösung handelt, aber es lohnt sich wahrscheinlich, die Diskussion zu ergänzen.

2
Greg Mattes

Im Folgenden wird eine sehr einfache Implementierung mit Marvin Framework gezeigt. Mit Marvin können Sie problemlos Echtzeit-Videoverarbeitung hinzufügen. 

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);
        }
    }
}

Ein weiteres Beispiel Anwendung mehrerer Algorithmen für die Echtzeit-Videoverarbeitung.

Dies ist meine JavaCV-Implementierung mit hochauflösender Videoausgabe und keinem merklichen Abfall der Framerate als bei anderen Lösungen (nur wenn meine Webcam einen neuen Fokus aufweist, fällt mir ein leichter Rückgang ein, allerdings nur für einen 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