ProcessingのPImageには、メモリリークの問題があるので、その回避方法を書きとめておきます。ちなみに、僕の環境ではProcessing 2.1を利用しています。
通常loadImage()
などでsetup()
内から1度呼ぶくらいであればリークすることはないと思いますが、
draw()
の中でcreateImage()
などを実行しているようなケースでは、PImageを作るたびにメモリが確保され続け、いずれExceptionしてしまいます。
僕が書いていたコードを例に、回避の仕方をまとめます。
カメラキャプチャイメージを集めて利用するケーススタディ
例えばカメラからの動画をずっと貼り付けておくのではなく、特定フレーム毎に静止画としてカメラキャプチャ画像を取得して、画像としてを利用するケースを考えます。
少し省略しますが、下記のように毎秒1フレームでキャプチャを取得してArrayListにスタックすることを考えます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import processing.video.*;
Capture cam;
ArrayList<PImage> imgs;
void setup(){
frameRate(1);
String[] cams = Capture.list();
if(cams.length == 0) {
exit();
} else {
cam = new Capture(this,cams[0]);
cam.start();
}
imgs = new ArrayList<PImage>();
}
void draw(){
if (cam.available() == true) {
cam.read();
}
PImage tmp = cam.get();
imgs.add(tmp);
}
|
この例だと、実行して放置するとExceptionしてしまいます。
これを回避する方法はGithubのIssueのスレッドにあるのですが、
g.removeCache(image)
を追記するのが有効です。
1
2
3
4
5
6
7
8
9
10
|
void draw(){
if (cam.available() == true) {
cam.read();
}
PImage tmp = cam.get();
imgs.add(tmp);
g.removeCache(tmp);
}
|
さらに、ArrayListを空にするタイミングでも、実行する必要があります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
void draw(){
if (cam.available() == true) {
cam.read();
}
if (imgs.size() > 10) {
for (int n = 0; n < imgs.size(); n++) {
g.removeCache(imgs.get(n));
}
imgs.clear();
System.gc();
println('cleared buffer size: '+ imgs.size());
}
PImage tmp = cam.get();
imgs.add(tmp);
g.removeCache(tmp);
}
|
System.gc()
も加えていますが、これだけだと回避できませんでした。
なのでArrayListに入っているPImageの参照ひとつひとつにremoveCache
をする必要があります。