画像処理より何より、先ず実態調査が重要なので
JMF(Java Media Framework)を用いて連続的に動画を記録しようと考えました。
市販のHDDレコーダーを使えばそれでいいのでしょうが
比較的高価だし、重たいし、で現場に持っていくのなら
ポータブルのHDDとかの方が断然いいよねぇと思いましたので
JMFで作ってみたんです。
結果は惨敗。
やったことは、1~1.5時間ぐらいの長さのH263のmovファイル(QuickTime)を
延々と作り続けるだけなのですが
最初はいいのですが、半日~数日立つと、
Unexpected Errorだか何だか、Native Codeでエラーが出た
といった内容のエラーが出て、プログラム全体が落ちてしまいます。
このエラー、原因分からず、私には対処の仕方がわかりませんでした。
決してOutOfMemoryとかでは無い様なのですが
どうもスペックの低いパソコンほどエラーが出るまでの時間が短いので
ハード的な原因(例えば読み込み、書きこみ時のエラー等?)に起因するのでは?
と考えています。
でも良く分かりません。
このプログラムはDataSorceを何回もコピーして使っているのですが
もしかしたらこういうやり方の回数が決まっているのかもしれません。
(でも短いファイルを大量に作っても大丈夫なので回数でもないよなぁ。
やっぱり全くわかりませんなぁ)
でこの件、仕方なく
プログラムが落っこちてもそのプロセスだけ落ちてね
という意味合いで、ProcessBuliderを使って外部プロセスとして
動画保存プログラムを起動させることとしました。
こうすると、ファイルとファイルのつなぎ目に4~5秒ぐらいの間が空いてしまいますが
なんとか落ちずに1週間は稼働し続けています。
今現場に持って行ってもらってますのでもっと長期でいけるか楽しみです。
なお、このプログラムを使ったPCは
DELL社製のCore2Duoの2GHzぐらい
メモリは 1GBのパソコンでした。
あとでソースコードをのっけようと思いますが
バックアップとらずに現場に持っていったんでまた今度。
2010年3月19日金曜日
2008年9月29日月曜日
JMF(Java Media Framework) による data strage memo
import java.awt.BorderLayout;
import java.awt.Frame;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSinkException;
import javax.media.NoDataSourceException;
import javax.media.NoProcessorException;
import javax.media.Processor;
import javax.media.control.TrackControl;
import javax.media.format.VideoFormat;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
import javax.media.protocol.SourceCloneable;
/**
* DVカメラからの動画キャプチャとそのデータをファイルに保存する方法。
* ついでに動画表示をする。
* @author Yuko
*/
public class CaptureAndDisplay {
public static void main(String[] args){
/** * 入力もと */
MediaLocator in=null;
/** * 出力先 */
MediaLocator out=null;
/** DVカメラを入力先とする */
final String VFW="vfw://0";
in = new MediaLocator( VFW );
/** 出力先ファイル名を指定 */
try {
File file = new File("C:\\test\\test.avi");
out = new MediaLocator( file.toURI().toURL() );
} catch (MalformedURLException e2) {
e2.printStackTrace(); }
/**
* 書き込み用DataSinkに色々設定するためのProcessor
*/
Processor processor4DataSink =null;
/**
* 画像表示用のProcessor。別にPlayerでもよい。
*/
Processor processor4Display=null;
/**
* DVカメラのデータ。MediaLocatorより。
* これの複製を作って、DataSink用Processor、Player(ディスプレー)用Processorに渡す。
*/
DataSource ds =null;
/**
* これはProcessorに使用するDataSource
*/
DataSource ds4Processor=null;
/**
* これはProcessorに使用するDataSource
*/
DataSource ds4DataSink=null;
/**
* 画像データをファイルに書き込むためのもの
*/
DataSink filewriter = null;
/*
* Windowsでmpegを再生する場合、最適化のためにWindowsの一部の機能を使っていたりするため
* 一部javaの機能が使えない場合がある。
* このためJMFでは、javaの機能が使えるようなmpeg再生モジュールを別途用意しているとのこと
* デフォルトでは前期のWindows最適化のモジュールが選択されているため
* java用再生モジュールを使用するには下記のようなsetHintが必要。
*/
Manager.setHint(Manager.PLUGIN_PLAYER,Boolean.TRUE);//これだけ実行すれば何となくうまく行く様子。
// Manager.setHint(Manager.LIGHTWEIGHT_RENDERER,Boolean.TRUE); //この文を生かすと画像がちらつく。
try {
//とりあえず、おおもとのDataSourceを作る
ds = Manager.createDataSource(in);
} catch (NoDataSourceException e2) {
e2.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace(); }
/*
* DataSourceの複製の作成。
* Processorは、画像表示とDataSinkによる動画データのファイル書き込みの両方を一度にはできないらしい。
* このためDataSourceを複製し、別々のDataSourceをつくり、それからそれぞれのProcessorを作成しないといけない。
* (表示のためだけならPlayerで良い)
*/
ds=Manager.createCloneableDataSource(ds);
ds4Processor=((SourceCloneable)ds).createClone();
try {
processor4DataSink=Manager.createProcessor(ds4Processor);
processor4Display=Manager.createProcessor(ds);
} catch (NoProcessorException e3) {
e3.printStackTrace();
} catch (IOException e3) {
e3.printStackTrace();
}
processor4DataSink.configure();
while(processor4DataSink.getState()!=Processor.Configured);
processor4Display.configure();
while(processor4Display.getState()!=Processor.Configured);
TrackControl[] tc= processor4DataSink.getTrackControls();
//tc[0]がVideoFormatと決めつけていますが、場合によっては違うことが十分あると思うので
//instanceof とかでちゃんと調べた方がいいと思います。
TrackControl t=tc[0];
//Formatの確認。本来不必要。
Format f=t.getFormat();
System.out.println("format > "+f.toString());
//Formatを設定する
t.setFormat(new Format(VideoFormat.MJPG));
// t.setFormat(new YUVFormat());// <= これはデータサイズが大きいので困る。
//Formatの確認。本来不必要。
f=t.getFormat();
System.out.println("format > "+f.toString());
//.avi形式を指定。これをしないとNoDataSinkExceptionが出るらしい。
processor4DataSink.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.MSVIDEO));
//ProcessorをPlayerと同じように使うための作法
processor4Display.setContentDescriptor(null);
//Realizeの状態にする。
processor4Display.realize();
processor4DataSink.realize();
while(processor4DataSink.getState()!=Processor.Realized);
while(processor4Display.getState()!=Processor.Realized);//realize待ち
//表示用のFrame作成
Frame myframe=new Frame("MONITOR");
// myf2.add(display.getControlPanelComponent(),BorderLayout.SOUTH);
myframe.add(processor4Display.getVisualComponent(),BorderLayout.CENTER);
//720×480を美しく表示するためにはこのサイズがよさそう。
myframe.setSize(728,535); myframe.setVisible(true);
/*
* Processorをスタートさせておかないと、ファイル書き込みは始まらない。
* しかしAPIGuideにはそのようには書いていない。(多分)
* 困ったもんです。
*/
processor4DataSink.start();
processor4Display.start();
//上記のように設定したのち、改めてここで、DataSourceを取得する必要あるらしい。
ds4DataSink = processor4DataSink.getDataOutput();
try {
filewriter=Manager.createDataSink(ds4DataSink, out);
//filewriter=Manager.createDataSink(ds, out); // <= このような使い方はできなかった
//ファイルオープン
filewriter.open();
//ファイル書き込み開始。ただし前述のようにProcessorをスタートさせておかないと、ファイル書き込みは始まらない。
filewriter.start();
} catch (NoDataSinkException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//とりあえず30secだけ録画
try {
Thread.sleep(30000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
//書き込み停止。ただしこれはやらなくても良い様子。
filewriter.stop();
} catch (IOException e) {
e.printStackTrace();
}
/*
* Processor停止。
* これをやらないと読めないファイルになるらしい。
* Processor stop()では読めるファイルにならなかった。
* しかしAPIGuideには多分書いていない。
*/
processor4DataSink.close();
filewriter.close();
System.out.println("file closed");
System.exit(0);
}
}
import java.awt.Frame;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSinkException;
import javax.media.NoDataSourceException;
import javax.media.NoProcessorException;
import javax.media.Processor;
import javax.media.control.TrackControl;
import javax.media.format.VideoFormat;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
import javax.media.protocol.SourceCloneable;
/**
* DVカメラからの動画キャプチャとそのデータをファイルに保存する方法。
* ついでに動画表示をする。
* @author Yuko
*/
public class CaptureAndDisplay {
public static void main(String[] args){
/** * 入力もと */
MediaLocator in=null;
/** * 出力先 */
MediaLocator out=null;
/** DVカメラを入力先とする */
final String VFW="vfw://0";
in = new MediaLocator( VFW );
/** 出力先ファイル名を指定 */
try {
File file = new File("C:\\test\\test.avi");
out = new MediaLocator( file.toURI().toURL() );
} catch (MalformedURLException e2) {
e2.printStackTrace(); }
/**
* 書き込み用DataSinkに色々設定するためのProcessor
*/
Processor processor4DataSink =null;
/**
* 画像表示用のProcessor。別にPlayerでもよい。
*/
Processor processor4Display=null;
/**
* DVカメラのデータ。MediaLocatorより。
* これの複製を作って、DataSink用Processor、Player(ディスプレー)用Processorに渡す。
*/
DataSource ds =null;
/**
* これはProcessorに使用するDataSource
*/
DataSource ds4Processor=null;
/**
* これはProcessorに使用するDataSource
*/
DataSource ds4DataSink=null;
/**
* 画像データをファイルに書き込むためのもの
*/
DataSink filewriter = null;
/*
* Windowsでmpegを再生する場合、最適化のためにWindowsの一部の機能を使っていたりするため
* 一部javaの機能が使えない場合がある。
* このためJMFでは、javaの機能が使えるようなmpeg再生モジュールを別途用意しているとのこと
* デフォルトでは前期のWindows最適化のモジュールが選択されているため
* java用再生モジュールを使用するには下記のようなsetHintが必要。
*/
Manager.setHint(Manager.PLUGIN_PLAYER,Boolean.TRUE);//これだけ実行すれば何となくうまく行く様子。
// Manager.setHint(Manager.LIGHTWEIGHT_RENDERER,Boolean.TRUE); //この文を生かすと画像がちらつく。
try {
//とりあえず、おおもとのDataSourceを作る
ds = Manager.createDataSource(in);
} catch (NoDataSourceException e2) {
e2.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace(); }
/*
* DataSourceの複製の作成。
* Processorは、画像表示とDataSinkによる動画データのファイル書き込みの両方を一度にはできないらしい。
* このためDataSourceを複製し、別々のDataSourceをつくり、それからそれぞれのProcessorを作成しないといけない。
* (表示のためだけならPlayerで良い)
*/
ds=Manager.createCloneableDataSource(ds);
ds4Processor=((SourceCloneable)ds).createClone();
try {
processor4DataSink=Manager.createProcessor(ds4Processor);
processor4Display=Manager.createProcessor(ds);
} catch (NoProcessorException e3) {
e3.printStackTrace();
} catch (IOException e3) {
e3.printStackTrace();
}
processor4DataSink.configure();
while(processor4DataSink.getState()!=Processor.Configured);
processor4Display.configure();
while(processor4Display.getState()!=Processor.Configured);
TrackControl[] tc= processor4DataSink.getTrackControls();
//tc[0]がVideoFormatと決めつけていますが、場合によっては違うことが十分あると思うので
//instanceof とかでちゃんと調べた方がいいと思います。
TrackControl t=tc[0];
//Formatの確認。本来不必要。
Format f=t.getFormat();
System.out.println("format > "+f.toString());
//Formatを設定する
t.setFormat(new Format(VideoFormat.MJPG));
// t.setFormat(new YUVFormat());// <= これはデータサイズが大きいので困る。
//Formatの確認。本来不必要。
f=t.getFormat();
System.out.println("format > "+f.toString());
//.avi形式を指定。これをしないとNoDataSinkExceptionが出るらしい。
processor4DataSink.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.MSVIDEO));
//ProcessorをPlayerと同じように使うための作法
processor4Display.setContentDescriptor(null);
//Realizeの状態にする。
processor4Display.realize();
processor4DataSink.realize();
while(processor4DataSink.getState()!=Processor.Realized);
while(processor4Display.getState()!=Processor.Realized);//realize待ち
//表示用のFrame作成
Frame myframe=new Frame("MONITOR");
// myf2.add(display.getControlPanelComponent(),BorderLayout.SOUTH);
myframe.add(processor4Display.getVisualComponent(),BorderLayout.CENTER);
//720×480を美しく表示するためにはこのサイズがよさそう。
myframe.setSize(728,535); myframe.setVisible(true);
/*
* Processorをスタートさせておかないと、ファイル書き込みは始まらない。
* しかしAPIGuideにはそのようには書いていない。(多分)
* 困ったもんです。
*/
processor4DataSink.start();
processor4Display.start();
//上記のように設定したのち、改めてここで、DataSourceを取得する必要あるらしい。
ds4DataSink = processor4DataSink.getDataOutput();
try {
filewriter=Manager.createDataSink(ds4DataSink, out);
//filewriter=Manager.createDataSink(ds, out); // <= このような使い方はできなかった
//ファイルオープン
filewriter.open();
//ファイル書き込み開始。ただし前述のようにProcessorをスタートさせておかないと、ファイル書き込みは始まらない。
filewriter.start();
} catch (NoDataSinkException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//とりあえず30secだけ録画
try {
Thread.sleep(30000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
//書き込み停止。ただしこれはやらなくても良い様子。
filewriter.stop();
} catch (IOException e) {
e.printStackTrace();
}
/*
* Processor停止。
* これをやらないと読めないファイルになるらしい。
* Processor stop()では読めるファイルにならなかった。
* しかしAPIGuideには多分書いていない。
*/
processor4DataSink.close();
filewriter.close();
System.out.println("file closed");
System.exit(0);
}
}
2007年11月8日木曜日
corega CG-WLNCMNGV2
安価な家庭用のネットワークカメラを使い
自作のJAVAプログラムで
最終的には工場内の設備の自動監視を
おこなうことを企んでいます。
そこでEthernetに接続できて
無線機能がついている物の中で一番安い
corega CG-WLNCMNGV2というカメラを
買ってきて遊んでいます。
しかし、ネットワークカメラって
画像が勝手に流れてくるような
ビデオカメラのようなものを考えていたので
JMFで
MediaLocator("vfw://0")とすれば
captureできるのかと考えていたのですが
仕様をよく読んでみると
このカメラはJPEG画像を
連続的に送っているだけのようで
残念ながらJMFではMotion-JPEGは扱えないようなので
結局、カメラ内部に保存されている
IMAGE.JPGというファイルを
ImageIOのread()メソッドを使って読むことにしました。
これで一応目的とすることは
ある程度できるようになったのですが
残念ながら 2.5fps程度が精々です。
カメラ自体は20fpsは可能なようなので
何か別の方法があると思うのですが
ちょっとうまくいきません。
あと画像処理をするには
露光を一定にできないのも少々難有りですね。
自作のJAVAプログラムで
最終的には工場内の設備の自動監視を
おこなうことを企んでいます。
そこでEthernetに接続できて
無線機能がついている物の中で一番安い
corega CG-WLNCMNGV2というカメラを
買ってきて遊んでいます。
しかし、ネットワークカメラって
画像が勝手に流れてくるような
ビデオカメラのようなものを考えていたので
JMFで
MediaLocator("vfw://0")とすれば
captureできるのかと考えていたのですが
仕様をよく読んでみると
このカメラはJPEG画像を
連続的に送っているだけのようで
残念ながらJMFではMotion-JPEGは扱えないようなので
結局、カメラ内部に保存されている
IMAGE.JPGというファイルを
ImageIOのread()メソッドを使って読むことにしました。
これで一応目的とすることは
ある程度できるようになったのですが
残念ながら 2.5fps程度が精々です。
カメラ自体は20fpsは可能なようなので
何か別の方法があると思うのですが
ちょっとうまくいきません。
あと画像処理をするには
露光を一定にできないのも少々難有りですね。
2007年10月9日火曜日
Javaでの画像取扱い: IEEE1394について
JavaでIEEE1394から取り込んだ動画を取り扱う方法がないかを調べてみました。
Javaで動画を取り扱うには、sunで配布しているJMF(Java Media Framework)というものを使います。このJMFをインストールして使えば、USBカメラなんかはデータ元に vfwを指定することで簡単に扱えるようになるのですが、IEEE1394から取り込んだ動画を同様に扱うとエラーが出ます。
どうも、IEEE1394から読み込む画像はDVSDという形式で、JMFのサポート範囲外であるためだったらしいです。
でもなんとか読み込む方法がないかと探していたら、Windowsの場合なんかだと
「Panasonic VFW DV codec というビデオコーデックをインストールすることでDVSD形式のデジタルビデオカメラの信号をJavaで認識することができた 」
との記述をネット上で見つけることができました。
http://archives.java.sun.com/cgi-bin/wa?A2=ind0510&L=jmf-interest&F=&S=&P=3500
ダウンロードはこんな所からできるようです。
http://cowscorpion.com/Codec/PanasonicDVCodec.html
Javaで何とかしたわけではないので、ちょっとインチキっぽいですが
この情報私には大変役にたちました。
尚、私はコーデックが何で、これが何をしてJavaで認識できるようになったのかも分からないド素人です。
Javaで動画を取り扱うには、sunで配布しているJMF(Java Media Framework)というものを使います。このJMFをインストールして使えば、USBカメラなんかはデータ元に vfwを指定することで簡単に扱えるようになるのですが、IEEE1394から取り込んだ動画を同様に扱うとエラーが出ます。
どうも、IEEE1394から読み込む画像はDVSDという形式で、JMFのサポート範囲外であるためだったらしいです。
でもなんとか読み込む方法がないかと探していたら、Windowsの場合なんかだと
「Panasonic VFW DV codec というビデオコーデックをインストールすることでDVSD形式のデジタルビデオカメラの信号をJavaで認識することができた 」
との記述をネット上で見つけることができました。
http://archives.java.sun.com/cgi-bin/wa?A2=ind0510&L=jmf-interest&F=&S=&P=3500
ダウンロードはこんな所からできるようです。
http://cowscorpion.com/Codec/PanasonicDVCodec.html
Javaで何とかしたわけではないので、ちょっとインチキっぽいですが
この情報私には大変役にたちました。
尚、私はコーデックが何で、これが何をしてJavaで認識できるようになったのかも分からないド素人です。
登録:
投稿 (Atom)