web-dev-qa-db-ja.com

Javaベースのアプリケーションで使用するためにライブビデオデバイスから画像をキャプチャする最良の方法は何ですか?

特定のシナリオを準リアルタイムで検出するための画像処理の問題を調査しています。私の目標は、ライブビデオをMotion JPEGフレームとして私のJavaコードsomehow)として到着させることです。

私は Java Media Framework に精通しており、悲しいことに、私たちはそれが事実上無効なAPIであると考えることができると思います。私は Axisボックス にも精通しており、私はそれらの解決策を本当に気に入っていますが、私の特定の関心のある点に関する重要なフィードバックをいただければ幸いです。

これが私がこの議論の目的のために「最高」を定義する方法です:

  • レイテンシ-このビデオストリームを使用してカメラを制御している場合、可能であれば往復のレイテンシを100ミリ秒未満に維持したいと考えています。これは、私の制御入力から目に見える変化が見える時間までの時間として測定されます。しばらくしてから編集してください。もう1つ覚えておくべきことは、カメラ制御は手動と自動(イベントトリガー)の組み合わせになる可能性が高いということです。高品質のフィードが個別にアーカイブされている場合でも、これらの画像をすぐに表示する必要があります。
  • コスト-無料/オープンソースは無料ではないよりも優れています。
  • 調整可能なコーデックパラメータ-特定の状況でコーデックを調整できる必要があります。時には、高速で低解像度のストリームの方が実際には処理が簡単です。
  • Java-との「統合」-このソリューションをコードにフックするのはどれほどの問題ですか?ソケット経由でパケットを送信していますか?URLにアクセスしていますか?Direct3D/JNIの組み合わせをインストールしていますか?
  • Windows/Linux /両方? -いくつかの種類のOSに配信する必要があるため、オペレーティングシステムにとらわれないソリューションを好みますが、一方には最適であるが他方には最適でないソリューションがある場合があります。

注:私は他の画像/ビデオキャプチャコーデックを認識しており、それがこの質問の焦点では​​ありません。フレームの精度が失われるため、ストリーミングAPI(MPEG4など)に特に関心がない。ただし、別のフレーム精度のデータストリームを配信するという私の質問に対する解決策がある場合は、ご連絡ください。

この質問のフォローアップ:この時点では、ソフトウェアまたはPCで直接ビデオをキャプチャするのではなく、 Axisビデオエンコーダー などのアプライアンスを購入する傾向があります。しかし、誰かが代替案を持っているなら、私はそれらを聞きたいです。

23
Bob Cross

このJavaCV実装は正常に動作します。

コード:

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

ライブビデオの表示に関する投稿 カメラからもあり、 JavaCVの構成: もあります。

これはあなたの要件を満たしていると思います。

7
gtiwari333

FMJは間違いなくビデオをキャプチャしてMJPEGフレームに変換できます。

3
Ken Larson

JMFのデッドネスについて、あなたは FMJ実装 を知っていますか?それが「最良の」ソリューションとしての資格があるかどうかはわかりませんが、おそらく議論に追加する価値があります。

2
Greg Mattes

以下は Marvin Framework を使用した非常に簡単な実装です。 Marvinを使用すると、リアルタイムのビデオ処理を簡単に追加できます。

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

別の リアルタイムビデオ処理に複数のアルゴリズムを適用する。

これは、高解像度のビデオ出力を備えたJavaCV実装であり、他のソリューションよりもフレームレートの顕著な低下はありません(ただし、Webカメラを再フォーカスしたときにのみ、わずかな低下に気付きましたが、少しの間だけです)。

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