OpenCv2.4の使用
画像を読み込むには2つのオプションがあります。
1- CvMat and Imread
2- IpImage and CvLoadImage
どちらを使用するのが良いですか?2つを混合してみたところ、セグメンテーション違反が発生しました。
OpenCv2.4の使用
画像を読み込むには2つのオプションがあります。
1- CvMat and Imread
2- IpImage and CvLoadImage
どちらを使用するのが良いですか?2つを混合してみたところ、セグメンテーション違反が発生しました。
imread
Mat
ではなく を返しますCvMat
。それらは 2 つの異なるインターフェースです ( C++ の場合はMat
/ 、C インターフェースの場合はimread
Ipl... および Cv.. )。
C++ インターフェースは、より良く、より安全で、使いやすくなっています。メモリを自動的に処理し、同じタスクのコードを少なくすることができます。OpenCV 関係者は、非常に特定のプロジェクト要件によって C が強制されない限り、C++ の使用を推奨しています。
例 (C++)
cv::Mat image = imread("path/to/myimage.jpg")
if(image.empty())
return;
cv::imshow("Image", image);
cv::Mat bw = image > 128; // threshold image
cv::Mat crop = image(cv::Rect(0, 0, 100, 100)); // a 100px x 100px crop
crop= 0; // set image to 0
cv::waitKey();
// end code here
特に明記しない限り、すべての行列割り当ては同じデータを参照することに注意してください。上記の例では、crop
行列は を指してimage
おり、それをゼロに設定すると、 の特定の部分が 0 に設定されimage
ます。
データの新しいコピーを作成するには、Mat::copyTo または Mat::clone(); を使用します。
そしてCインターフェース
IplImage* pImg = CvLoadImage("path/to/myimage.jpg");
if(pImg == NULL)
return;
// ... big bloat to do the same operations with IplImage
CvShowImage("Image", pImg);
cvWaitKey();
CvReleaseImage(&pImg); // Do not forget to release memory.
// end code here
IplImage と Mat はどちらも相互変換可能です。
Mat からデータを取得するのは非常に簡単なので、Mat と imread() を使用することをお勧めします。
Mat::data は、1D と値に簡単にアクセスできる実際の行列データへのポインターを返します。http://opencv.itseez.com/modules/core/doc/old_basic_structures.html?highlight=mat#union%20data
さまざまな追跡アルゴリズム (OpenTLD など) のために OpenCV に機械学習の概念を追加する場合は、Mat.data を使用してデータに簡単にアクセスし、実際の行列へのポインターを取得できます。
OpenCV のユーティリティ (CalcOpticalFlowPyrLK など) の多くは、Mat を必要とします。マットを使用することをお勧めします。IplImage は今では古いものです。
OpenCV_2 クックブックから:
この構造は、IPL ライブラリー (Intel Image Processing Library) から継承され、現在は IPP ライブラリー (Intel Integrated Performance Primitive ライブラリー) に統合されています。古い C インターフェイスで作成されたコードとライブラリを使用する場合、それらの IplImage 構造を操作する必要がある場合があります。幸いなことに、IplImage を cv::Mat オブジェクトに変換する便利な方法があります。
IplImage* iplImage = cvLoadImage("c:\img.jpg"); cv::Mat image4(iplImage,false);
関数 cvLoadImage は、イメージをロードするための C インターフェイス関数です。cv::Mat オブジェクトのコンストラクターの 2 番目のパラメーターは、データがコピーされないことを示します (新しいコピーが必要な場合は true に設定しますが、false はデフォルト値であるため、省略されている可能性があります)。 IplImage と image4 は同じ画像データを共有します。ここでは、ダングリング ポインターを作成しないように注意する必要があります。このため、IplImage ポインターを OpenCV 2 によって提供される参照カウント ポインター クラスにカプセル化する方が安全です。
cv::Ptr iplImage = cvLoadImage("c:\img.jpg");
それ以外の場合、IplImage 構造体が指すメモリの割り当てを解除する必要がある場合は、明示的に行う必要があります: cvReleaseImage(&iplImage); この非推奨のデータ構造は使用しないでください。代わりに、常に cv::Mat を使用してください。
これは、ポインターにどれだけ慣れているかによって異なります。IplImage では、次のようにデータにアクセスできます。
data[i*widthstep+j*nchannels +k]
ここで、i、j、k はいくつかの整数であり、これは非常に簡単なアプローチです。3次元の通常の行列では、データにアクセスするのはそれほど簡単ではありません. 通常の行列データの場合、アクセスは a[i][j] です
*(*(a + i) + j) is the value of jth element of ith row in matrix a