opencvでのMat、CvMat、IplImageの紹介と3つの間の変換

OpenCVの画像操作に関連する一般的なデータコンテナは、Mat、cvMat、およびIplImageです。これらの3つのタイプは、画像を表現および表示できます。違いは、マットタイプは計算に重点を置き、数学はより高度です。OpenCVはマットタイプの計算を最適化し、CvMatおよびIplImageタイプは「画像」に重点を置き、opencv 「画像」に焦点を当てています。画像操作(ズーム、シングルチャネル抽出、画像しきい値操作など)が最適化されています。opencv2.0より前は、opencvはCで完全に実装されていましたが、IplImageタイプとCvMatタイプの関係は、オブジェクト指向の継承関係に似ています。実際、CvMat-CvArrの上に、より抽象的な基本クラスがあります。これは、ソースコードで一般的です。

1. opencvドキュメントには、CvMatが廃止された(CvMatは廃止されたため、代わりにMatの使用を検討する)ことは推奨されないことが明確に記載されています
。2。派生関係:CvArr-> CvMat-> IplImage 3.Matの一連の事項
はCvArrおよびそのサブクラスcvLoadImage()、cvShowImage()とは異なるimread、imshowなど。

1.マットタイプ:マトリックスタイプ、マトリックス。
openCVでは、Matは多次元の密なデータ配列です。ベクトルや行列、画像、ヒストグラムなどの一般的な多次元データを処理するために使用できます。
Matには3つの重要なメソッドがあります:
1。Matmat = imread(const String * filename);画像の読み取り
2. imshow(const string frameName、InputArray mat);画像の表示
3. imwrite(const string&filename、InputArray img);
との比較CvMatおよびIplImageタイプ、画像格納するためのMatタイプは、より強力なマトリックス操作機能を備えており、一般的なマトリックス操作をサポートします。計算量の多いアプリケーションでは、CvMatタイプとIplImageタイプをMatタイプに変換すると、計算時間が大幅に短縮されます。
2、CvMatタイプ:画像タイプ

typedef struct CvMat
{
    int type;
    int step;
    /* for internal use only */
    int* refcount;
    int hdr_refcount;
    union
    {
        uchar* ptr;
        short* s;
        int* i;
        float* fl;
        double* db;
    } data;
#ifdef __cplusplus
    union
    {
        int rows;
        int height;
    };
    union
    {
        int cols;
        int width;
    };
#else
    int rows;
    int cols;
#endif
}
CvMat;


openCVには、ベクターデータ構造はありません。いつでも、ただしベクトルを表現したい場合は、行列データを使用してそれを表現できます。ただし、CvMat型は、線形代数のコースで学習したベクトルの概念よりも抽象的です。たとえば、CvMatの要素データ型は、基本データ型に限定されません。たとえば、次のようにすると、2次元データ行列が作成されます。 :CvMat * cvCreatMat(int rows、int cols、int type);
typeは、RGBやその他のマルチチャネルデータなど、事前定義された任意のデータ型にすることができます。このようにして、カラフルな画像をCvMatマトリックスで表すことができます。
3. IplImage:画像タイプ。
タイプの関係から、IplImageタイプはCvMatタイプを継承していると言えます。もちろん、画像データに解析するための他の変数も含まれています。これは次のように定義されます。


typedef struct _IplImage  
    {  
        int nSize; / * IplImage size * /  
        int ID; / * Version(= 0)* /  
        int nChannels; / *ほとんどのOPENCV関数は、1、2、3、または4チャネルをサポートします* /  
        int alphaChannel; / *無視されますOpenCVのにより* /  
        int型の深さ; / *画素が奥行きビット:IPL_DEPTH_8U、IPL_DEPTH_8S、IPL_DEPTH_16U、 
                               IPL_DEPTH_16S、IPL_DEPTH_32S、IPL_DEPTH_32FとIPL_DEPTH_64Fによってサポートされている  
        チャーチャネル* / * /  
        チャー]; / *上記のように/ *同じ  
        INT dataOrder; / * 0-インターリーブされたカラーチャネル、1-分離されたカラーチャネル 
                               。cvCreateImageはインターリーブされた画像のみを作成できます* /  
        int origin; / * 0-左上の構造体、 
                               1-左下構造(Windowsのビットマップ形式)* /  
        INT ALIGN; / *画像線配置(4または8)OpenCVのは、それを無視し、代わりに* /のwidthStep使用  
        INT幅を、ピクセル単位/ *画像幅* /  
        int型の高さ; / *画像の高ピクセル数* /  
        struct _IplROI * roi; / *画像の対象領域。値が空でない場合、領域のみが処理されます* /  
        struct _IplImage * maskROI; / * OpenCVではNULLを設定する必要があります* /  
        void * imageId; / *上記と同じ* /  
        struct _IplTileInfo * tileInfo; / *上記と同じ* /  
        int imageSize; / *画像データサイズ(インターリーブ形式imageSize = image-> height * image-> widthStep)、unit byte * /  
        char * imageData; / *配置する画像データを
        指す* /   int widthStep; / *配置する画像行のサイズ(バイト単位)* /  
        int BorderMode [4] ; / *ボーダーエンドモード、OpenCVでは無視されます* /  
        int BorderConst [4]; / *上記と同じ* /  
        char * imageDataOrigin; / *ポインタは、画像メモリ割り当てを修正するために準備された別の画像データ構造(必ずしも配置されている必要はありません)を     指します* /  
    }  
