• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:OpenCV cvLoadImageについて)

OpenCVで画像判定プログラムのメモリーリークを解消する方法について

このQ&Aのポイント
  • OpenCVで画像判定プログラムを作成している際に、メモリーリークが発生している問題があります。
  • 質問者のC言語の経験では、ファイルの次のレコードを読み込む場合はバッファーに上書きすることで対応してきましたが、OpenCVの場合はどうなるのかが分かりません。
  • また、リセットイメージコマンドを使用した場合、データを読み込まずにcvReleaseImageをかけなかった場合にメモリーリークが発生するのかも疑問です。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

cvLoadImageはIplIamge構造体の画像の幅や高さなどに値を代入に、imageDataのポインタにmallocしたポインタを代入し、このポインタの示すメモリに画像データを格納します。 そのため、cvLoadImageとcvReleaseImageは必ずペアで使います。 補足して頂いた >IplImage に cvLoadImage されたものを、 例えば cvResetImage 見たいなコマンドでバッファークリアーをして >再度 IplImageで作成した構造体に cvLoadImage を行える の部分が良く分からなかったのですが、”バッファークリア”や”リセットイメージ”という処理は、メモリの解放なのか?それともメモリの初期化(全ての値を0にするなど)の事でしょうか? ちなみに、特定の値で初期化するには、cvSetやcvZeroなどがあります。 いづれにしても、cvLoadImageで画像ファイルから画像データを取得しようとする以上、cvLoadImage内であらたにメモリを確保してしまうので、 for( int iCnt = 0; iCnt < 10; iCnt++ ) { iplImg = cvLoadImage( "ファイル名", パラメーター ); cvReleaseImage( &iplImg ); } のように書かないといけません。 また、OpenCVのIplImage構造体といえども、ただのC言語の構造体なので、IplImage構造体の配列にして、 IplImage* imgs[10]; for (int i = 0; i < 10; i++){ imgs[i] = cvCreateImage(cvSize(5000,5000), 8, 1); } for (int i = 0; i < 10; i++){ cvReleaseImage(&imgs[i]); } というような書き方もできます。 最後にまとめて解放できる処理があったという事ですが、ニュアンス的に似ているのは全てのウィンドウを閉じるcvDestroyAllWindowsぐらいでしょうか? また、メモリの解放が面倒というのであれば、私はあまり使っていないのですが、OpenCV2.0から登場したcv::Matを使うのも手だと思います。

TinyPine
質問者

お礼

再度のご回答有難うございます。 全ての画像を一度に開放するのでは無く、一つ一つ処理するので、一つ前の画像の開放がどうなっているか、上書きされるのか、上書きされるとしてら、前の画像の情報は何処に行ってしまうのかと思い質問しました。 結論として、cvLoadとcvReleaseImageはペアで使わなければ行けない様なので、プログラムをみて、ペアに成っていない所を探してみます。 私の部署ではOpenCVは初めてで、相談者も居なく困っておりました。 現在作成中のプログラムは私の部門ではOpenCVの解説の役割も担う事に成りますので、コメントを多く入れていますので、この辺の関数内部の動きもコメントに書き込んで置きます。 有難うございました。

その他の回答 (1)

回答No.1

C言語の経験があるのなら、cvLoadImageとcvReleaseImageはC言語のmallocとfreeとの関係と同じです。 cvLoadImageでは内部的には必ずmallocを行うので、cvLoadImageとcvReleaseIamgeを対で使わないとメモリリークしてしまいます。 もし、作業用のIplIamgeを確保したいのなら、cvCreateImageを使います。 これもやっぱり内部的にはmallocを行うので、使い終わったらcvReleaseIamgeが必要です。 メモリ確保をせずに画像ファイルを読み込める関数があるか?定かでないのですが、読み込むまで画像サイズの分からないファイルからデータを読み込むので、やっぱり、そういう関数は無いかも?しれません。

TinyPine
質問者

補足

ご回答有難うございます。 書き方が悪くて誤解を与えてしまった様ですが、メモリーを確保せずにファイルを読み込む関数は無いと思います。 IplImage に cvLoadImage されたものを、 例えば cvResetImage 見たいなコマンドでバッファークリアーをして 再度 IplImageで作成した構造体に cvLoadImage を行える様なコマンドでしたが、本日会社に行き、色々探したのですが、分かりませんでした。 本題ですが、私は複数画像取得する時に IplImage* iplImg; for( int iCnt = 0; iCnt < 10; iCnt++ ) { iplImg = cvLoadImage( "ファイル名", パラメーター ); } cvReleaseImage( &iplImg ); の様にコーディングすれば良いと思っていましたが、cvLoadImageがMalloc、cvReleaseImageがFreeに相当するとすると、 IplImage* iplImg; for( int iCnt = 0; iCnt < 10; iCnt++ ) { iplImg = cvLoadImage( "ファイル名", パラメーター ); cvReleaseImage( &iplImg ); } とコーディングしなければ成らないと言う事で良いと思います。 この理解でよろしいでしょうか。 因みに私が見たと思っているコマンドをcvXxxxとすると IplImage* iplImg; for( int iCnt = 0; iCnt < 10; iCnt++ ) { iplImg = cvLoadImage( "ファイル名", パラメーター ); cvXxxx( &iplImg ); } cvReleaseImage( &iplImg ); とコーディングする様に書かれていた記憶があります。 ただし"ファイル名"はその都度変わるものとします。