OpenCVのJavaラッパーを使用しています。私はフィルムのフレームにイテレータを書き込もうとしました。私の問題は、イテレータが巨大なメモリリークだということです。ここでは、このリークを持っているイテレータの非常に単純化されたバージョンは次のとおりです。反復処理によるメモリリークOpencvフレーム
public static final class SimpleIt implements Iterator<Mat> {
private final VideoCapture capture;
boolean hasNext;
public SimpleIt(final VideoCapture capture) {
this.capture = capture;
hasNext = capture.grab();
}
@Override
public boolean hasNext() {
return hasNext;
}
@Override
public Mat next() {
final Mat mat = new Mat();
capture.retrieve(mat);
hasNext = capture.grab();
return mat;
}
}
私はこのループを使用してこのコードの上に反復処理:
final VideoCapture vc = new VideoCapture("/path/to/file");
final SimpleIt it = new SimpleIt(vc);
while (it.hasNext) {
it.next();
}
だけ反復は、メモリ消費の線形が増加します。問題はnext() - Methodの最初の行であることがわかります。常に新しいMatを作成します。しかし、Javaだけでは、このMatは反復コードが次の画像に反復するとすぐに範囲外になります。
私は毎回新しいマットを使用しないことで、この問題を克服するが、常に同じマット・オブジェクトを上書きし、このようなことができます:
private final VideoCapture capture;
private final Mat mat = new Mat();
boolean hasNext;
@Override
public Mat next() {
capture.retrieve(mat);
hasNext = capture.grab();
return mat;
}
しかし、今意志イテレータによって与えられた最後のフレーム上書きされる。したがって、この1つのフレームに興味があれば、後で使用するために外部に保持することはできません。私はそれをコピーすることができます、もちろん、それはまた高価だろう。
Javaヒープスペースではないため、ガベージコレクタはメモリ消費を認識しないため、Matオブジェクトを破棄しないことが問題であると想定します。ループ内でmat.release()を呼び出すと役立ちますが、もちろん実際のコードでは、これは私のMatオブジェクトに対してガベージコレクションを持たないことを意味します。
誰もそれを行う方法を知っていますか?
編集:
私の第二の溶液に問題が何であるかを明確にすることがないようなので、私はより明確にそれを書き留め。イテレータの第二のバージョンで
final VideoCapture vc = new VideoCapture("/path/to/file");
final SimpleIt it = new SimpleIt(vc);
int i = 0;
Mat save = null;
while (it.hasNext) {
final Mat next = it.next();
if (i == 10) {
save = next;
Highgui.imwrite("/path/to/10.png", save);
} else if (i == 30) {
Highgui.imwrite("/path/to/30.png", save);
}
i++;
}
、10.pngと30.pngは異なるイメージになります:イテレータを使用して、次のコードを考えてみてください。しかし、それは明らかに意図されたものではありません。
あなたはメモリが不足していますか?そうでなければ、これはリークではありません - GCは必要なときに実行されます。 –
はい、そうです。数秒で幾らかのギガバイトがいっぱいです。 – Matthias