IplImage;  
2つdataOrder値:インターリーブされたカラーチャネルは、カラーデータの配置がBGRBGRの千鳥配置になります。複数のカラーチャネルがある場合、個別のカラーチャネルは複数のカラープレーンに保存されます。roiはIplROI構造体であり、xOffset、yOffset、height、width、coiメンバー変数が含まれます。ここで、xOffset、yOffsetはx、y座標であり、coiは対象のチャネル(対象のチャネル)を表します。 0は有効ではありません。画像内のデータ要素へのアクセスは、間接ストレージと直接ストレージに分けられます。画像要素が浮動小数点型の場合、(uchar *)は(float *)に変更されます。 
補足:IplImageはCvMatから派生し、CvMatはCvArrから派生、つまり、CvArr-> CvMat-> IplImage

            CvArrは関数のパラメーターとして使用され、どのCvMatまたはIplImageが渡されても、CvMatによって内部的に処理されます。

CvMatとIplImageを作成するときの小さな違い:

1.行列を作成する場合、最初のパラメーターは行数で、2番目のパラメーターは列数です。

CvMat * cvCreateMat(int rows、int cols、int type);

2.画像​​を作成する場合、CvSizeの最初のパラメーターは幅(列数)、2番目のパラメーターは高さ(行数)です。これは、CvMatマトリックスの反対です。

IplImage * cvCreateImage(CvSizeサイズ、int深度、intチャネル);

CvSize cvSize(int width、int height);

さらに、IplImageの内部バッファの各行は4バイトで整列され、CvMatにはこの制限がありません。

4、相互変換
4.1IplImage->マット

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    IplImage* srcImg = cvLoadImage("F:\\IM_VIDEO\\kobe.jpg");
    Mat m = cvarrToMat(srcImg, true);
    namedWindow("kobe image", CV_WINDOW_AUTOSIZE);
    imshow("kobe image", m);
    waitKey(0);
    return 0;
}


演算結果:

4.2マット-> IplImage:

 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    Mat m = imread("F:\\IM_VIDEO\\kobe.jpg");
    IplImage* transIplimage = cvCloneImage(&(IplImage)m);
    cvShowImage("kobe image", transIplimage);
    waitKey(0);
    cvReleaseImage(&transIplimage);
    return 0;
}


実行結果は上記と同じです。
5.ピクセル取得方法
5.1マット法のピクセル取得方法は次の場所にあります:http://blog.csdn.net/piaoxuezhong/article/details/54236227

5.2IplImageメソッドのピクセル取得

直接アクセス:
私たちにとってさらに重要な2つの要素は、char * imageDataとwidthStepです。imageDataは画像のピクセルデータを格納します。widStepはCvMatのstepに似ており、行データの長さをバイト単位で表します。
m * nシングルチャネルバイトイメージ、そのimageDataは次のように配置されます。


#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1);
    uchar* tmp = new uchar[img->width*img->height*img->nChannels];
    for (int i = 0; i < img->height; i++)
    {
        for (int j = 0; j < img->width; j++)
        {
            *tmp = ((uchar *)(img->imageData + i*img->widthStep))[j];
        }
    }
    cout << "第1行第1列的图像灰度值: " << (float)tmp[0]<< endl;
    cvShowImage("kobe image", img);
    waitKey(0);
    cvReleaseImage(&img);
    return 0;
}


ポインタ取得方法:


#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1);
    //uchar* tmp = new uchar[img->width*img->height*img->nChannels];
    uchar* data = (uchar *)img->imageData;
    int step = img->widthStep / sizeof(uchar);
    uchar* tmp = data;
    for (int i = 0; i < img->height; i++)
    {
        for (int j = 0; j < img->width; j++)
        {
            *tmp = data[i*step + j];
        }
    }
    cout << "第1行第1列的图像灰度值: " << (float)tmp[0] << endl;
    cvShowImage("kobe image", img);
    waitKey(0);
    cvReleaseImage(&img);
    return 0;
}


 

おすすめ

転載: blog.csdn.net/yangdashi888/article/details/104522460