C++によるIplImageの扱いについて

以前、CによるIplImageの扱いをメモしたので、C++もやってみます。

単なる自分の理解のためですが・・。

まずは、C++による画像ファイルの読み込み。

using namespace cv;

//以下のコードで,API の混合利用の有効と無効を切り替えます。
//
#define DEMO_MIXED_API_USE 1

int main( int argc, char** argv )
{
    const char* imagename = argc > 1 ? argv[1] : "C:/OpenCV2.2/img/lena.jpg";
#if DEMO_MIXED_API_USE
    // Ptr は,参照カウントを行う安全なポインタクラス。
    Ptr iplimg = cvLoadImage(imagename);

    // cv::Mat は CvMat と IplImage を置き換えますが,
    // 新旧のデータ構造間の変換は簡単です.
    // (デフォルトでは,ヘッダのみが変換されデータは共有されます)
    Mat img(iplimg);
#else
    // cvLoadImage に代わる新しい関数は MATLAB 形式の名前です。
    Mat img = imread(imagename);
#endif

    if( !img.data ) // 画像が適切に読み込まれたかどうかをチェックします.
        return -1;

    Mat img_yuv;
    // 画像を,YUV色空間に変換します.
    // 出力画像のメモリは,自動的に確保されます.
    cvtColor(img, img_yuv, CV_BGR2YCrCb);

    // 画像を色平面毎に分割します.
    vector planes;
    split(img_yuv, planes);

    // 別の Mat コンストラクタ.指定されたサイズ,型の行列を確保します.
    Mat noise(img.size(), CV_8U);

    // 行列を正規分布する乱数値で埋めます.
    // 一様分布の乱数を使う場合は, randu().
    // CvScalar は Scalar に,cvScalarAll() は Scalar::all() に置き換わります.
    randn(noise, Scalar::all(128), Scalar::all(20));

    // ノイズを少し平滑化します.カーネルサイズは 3x3 ,シグマは共に 0.5 に設定.
    GaussianBlur(noise, noise, Size(3, 3), 0.5, 0.5);

    const double brightness_gain = 0;
    const double contrast_gain = 1.7;
#if DEMO_MIXED_API_USE
    // IplImage または CvMat に対してのみ動作する関数でも,
    // そこに新しい形式の行列を渡すのは簡単です.
    // ステップ1) - ヘッダを変換,データはコピーされません
    IplImage cv_planes_0 = planes[0], cv_noise = noise;
    // ステップ2) - 関数の呼び出し.ポインタを渡すので,単項演算子 "&" を忘れないように.
    cvAddWeighted(&cv_planes_0, contrast_gain, &cv_noise, 1,
                 -128 + brightness_gain, &cv_planes_0);
#else
    addWeighted(planes[0], constrast_gain, noise, 1,
                -128 + brightness_gain, planes[0]);
#endif
    const double color_scale = 0.5;
    // cvConvertScale は, Mat::convertTo() に置き換わります.
    // 出力行列の型(ここではそのまま,つまり planes[1].type() を渡します)
    // を明示的に指定する必要があります.
    planes[1].convertTo(planes[1], planes[1].type(),
                        color_scale, 128*(1-color_scale));

    // コンパイル時にデータ型が分かっている場合(ここでは, "uchar" )に
    // 利用できる, convertTo の別の形式です.
    // この表記法は,テンポラリな配列を作成せず,上述の表記法とほぼ同じ速度です.
    planes[2] = Mat_(planes[2]*color_scale + 128*(1-color_scale));

    // cvMul() は, Mat::mul に置き換わります.このシンプルな表記法でも,
    // テンポラリな配列は作成されません.
    planes[0] = planes[0].mul(planes[0], 1./255);

    // 結果をマージして元に戻します.
    merge(planes, img_yuv);
    // そして,出力 RGB 画像を作成します.
    cvtColor(img_yuv, img, CV_YCrCb2BGR);

    // これは cvNamedWindow に相当します.
    namedWindow("image with grain", CV_WINDOW_AUTOSIZE);
#if DEMO_MIXED_API_USE
    // これは img と iplimg が本当にデータを共有していることを示します.
    // これまでの処理結果は img に格納されており,したがって iplimg 内にも存在します.
    cvShowImage("image with grain", iplimg);
#else
    imshow("image with grain", img);
#endif
    waitKey();

    return 0;
    // vector<>, Mat, Ptr<> のデストラクタにより,
    // すべてのメモリは自動的に解放されます.
}

また、読み込みだけでなく、画像のバッファを生成する方法も。

using namespace cv;

//以下のコードで,API の混合利用の有効と無効を切り替えます。
//
#define DEMO_MIXED_API_USE 1

int main( int argc, char** argv )
{
    const char* imagename = argc > 1 ? argv[1] : "C:/OpenCV2.2/img/lena.jpg";
#if DEMO_MIXED_API_USE
    // Ptr は,参照カウントを行う安全なポインタクラス。
    Ptr iplimg = cvLoadImage(imagename);

    // cv::Mat は CvMat と IplImage を置き換えますが,
    // 新旧のデータ構造間の変換は簡単です.
    // (デフォルトでは,ヘッダのみが変換されデータは共有されます)
    Mat img(iplimg);
#else
    // cvLoadImage に代わる新しい関数は MATLAB 形式の名前です。
    Mat img = imread(imagename);
#endif

    if( !img.data ) // 画像が適切に読み込まれたかどうかをチェックします.
        return -1;

    // これは cvNamedWindow に相当します.
    namedWindow("image with grain", CV_WINDOW_AUTOSIZE);
#if DEMO_MIXED_API_USE
    // これは img と iplimg が本当にデータを共有していることを示します.
    // これまでの処理結果は img に格納されており,したがって iplimg 内にも存在します.
    cvShowImage("image with grain", iplimg);
#else
    imshow("image with grain", img);
#endif
    waitKey();

    return 0;
    // vector<>, Mat, Ptr<> のデストラクタにより,
    // すべてのメモリは自動的に解放されます.
}

cvCreateImage や cvLoadImage などの IplImage 構造体を対象とする関数が確保するデータ領域は4バイト境界にアラインメントが揃えられるので、また、上記のソースと同様に、次の様にするとギャップを持つ画像領域が確保されることになります。

Ptr ipl_img = cvCreateImage(cvSize(w,h), 8, 3);
cvCvtColor(ipl_img, ipl_img, CV_BGR2HSV);
Mat img, hsv_img(ipl_img);

コラム

OpenCVの勉強に購入した本です。どちらも良著だと思います。これから学ばれる人は是非参考にしてください!

OpenCV プログラミングブック 第2版 OpenCV 1.1対応 OpenCV プログラミングブック 第2版 OpenCV 1.1対応

「OpenCV プログラミングブック」は2版あるので気を付けてください。こちらが新しい方です。この本は実例が豊富ですので、OpenCVについて理解がしやすいです。一通り例題をこなすと、OpenCVについての知識が深まります。

 

 

 

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識 詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識

分厚いですが、オライリー本の例にもれず、良著だと思います。上の本でOpenCVの面白さを知った人には、手放せない本になるはずです。

 

コメントを残す

サブコンテンツ

このページの先頭へ