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;
}