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

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

OpenCV cvLoadImageについて

OpenCVで画像判定プログラムを作成しています。 大まかなプログラムは出来、現在細かなデバックを行っています。 現在、問題として、メモリーリークが発生しているみたいです。 ファイルを読み込む時、 IplImage *sourceImage; sourceImage=cvLoadImage("image/lena.jpg",CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR ); cvReleaseImage( &sourceImage ); としますが、これは読み込んだバッファー等の情報がsourceImageに書き込まれ、最後にcvReleaseImage( &sourceImage );を実行する事により、バッファー等のファイルを読み込む為に確保されだ領域が削除されると理解しています。 今までの私のC言語でのプログラミングの経験では、先ずバッファーを確保し、そこにファイルを読み込むと言う事を行って来ましたので、ファイルの次のレコードを読み込む場合はそのバッファーに上書きされて読む事ができました。 OpenCVでは上記sourceImageにバッファー等の情報が渡されますが、次のレコードを読む時はどう成るのでしょうか? 又、新たなバッファー領域が確保されてその情報が渡されるのでしょうか。そうすると、cvReleaseImageでは先に読み込んだバッファーの開放が出来なく成ると思います。それとも、読み込みは同じバッファー領域にされるのでしょうか。 ただ、そうすると、2回目の読み込みは上記、sourceImageで無く、別のIplImageで作成したポインターを指定した時、両方cvReleaseImageで開放してしまうと、同じ領域を2回開放してしまう事に成ってしまいます。 今、自宅なので参照出来ませんが、何か、リセットイメージみたいなコマンドがありました。ひょっとして、次のレコードを読み込む時は毎回このリセットイメージの様なコマンドをcvLoadImageとペアで使用して、最後にcvReleaseImageで開放するのでしょうか。 質問を書いている時に、更に疑問が出て来ました。もし、リセットイメージコマンドがあるとして、これを掛けた後、データーを読み込みもせず、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 ); とコーディングする様に書かれていた記憶があります。 ただし"ファイル名"はその都度変わるものとします。

