OpenCV 2.0 – cv::Ptr

A template class for smart reference-counting pointers

OpenCV 2.0では cv::Ptr という参照カウント方式のスマートポインタが用意されています。
これは Boost C++ Library の shared_ptr と同様のもので大変便利です。
参考:参照カウント – Wikipedia

一時的にcv::Ptrクラスのrefcountというメンバをprotectedからpublicに変更して挙動を見てみます。
(cxcore.hppの660行目付近にあります)

class Test {
public:
  Test() { std::cout<<"construct"<<std::endl; }
  ~Test() { std::cout<<"destruct"<<std::endl; }
};

int main(void) {
  using namespace std;
  cv::Ptr<Test> p1(new Test());  // 参照カウント 1
  cout<<"refcount: "<<*(p1.refcount)<<endl;
  {
    cv::Ptr<Test> p2;
    p2 = p1;  // 参照カウントが+1されて2になる
    cout<<"refcount: "<<*(p1.refcount)<<endl;
  }  // 参照カウントが-1されて1になる、まだオブジェクトは解放されない
  cout<<"refcount: "<<*(p1.refcount)<<endl;
  cout<<"main exit"<<endl;
  return 0;
}  // Testオブジェクトが解放される

--------------
/** 結果
 construct
 refcount: 1
 refcount: 2
 refcount: 1
 main exit
 destruct
**/

すばらしい。
また、IplImage に適用した場合はきちんとテンプレートの特殊化が施されているので安心です。

int main(void) {
  cv::Ptr<IplImage> img = cvLoadImage("test.jpg");

  if(img.empty()) {
    std::cerr<<"can't load image."<<std::endl;
    return -1;
  }

  namedWindow("image", CV_WINDOW_AUTOSIZE);
  imshow("image", Mat(img));
  waitKey();

  return 0;
}

--------------------------------------------------------------------
/* 参照カウント(refcount)が0になると Ptr::delete_obj() が呼ばれる
 CvMatやIplImageは以下のように特殊化されている */
template<> inline void Ptr<CvMat>::delete_obj()
{ cvReleaseMat(&obj); }   

template<> inline void Ptr<IplImage>::delete_obj()
{ cvReleaseImage(&obj); }

OpenCV 1.0ではメモリのアロケートに cvAlloc() という malloc() のラッパーが使われていましたが、
OpenCV 2.0ではその代わりに fastMalloc() という関数が用意され、cv::Ptr内でもコールされています。
少し中を覗いてみると、どうやらシステムコールの mmap() でアロケートしているようです。
(Windowsでは普通のmalloc()が呼ばれる模様)
詳しくはまだ読めていませんが、fastというくらいだからきっと速くなっているんでしょう。

メモリ管理を cv::Ptr に任せておくと開発が楽になるのは間違いなさそうです。

関連記事:
OpenCV 2.0を試してみた

 

Tags: ,

Comments

No comments so far.

  • Leave a Reply
     
    Your gravatar
    Your Name