関連するQ&A

  • OpenCV2.0でView Morphing

    環境はVisual Studio 2008 Express, OpenCV2.0です。 サポートされない実験的な関数にあるビューモーフィング関数を使い、2枚の画像から中間の画像を生成し、ウインドウに表示させるプログラムを作りたいです。 このpdfファイル(http://www.hci.otago.ac.nz/downloads/ViewMorphing_full.pdf)内の「10. Appendix B - Image Morphing in OpenCV」という箇所にあるコードを、以下のような定型文で囲んでみたんですけど、コンパイル時に分からないエラーが沢山出てきて解決できずに困っています。 どこか根本的な部分が抜けていて間違っているような気がするので、あらかじめ必要な宣言が抜けているとか、間違っていることに気づいた方がいらっしゃれば何でもいいので教えてください。よろしくお願いします。 #include <cv.h> #include <highgui.h> #include <cvaux.h> #pragma comment(lib, "cv200.lib") #pragma comment(lib, "highgui200.lib") #pragma comment(lib, "cvaux200.lib") int main(int argc, char** argv[]) { IplImage* morphedImage; IplImage* leftImage; IplImage* rightImage; cvNamedWindow("出力画像"); leftImage = cvLoadImage("left.jpg"); rightImage = cvLoadImage("right.jpg"); //------------------------------------------- ここに処理を入れる //------------------------------------------- // 表示ウインドウに画像を表示 cvShowImage("出力画像", _morphedImage); // キー入力待機 cvWaitKey(0); //表示ウインドウの破棄 cvDestroyWindow("出力画像"); cvReleaseImage(&leftImage); cvReleaseImage(&rightImage); cvReleaseImage(&morphedImage); //画像領域の解放 return 0; }

  • OpenCVでの画像読み込みについて

    OpenCVのファイルの読み込み部分がわからなくて困っています。 IplImage *src_img, *dst_img; if (argc < 2 || (src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR)) == 0) return -1; ここの処理は一体何を行っているのでしょうか? どのように動いているのか教えていただけないでしょうか? 一応調べた際、cvloadImage(ファイル名、状態)のようなことが書いてあったのでargv[1]を"test.jpg"に変更しても動きませんでした。

  • OPENCVの画像処理について

    現在OPENCVを使って画像処理の勉強をしているのですが画像を読み込む際 IplImage* cvLoadImage という関数?を使って画像を読み込んでいるのですが 例えばファイルAに10枚画像が入っていたとしてその10枚をIplImage* cvLoadImageで一枚ずつ読み込むのではなくまとめて読みこむ(配列のように読みこんだ画像の順から[1]などの番号が付くような)という関数はないのでしょうか? 画像を変えるたびに「名前.jpg」を変えないといけない手間を省きたいです。

  • OpenCVで画像を読み込みたい

    OpenCVを勉強しようと思い先日始めました。 http://chihara.naist.jp/opencv/?FrontPage 上記のサイトに掲載されている通りにVC++ 2008 EEで ・環境変数PATH ・インクルードファイル ・ライブラリファイル ・リンカ の設定をしました。 これでいざプログラムをコンパイルして実行すると何故か画像が読み込んでくれません。 これらの設定以外の他にするべきことがあるのでしょうか? いきなり出鼻を挫かれたので困っています。よろしくお願いします。 OS:XP SP2 開発環境:VC++ 2008 EE 実行したプログラム ---------------------------------------------------------------- #include "cv.h" #include "highgui.h" int main( int argc, char** argv ) { IplImage* img; char* filename = "abc.bmp"; if( argc == 2 && (img = cvLoadImage( filename, 1)) != 0 ) { cvNamedWindow( "Image view", 1 ); cvShowImage( "Image view", img ); cvWaitKey(0); // イベント処理を含む場合には,これが重要. cvDestroyWindow( "Image view" ); cvReleaseImage( &img ); return 0; } return -1; } ----------------------------------------------------------------

  • Opencvで質問

     Opencv初心者です。  今日opencvとVC++2010を設定して今練習中なのですが   #include <stdexcept>   #include <opencv/cv.h>   #include <opencv/highgui.h>   int main (int argc, char* argv[]){   const char *fileName = "C:\\Program Files\\OpenCV2.3.1\\samples\\c\\lena.jpg";   const char *windowName = "lena";   ::IplImage* img = ::cvLoadImage(fileName);   ::cvNamedWindow(windowName);   ::cvShowImage(windowName,img);   ::cvWaitKey();   ::cvDestroyWindow(windowName);   ::cvReleaseImage(&img);   }  と言うサンプルをビルドしたら  1>------ ビルド開始: プロジェクト: 画像処理練習, 構成: Debug Win32 ------  1>LINK : fatal error LNK1104: ファイル 'opencv_core231.lib' を開くことができません。  ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========  エラーが出てしまい先に進めません。  もしかしたら他に設定が悪いのでしょうか?  インストールもC:\Program Files\OpenCV2.3.1に名前も変えインストールしました。  ttp://shiotani.cn/20110904vc2010opencv.html  ここを参考にさせていただきました。 よろしくお願いします。

  • C++でOpenCV コンパイルでエラー

    超初心者です。 Visual C++2010 ExpressでOpenCVを使おうとしています。 このページを参考にしています。 http://gihyo.jp/dev/feature/01/opencv/0002?page=2 プログラムは以下の通り。 #include <C:\Program Files (x86)\opencv\build\include\opencv\cv.h> #include <C:\Program Files (x86)\opencv\build\include\opencv\highgui.h> int main(int argc, char* argv[]) { IplImage* img; // 画像ファイルポインタの宣言 char imgfile[] = "lena.jpg"; // 読み込み画像ファイル名 // 画像の読み込み img = cvLoadImage(imgfile, CV_LOAD_IMAGE_COLOR); // 画像の表示 cvNamedWindow ("lena", CV_WINDOW_AUTOSIZE); cvShowImage ("lena", img); cvWaitKey (0); cvDestroyWindow("lena"); // 画像の解放 cvReleaseImage(&img); return 0; } コンパイルすると、以下のエラーメッセージが出ます。 1>------ ビルド開始: プロジェクト: try, 構成: Debug Win32 ------ 1> try.cpp 1>c:\program files (x86)\opencv\build\include\opencv\cv.h(63): fatal error C1083: include ファイルを開けません。'opencv2/core/core_c.h': No such file or directory ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== どのようにすれば通るのでしょうか? 教えてください。よろしくお願いします。

  • OpenCVでのビット数のカウント

    はじめまして。今回皆様のお力をお借りしたく質問させて頂きました。 どうぞ宜しくお願いします。 私は今OpenCV1.1を使って、2枚のエッジ処理して2値化された画像の差分を取り、変化しているビット数をカウントして表示させるというプログラムを作っています。 しかし、デバッグするとエラーが出てしまい、失敗してしまいます。 どこに問題があるのでしょうか? プログラム初心者のため、初歩的なミスをしているのかもしれません。 開発環境はMicrosoft Visual C++ 2010です。 以下にプログラムを載せておきます。 #include "stdafx.h" #include <cv.h> #include <highgui.h> #pragma comment(lib,"cv.lib") #pragma comment(lib,"cxcore.lib") #pragma comment(lib,"highgui.lib") /* 背景画像のファイル名 */ #define INPUT_FILE1 "5×5medcanny.bmp" /* 対象画像のファイル名 */ #define INPUT_FILE2 "Fire5×5medcanny.bmp" /* 差分画像のファイル名 */ #define OUTPUT_DIFF_FILE "diff.bmp" #define WIDTH 352 #define HEIGHT 288 int _tmain(int argc, _TCHAR* argv[]) { // 画像変数宣言 IplImage *img_in1, *img_in2, *img_diff; cvNamedWindow("期待値画像"); // 表示ウィンドウの作成 cvNamedWindow("比較画像"); cvNamedWindow ("差分画像", CV_WINDOW_AUTOSIZE); img_in1 = cvLoadImage(INPUT_FILE1); // 画像ファイルの読み込み img_in2 = cvLoadImage(INPUT_FILE2); if(img_in1 == NULL || img_in2 == NULL) // ファイルが読み込めない場合 { printf("ファイルが読み込めません。\n"); cvWaitKey(0); // キー入力待機 return -1; } // 画像領域の確保 img_diff = cvCreateImage(cvSize(img_in1->width, img_in1->height), IPL_DEPTH_8U, 1); // 期待値画像と比較画像の差分 cvAbsDiff(INPUT_FILE1, INPUT_FILE2, OUTPUT_DIFF_FILE); // 差分画像ファイルの読み込み img_diff = cvLoadImage(OUTPUT_DIFF_FILE); // 差分画像の画素数の取得 IplImage img_hdr; IplImage *dst_img = cvGetImage (img_diff, &img_hdr); // 差分画像の画素数のカウント int count = 0; count += cvCountNonZero(dst_img); printf("%d\n",count);     cvShowImage("期待値画像", img_in1); // 表示ウィンドウに画像を表示 cvShowImage("比較画像", img_in2); cvShowImage("差分画像", img_diff); cvSaveImage("Image_diff.bmp", img_diff); // 出力画像の保存 cvWaitKey(0); // キー入力待機 cvDestroyAllWindows(); // すべての表示ウィンドウの破棄 cvReleaseImage(&img_in1); // 画像領域の解放 cvReleaseImage(&img_in2); cvReleaseImage(&img_diff); cvReleaseImage(&dst_img); return 0; }

  • 【OpenCV】BGRからHSVへの画像変換

    OpenCVを使って任意の画像データをBGR表色系からHSV表色系に変換するプログラムです。 コンパイルして実行してみたところ、添付画像のように元画像とは色味が異なった画像が出力されてしまいます。 他の画像ファイルを使ってみましたが結果は同じでした。 HSVへの変換がうまくいってないのでしょうが、調べても原因は分かりませんでした。 どなたか分かる方がいらっしゃいましたらご指摘お願いします。 以下にコードを載せます。 #include <cv.h> #include <highgui.h> int main (int argc, char **argv){ IplImage *src_img=0; // 入力画像 IplImage *hsv_img=0; // hsvに変換された画像 // (1)画像を読み込む src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); // (2)読み込んだ画像をhsvに変換する hsv_img = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 3); cvCvtColor (src_img, hsv_img, CV_BGR2HSV); // (3)画像を表示,キーが押されたときに終了 cvNamedWindow ("Source_Image", CV_WINDOW_AUTOSIZE); cvNamedWindow ("HSV_Image", CV_WINDOW_AUTOSIZE); cvShowImage ("Source_Image", src_img); cvShowImage ("HSV_Image", hsv_img); cvWaitKey (0); // (4)メモリ解放 cvDestroyWindow ("Source_Image"); cvDestroyWindow ("HSV_Image"); cvReleaseImage (&src_img); cvReleaseImage (&hsv_img); return 0; } OS:Windows7 OpenCVのバージョン:2.1 添付画像で用いた画像の形式:png

  • OpenCVでの画像サイズ取得について教えてください。

    OpenCVでの画像サイズ取得について教えてください。 rawデータをjpgにして取得し、その画像を4分割したいのですがエラーが3つ出てしまいます。 環境はVisual Studio2008です。 いろいろと調べたのですが、原因や対策がはっきりわからず、書き変えてもNGで困っています。 エラー:その1 「error LNK2028:未解決のトークン(0A00007B)"extern "C" struct IplImage *_cdecl cvLoadImage(char const roi.obj*.int)"(cvLoadImage@@$$J0YAPAU IplImage@@PBDH@Z)が関数"int _codecl main(int,char * *)"(?main@@$$HYAHHPAPAD@Z)で参照されました。」 エラー:その2 「error LNK2019: 未解決の外部シンボル"extern "C" struct IplImage * codecl cvLoadImage(char const *.int)" (?cvLoadImage@@$$J0YAPAU IplImage@@PBDH@Z)が関数"int_codecl main(int, char * *)" (?main@@$$HYAHHPAPAD@Z)で参照されました。」 エラー:その3 「fatal error LNK1120: 外部参照2が未解決です] '================== #pragma warning(disable : 4819) #include <cv.h> #include <highgui.h> #include <stdio.h> #define DIVX (4) #define DIVY (4) #define DIVXY (DIVX*DIVY) int main (int argc, char **argv) { int w, h IplImage *img=0; img=cvLoadImage("C:\・・・\\testfile.jpg, CV_LOAD_IMAGE_GRAYSCALE); w = img->width - img->width % DIVX + DIVX; h = img->height - img->height % DIVY + DIVY; printf("幅は%w, 高さは%h です。 \n"); } '=============================================== 画像サイズを取得し、画像を4分割したあと、画素値を変更したいと思っています。 できればjpgに変換せず、rawデータそのものの精度の画像を直接扱いたいのですが、 その場合、cvLoadImageでどう表記すると実現できるのでしょうか。 また、OpenCVのグレースケールは、何チャンネルなのでしょうか。 プログラム経験はありますが、OpenCVを使うため、C言語の勉強も始めたばかりです。 なにか見当違いな質問をしていたら申し訳ありません。 お忙しいところすみませんが、もしどなたか解決策をアドバイスいただける方がいらっしゃると 大変助かります。 どうぞ宜しくお願い致します。

  • OpenCVの実行エラー

    OpenCVで下記の用なテストプログラムを作成しました。 --------------------------------------- #include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #pragma comment(lib, "cv.lib") #pragma comment(lib, "cxcore.lib") #pragma comment(lib, "highgui.lib") int main(void) { unsigned char *Image; IplImage* img = NULL; IplImage* clone = NULL; // 画像読み込み img = cvLoadImage("image.bmp", -1); // 画像コピー clone = cvCloneImage(img); return 0; } --------------------------------------- ところが、実行すると --------------------------------------- Bad argument(Bad image header) in function cvCloneImage, D:\User\VP\openCV\cxcore\src\cxarray.cpp --------------------------------------- というエラーメッセージがでて実行することができませんでした。 OpenCVに付属していたsampleプログラムは動作しました。 // 画像コピー clone = cvCloneImage(img); の一文をコメントアウトするとエラーはなぜかでません。 このエラーはどうしてでるのでしょうか? OSはwindowsXP コンパイルはC++6.0とVS2005の両方で試しましたが同じ結果がでます。

専門家に質問してみよう