Opencv-C++ 注意事項 (2): opencv の行列演算

作成と初期化

OpenCV における行列演算は非常に重要です. この記事では行列の作成, 初期化, 基本的な行列演算をまとめ, サンプルコードを示します. 主な内容は次のとおりです.

1.1 データ型

マトリックスを確立するには、マトリックスに格納されるデータ型を指定する必要があります。画像処理で一般的に使用されるいくつかのデータ型は次のとおりです。

CV_8UC1// 8位无符号单通道
CV_8UC3// 8位无符号3通道
CV_8UC4
CV_32FC1// 32位浮点型单通道
CV_32FC3// 32位浮点型3通道
CV_32FC4
 

データ ビット深度 8 ビット、32 ビット、データ型 U: uchar、F: float 型、およびチャネル数 C1: 単一チャネル、C3: 3 チャネル、C4: 4 チャネルを含みます。

1.2 基本的な方法

画像をロードすることで Mat タイプの行列を作成できます。もちろん、手動で直接行列を作成することもできます。基本的な方法は、行列のサイズとデータ型を指定することです。

// 基本方法
	cv::Mat a(cv::Size(5,5),CV_8UC1); // 单通道
	cv::Mat b = cv::Mat(cv::Size(5,5),CV_8UC3); //3通道每个矩阵元素包含3个uchar值
	cout<<"a  = "<<endl<<a<<endl<<endl;
	cout<<"b  = "<<endl<<b<<endl<<endl;
	system("pause");`

ここに画像の説明を挿入
3 チャネル行列では、行列要素に 3 つの変数が含まれます。

1.3 初期化方法

上記の方法では行列データを初期化していないため、ランダムな値が表示されます。この状況を回避したい場合は、Mat クラスのいくつかの初期化メソッドを使用して行列を作成できます。

// 初始化方法 	
cv::Mat mz = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); 
// 全零矩阵 	
cv::Mat mo = cv::Mat::ones(cv::Size(5,5),CV_8UC1); 
 // 全1矩阵 	
 cv::Mat me = cv::Mat::eye(cv::Size(5,5),CV_32FC1);  
 // 对角线为1的对角矩阵 
 	cout<<"mz = "<<endl<<mz<<endl<<endl; 	
 	cout<<"mo = "<<endl<<mo<<endl<<endl; 	
 	cout<<"me = "<<endl<<me<<endl<<endl;

操作結果:
ここに画像の説明を挿入

行列の加算と減算

行列の加算と減算には「+」と「-」の記号を使用できます。

cv::Mat a= Mat::eye(Size(3,2), CV_32F);
cv::Mat b= Mat::ones(Size(3,2), CV_32F);
cv::Mat c= a+b;
cv::Mat d= a-b;

ここに画像の説明を挿入

行列の乗算

行列とスカラーの乗算、および行列と行列の乗算を計算するには、「*」を使用します (行列の乗算の行数と列数についての対応する規則を満たす必要があります)。

Mat m1= Mat::eye(2,3, CV_32F); //使用cv命名空间可省略cv::前缀,下同
	Mat m2= Mat::ones(3,2, CV_32F);
	cout<<"m1  = "<<endl<<m1<<endl<<endl;
	cout<<"m2  = "<<endl<<m2<<endl<<endl;
	// Scalar by matrix
	cout << "\nm1.*2 = \n" << m1*2 << endl;
	// matrix per element multiplication
	cout << "\n(m1+2).*(m1+3) = \n" << (m1+1).mul(m1+3) << endl;
	// Matrix multiplication
	cout << "\nm1*m2 = \n" << m1*m2 << endl;

ここに画像の説明を挿入

行列転置

行列の転置とは、行列の行と列の順序を逆にして (i 番目の行を i 番目の列に変換)、新しい行列を形成することです。OpenCV は、Mat クラスの t() 関数を通じて実装されます。
// 転置

Mat m1= Mat::eye(2,3, CV_32F);	
Mat m1t = m1.t();
cout<<"m1  = "<<endl<<m1<<endl<<endl;
cout<<"m1t  = "<<endl<<m1t<<endl<<endl;
system("pause");

操作結果:
ここに画像の説明を挿入

逆行列

逆行列は一部のアルゴリズムでよく使用され、OpenCV の Mat クラスの inv() メソッドによって実装されます。

// 求逆
	Mat meinv = me.inv();
	cout<<"me  = "<<endl<<me<<endl<<endl;
	cout<<"meinv = "<<endl<<meinv<<endl<<endl;
	system("pause");

ここに画像の説明を挿入
単位行列の逆行列はそれ自体です。

行列内のゼロ以外の要素の数

オブジェクトのピクセルまたは面積を計算するには、多くの場合、計算行列内のゼロ以外の要素の数が必要になります。計算行列は、countNonZero() 関数を使用して OpenCV に実装されます。
// ゼロ以外の要素の数

int nonZerosNum = countNonZero(me); // me は入力行列または画像
cout<<"me = "<<endl<<me<<endl;
cout<<"me="< 内の非ゼロ要素の数<nonZerosNum< <endl<<endl;
system("pause");

操作結果:
ここに画像の説明を挿入

行列の平均と標準偏差

OpenCV は、行列の平均値と標準偏差の計算関数を提供します。これは、meanStdDev(src, means, stddev) 関数を使用して実装できます。 パラメータ src

入力行列または画像
means – 平均、OutputArray
stddev – 標準偏差、OutputArray

 // 均值方差
	Mat mean;
	Mat stddev;
	meanStdDev(me, mean, stddev); //me为前文定义的5×5对角阵
	cout<<"mean = "<<mean<<endl;
	cout<<"stddev = "<<stddev<<endl;
	system("pause");

ここに画像の説明を挿入
src がマルチチャネル画像または多次元行列の場合、関数は異なるチャネルの平均と標準偏差をそれぞれ計算するため、戻り値の mean と stddev は対応する次元のベクトルになることに注意してください。

Mat mean3;
	Mat stddev3;
	Mat m3(cv::Size(5,5),CV_8UC3,Scalar(255,200,100));
	cout<<"m3  = "<<endl<<m3<<endl<<endl;
	meanStdDev(m3, mean3, stddev3);
	cout<<"mean3 = "<<mean3<<endl;
	cout<<"stddev3 = "<<stddev3<<endl;
	system("pause");

マルチチャネル行列演算結果:
ここに画像の説明を挿入
ここに画像の説明を挿入

マトリックスのグローバル極値と位置

求输入矩阵的全局最大最小值及其位置,可使用函数:
void minMaxLoc(InputArray src, CV_OUT double* minVal,
                           CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,
                           CV_OUT Point* maxLoc=0, InputArray mask=noArray());
                           参数:

 

src – 输入单通道矩阵(图像).
minVal – 指向最小值的指针, 如果未指定则使用NULL
maxVal – 指向最大值的指针, 如果未指定则使用NULL
minLoc – 指向最小值位置(2维情况)的指针, 如果未指定则使用NULL
maxLoc – 指向最大值位置(2维情况)的指针, 如果未指定则使用NULL
mask – 可选的蒙版,用于选择待处理子区域
 

// 求极值 最大、最小值及其位置
	Mat img = imread("Lena.jpg",0);
	imshow("original image",img);
 
	double minVal=0,maxVal=0;
	cv::Point minPt, maxPt;
	minMaxLoc(img,&minVal,&maxVal,&minPt,&maxPt);
	cout<<"min value  = "<<minVal<<endl;
	cout<<"max value  = "<<maxVal<<endl;
	cout<<"minPt = ("<<minPt.x<<","<<minPt.y<<")"<<endl;
	cout<<"maxPt = ("<<maxPt.x<<","<<maxPt.y<<")"<<endl;
	cout<<endl;
 
	cv::Rect rectMin(minPt.x-10,minPt.y-10,20,20);
	cv::Rect rectMax(maxPt.x-10,maxPt.y-10,20,20);
 
	cv::rectangle(img,rectMin,cv::Scalar(200),2);
	cv::rectangle(img,rectMax,cv::Scalar(255),2);
 
	imshow("image with min max location",img);
	cv::waitKey();

操作結果:
ここに画像の説明を挿入
ここに画像の説明を挿入

GEMM 一般行列乗算

void cvGEMM( const CvArr* src1, const CvArr* src2, double alpha,
const CvArr* src3, double beta, CvArr* dst, int tABC=0 );
#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( src1, src2, 1, src3, 1, dst, 0 )
#define cvMatMul( src1, src2, dst ) cvMatMulAdd( src1, src2, 0, dst )
src1
最初の入力配列
src2
2 番目の入力配列
src3
3 番目の入力配列 (オフセット量)、またはオフセットがない場合は NULL。
dst
出力配列
tABC
T 操作フラグ。0、または以下に示す値の組み合わせです。
CV_GEMM_A_T - src1 を転置
CV_GEMM_B_T - src2 を転置
CV_GEMM_C_T - src3 を転置
たとえば、CV_GEMM_A_T+CV_GEMM_C_T は、
alpha src1T src2 + beta*src3Tに対応します。
機能cvGEMM の実行 一般的な行列乗算:

dst = alpha*op(src1) op(src2) + beta op(src3)、op(X) は X または XT
すべての行列は同じデータ型と調整行列サイズを持つ必要があります。実数浮動小数点行列または複素浮動小数点行列をサポートします。

Transform は、配列の各要素に対して行列変換を実行します。

void cvTransform( const CvArr* src, CvArr* dst, const CvMat* transmat, const CvMat*Shiftvec=NULL );
src
入力配列
dst
出力配列
transmat
変換行列
shifvec
オプションのシフト ベクトル
関数 cvTransform は配列の各要素に対して行列を実行します src Transform および結果を dst に保存します。

dst(I)=transmat*src(I) + shiftvec
または

dst(I)k=sumj(transmat(k,j)*src(I)j) + SHIFTVEC(k)
N チャネル配列 src の各要素は、M×N を使用して N 要素ベクトルとみなされます。変換行列transmatとオフセットベクトルshiftvecは、それをMチャネル配列dstの要素に変換します。ここでは、オフセット ベクトル shiftvec をトランスマットに埋め込むことを選択できます。この場合、transmat は M×N+1 の行列である必要があり、右端の列がオフセット ベクトルと見なされます。

入力配列と出力配列は同じ深さと同じサイズまたは ROI サイズを持つ必要があります。transmat と shiftvec は実数の浮動小数点行列である必要があります。

この関数は、ND ポイント セットの幾何学的変換、任意の線形色空間変換、チャネル変換などに使用できます。

MulTransused 配列の積と配列の転置を計算します。

void cvMulTransused( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL );
src
入力行列
dst
宛先行列
order
乗算order
delta
乗算前に src から減算するオプションの配列。
関数 cvMulTransposed は、src とその転置の積を計算します。

機能評価式:

注文=0の場合

dst=(src-delta)*(src-delta)T
else

dst=(src-デルタ)T*(src-デルタ)

Trace は行列のトレースを返します

CvScalar cvTrace( const CvArr* mat );
mat
入力行列 関数
cvTrace は、行列 mat の対角要素の合計を返します。

tr(src) = ∑ mat(i,i)
i

Transpose 行列の転置

void cvTranspose( const CvArr* src, CvArr* dst );
#define cvT cvTranspose
src
入力行列
dst
ターゲット行列
関数 cvTranspose は行列 src の転置を求めます。

dst(i,j)=src(j,i)
なお、複素行列の場合は複素数の共役は求められません。活用は独立している必要があります。cvXorS サンプル コードを参照してください。

Det は行列の行列値を返します。

double cvDet( const CvArr* mat );
mat
入力行列 関数
cvDet は、正方行列 mat の行列値を返します。小さな行列の場合は直接計算し、大きな行列の場合はガウス (GAUSSIAN) 消去法を使用します。対称正定行列の場合、SVD 関数 U=V=NULL を使用し、w の対角要素の積を使用して行列式を計算することもできます。

Invert は行列の逆行列または擬似逆行列を見つけます

double cvInvert( const CvArr* src, CvArr* dst, int method=CV_LU );
#define cvInv cvInvert
src
入力行列
dst
ターゲット行列
メソッド
反転メソッド:
CV_LU - 最適なピボット選択のためのガウス消去法
CV_SVD - 特異値分解メソッド (SVD)
CV_SVD_SYM - 正定対称行列の SVD メソッド
関数 cvInvert は行列 src を反転し、結果を dst に保存します。

LU 法の場合、関数は src の行列式の値を返します (src は正方行列である必要があります)。0の場合、行列は反転されず、dstは0で埋められます。

SVD 法の場合、関数は src の条件番号の逆数 (最小特異値と最大特異値の比) を返し、src がすべて 0 の場合は 0 を返します。src が単数の場合、SVD メソッドは擬似逆行列を計算します。

Solve は線形システムまたは最小二乗問題を解決します

int cvSolve( const CvArr* src1, const CvArr* src2, CvArr* dst, int メソッド=CV_LU );

src1 入力行列
src2 線形システムの右側部分
dst 出力 解法

解法 (行列逆行列) :
CV_LU - 最適なピボット選択のためのガウス消去法
CV_SVD - 特異値分解 (SVD)
CV_SVD_SYM - 正定対称行列の SVD 法
線形システムまたは最小二乗法の関数 cvSolve (後者は SVD 法で解くことができます):

/mbox{dst} = /arg /min_X |/mbox{src1}/cdot X-/mbox{src2}|
CV_LU メソッドを使用する場合。この関数は、src1 が正数の場合は 1 を返し、それ以外の場合は 0 を返します。その場合、dst は無効です。

SVD 実浮動小数点行列の特異値分解

void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 );

AM×N 入力行列 W 結果の特異値行列 (M×N または N×N) またはベクトル (N×1) U オプションの左直交行列 (M×M または M×N) CV_SVD_U_T の場合、次の数を指定し
ます上記の行と列を交換する必要があります。V オプションの右直交行列 (N×N)

flags
操作フラグ。0 または次の値の組み合わせを指定できます:
CV_SVD_MODIFY_A 行列 src1 は操作によって変更できます。こうすることで処理速度が速くなります。
CV_SVD_U_T は転置行列 U を返すことを意味し、このフラグを指定すると処理が高速化されます。
CV_SVD_V_T は転置行列 V を返すことを意味し、このフラグを指定すると処理が高速化されます。

関数 cvSVD は、行列 A を対角行列と 2 つの直交行列の積に分解します。

/mathbf{/it A=UWV^T}

ここで、W は特異値の対角行列であり、U および V と同様に特異値の 1 次元ベクトルとしてエンコードできます。すべての特異値は負ではなく、降順で格納されます。(U と V
もそれに応じて保存されます)。

SVD アルゴリズムは数値処理において非常に安定しており、その典型的な用途には次のものがあります。

A が正方行列、対称行列、正行列である場合、たとえば A が共分散行列である場合、固有値問題を正確に解決します。この場合、W は固有値のベクトル、
U=V は行列の固有ベクトルになります (したがって、固有ベクトルを計算する必要がある場合、U と V の一方のみを計算する必要があります)。条件の悪い線形システムを正確に解決します。
過剰決定線形システムの最小二乗解。前の問題も今回の問題も、CV_SVD を指定した cvSolve メソッドを使用できます。
ランク (ゼロ以外の特異値の数)、条件番号 (最大と最小の特異値の比)、行列式の値 (行列式の絶対値は特異値の積に等しい) などの行列のさまざまな特徴を正確に計算します
。値は行列 U と V の計算を必要としません。

SVBkSb 特異値逆置換アルゴリズム (逆置換)

void cvSVBkSb( const CvArr* W, const CvArr* U, const CvArr* V,
const CvArr* B, CvArr* X, int flags );
W
特異値行列またはベクトル
U
左直交行列 (転置される可能性あり)
V
右直交行列(転置される可能性があります)
B
元の行列 A の擬似逆行列の乗法行列。これはオプションのパラメータです。これが省略された場合は、適切なサイズの恒等行列とみなされます (したがって、x は A の擬似逆行列の再構成になります)。
Xターゲット行列:
特異値逆置換アルゴリズムの結果の
フラグ
操作フラグ。これは、今説明した cvSVD のフラグと同じです。
関数 cvSVBkSb は、分解された行列 A と行列 B の逆置換を計算します (cvSVD の説明を参照)。

X=V W-1 UT*B
ここに

W-1(i,i)=1/W(i,i) W(i,i) > イプシロン・スミ W(i,i) の場合、それ以外の場合: 0。イプシロンは小さい数
です
この関数と cvSVD 関数は、cvInvert と cvSolve を実行するために使用されます。これらの関数 (svd および bksb) を使用する理由は、一次関数 (低レベル) 関数が高度な関数の計算で内部的に割り当てられた一時行列を回避できるためです。 (調査と解決)。

EigenVV は対称行列の固有値と固有ベクトルを計算します

void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
mat
入力対称正方行列。処理中に変更されます。
evects
固有ベクトル出力行列、
evals
固有値出力行列を降順で連続的に格納します (もちろん、固有値と固有ベクトルのソートは同期されます)。
eps
対角化の精度 (通常、DBL_EPSILON=≈10-15 で十分です)。
関数 cvEigenVV は、行列 A の固有値と固有ベクトルを計算します。

mat*evects(i,:)' = evals(i)*evects(i,:)' (MATLAB での表記)
行列 A のデータは、この関数によって変更されます。

現在、この関数は関数 cvSVD よりも遅く、精度も低くなります。A が正定値であることがわかっている場合 (たとえば、共分散行列である場合)、通常は関数 cvSVD に渡されて、その固有値と固有ベクトルが計算されます。特に固有ベクトルを計算する必要はありません。

CalcCovarMatrix ベクトルのコレクションの共分散行列を計算します

void cvCalcCovarMatrix( const CvArr** vects, int count, CvArr* cov_mat, CvArr* avg, int flags );入力ベクトル
をベクトルします。
これらは同じデータ型とサイズでなければなりません。ベクトルは 1 次元である必要はなく、2 次元 (画像など) などにすることもできます。入力ベクトルの数を
カウントします。 cov_mat は、浮動小数点型の正方行列である共分散行列を出力します。avg入力または出力配列 (フラグに依存) - 入力ベクトルの平均ベクトル。flags操作フラグ、次の値の組み合わせ: CV_COVAR_SCRAMBLED - 出力共分散行列は次のように計算されます: scale * [vects[0] − avg,vects[1] − avg,…]T * [vects[0] − avg,vects[ 1] − avg,…]、つまり、共分散行列は count×count です。このような珍しい行列は、一連の大きなベクトル (EigenFaces など) に対する高速 PCA メソッドで使用されます。顔認識技術)。このスクランブルされた (「スクランブルされた」) 行列の固有値は、真の共分散行列の固有値と一致し、真の固有ベクトルは、スクランブルされた (「スクランブルされた」) 共分散行列の固有ベクトルから簡単に計算できます。CV_COVAR_NORMAL - 出力共分散行列は次のように計算されます。










scale * [vects[0] − avg,vects[1] − avg,…] * [vects[0] − avg,vects[1] − avg,…]T、つまり cov_mat は 1 つずつになります。入力ベクトルの要素数が同じ線形サイズの共分散行列。CV_COVAR_SCRAMBLED と CV_COVAR_NORMAL は同時にどちらか 1 つだけを指定できます。
CV_COVAR_USE_AVG - このフラグが指定されている場合、関数は入力ベクトルから avg を計算せず、過去の avg ベクトルを使用します。これは、avg が何らかの方法で計算されている場合に役立ちます。または、共分散行列が部分的に計算される場合、この場合、 avg は入力ベクトルのサブセットの平均ではなく、セット全体の平均ベクトルになります。
CV_COVAR_SCALE - このフラグが指定されている場合、共分散行列がスケーリングされます。「ノーマル」モードではスケーリングは 1./count であり、「スクランブル」モードではスケーリングは各入力ベクトルの要素の合計の逆数です。デフォルトでは (フラグが指定されていない場合)、共分散行列はスケーリングされません (scale=1)。
関数 cvCalcCovarMatrix は、入力ベクトルの共分散行列と平均ベクトルを計算します。この機能は主成分分析(PCA)やマハラノビス距離(マハラノビス距離)比較ベクトルなどに利用できます。

マハラノビスは、2 つのベクトル間のマハラノビス距離 (マハラノビス距離) を計算します。

double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );
vec1
最初の 1 次元入力ベクトル
vec2
2 番目の 1 次元入力ベクトル
mat
共分散行列 cvMahalanobis の逆行列関数は
2 つのベクトルの差を計算します重み付けされた距離の場合、返される結果は次のとおりです。

d(vec1,vec2)=/sqrt{ /sum_{i,j} /{mat(i,j) (vec1(i)-vec2(i)) (vec1(j)-vec2(j))/} }
共分散行列は関数 cvCalcCovarMatrix で計算でき、逆行列は関数 cvInvert で計算できます (行列が特異である可能性があるため、CV_SVD メソッドの方が良い選択です)。

CalcPCA はベクトル セットに対して PCA 変換を実行します

void cvCalcPCA( const CvArr* data, CvArr* avg,
CvArr* eigenvalues, CvArr* eigenvectors, int flags );
データ入力データ、各ベクトル
は単一の行ベクトル (CV_PCA_DATA_AS_ROW) または単一の列ベクトル (CV_PCA_DATA_AS_COL) です。、関数内で内部的に計算されるか、呼び出し元によって提供され、eigenvaluesによって出力される共分散行列固有値を提供します。eigenvectors によって出力される共分散行列の固有ベクトル (つまり、主成分)、各ベクトルには次の行があります。flags操作フラグ。次のメソッドを組み合わせたものです。CV_PCA_DATA_AS_ROW - ベクトルは行に格納されます (つまり、任意のベクトルは連続的に格納されます) CV_PCA_DATA_AS_COL - ベクトルは列に格納されます (つまり、特定のベクトル コンポーネントの値は(上記 2 つの符号は相互に排他的です) CV_PCA_USE_AVG - 事前に計算された平均値を使用します。この関数はベクトル セットに対して PCA 変換を実行します。最初に cvCalcCovarMatrix を使用して共分散行列を計算し、次に固有値と共分散行列の固有ベクトル 出力固有値/eigenvectors 数値は MIN(rows(data),cols(data)) 以下です。












ProjectPCA はベクトルを部分空間に投影します

void cvProjectPCA( const CvArr* data, const CvArr* avg,
const CvArr* eigenvectors, CvArr* result )
データ
入力データの場合、各ベクトルは単一行または単一列の
平均
平均ベクトルにすることができます。これは、入力データが行にあることを意味します データは単一列ベクトルの形式で格納されます。つまり、入力ベクトルは列に格納されます。 eigenvectors eigenvectors (主成分
)
、各ベクトルには 1 つの行があります。
結果
出力分解係数行列、行列の行数は入力ベクトルの数と同じである必要があり、行列の列数は固有ベクトルの行数より小さくなければなりません。この関数は入力を投影します
。ベクトルを直交系 (固有ベクトル) に変換します。内積を計算する前に、入力ベクトルが平均ベクトルから減算されます。

result(i,:)=(data(i,:)-avg)*eigenvectors' // CV_PCA_DATA_AS_ROW レイアウト用。

[編集]
BackProjectPCA は
射影係数に従って元のベクトルを再構築します

void cvBackProjectPCA( const CvArr* proj, const CvArr* avg,
const CvArr* eigenvects, CvArr* result ); cvProjectPCA avg平均ベクトルの形式と一致する
proj入力データ。単一行ベクトルの場合は、出力がベクトルがそれ以外の場合、単一列ベクトルである場合、出力ベクトルは列に格納されます。eigenvectors 固有ベクトル(主成分)、各ベクトルは 1 つの行を持ちます。result関数によって出力される再構築された行列は、射影に従って元の行列を再構築します。係数ベクトル:







result(i,:)=proj(i,:)*eigenvectors + avg // CV_PCA_DATA_AS_ROW レイアウトの場合

添付

行列演算

空き行列スペースを割り当てる

概要:
OpenCV には、行列演算用の C 言語関数があります。他の多くのメソッドは、OpenCV と同じ効率で、より便利な C++ インターフェイスを提供します。OpenCV は、ベクトルを 1D 行列として処理します。行列は行に格納され、各行には 4 バイトの校正があり
ます

行列空間を割り当てます:
CvMat* cvCreateMat(int rows, intcols, int type);

    type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>.  
    例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.

    例程:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);

リリース行列空間:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvReleaseMat(&M);

行列のコピー:
CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
CvMat* M2;
M2=cvCloneMat(M1);

行列の初期化:
double a[] = { 1, 2, 3, 4, 5,
6, 7, 8,
9, 10, 11, 12 };

CvMat Ma=cvMat(3, 4, CV_64FC1, a);
別の方法:

CvMat Ma;
cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);

行列を単位行列として初期化します:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvSetIdentity(M); // ここに問題があるようですが、失敗しました。

行列要素にアクセスする

2 次元浮動小数点行列の (i,j) 番目の要素にアクセスする必要があるとします。

行列要素への間接アクセス:
cvmSet(M,i,j,2.0); // M(i,j) を設定
t = cvmGet(M,i,j); // M(i,j) を取得

4 バイトのアライメントを想定した直接アクセス:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
int n = M->cols;
float *data = M->data.fl;

データ[i*n+j] = 3.0;

直接アクセス、任意の補正バイト:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
int step = M->step/sizeof(float);
float *data = M->data.fl;

(データ+i*ステップ)[j] = 3.0;

初期化された行列要素への直接アクセス:
double a[16];
CvMat Ma = cvMat(3, 4, CV_64FC1, a);
a[i*4+j] = 2.0; // Ma(i,j)=2.0 ;

行列/ベクトル演算

行列間演算:
CvMat *Ma、*Mb、Mc;
cvAdd(Ma, Mb, Mc); // Ma+Mb -> Mc
cvSub(Ma, Mb, Mc); // Ma-Mb -> Mc
cvMatMul(Ma, Mb, Mc); // Ma
Mb -> Mc

電気効果の行列演算:
CvMat *Ma, *Mb, *Mc;
cvMul(Ma, Mb, Mc); // Ma.*Mb -> Mc
cvDiv(Ma, Mb, Mc); // Ma./Mb -> Mc
cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc

ベクトル積:
double va[] = {1, 2, 3};
double vb[] = {0, 0, 1};
double vc[3];

CvMat Va=cvMat(3, 1, CV_64FC1, va);
CvMat Vb=cvMat(3, 1, CV_64FC1, vb);
CvMat Vc=cvMat(3, 1, CV_64FC1, vc);

double res=cvDotProduct(&Va,&Vb); // ドット積: Va . Vb -> res cvCrossProduct
(&Va, &Vb, &Vc); // ベクトル積: Va x Vb -> Vc
end{verbatim}
Note Va, Vb, Vc は、ベクトル積に同じ数のベクトル要素を持たなければなりません。

単一行列演算:
CvMat *Ma, *Mb;
cvTranspose(Ma, Mb); // transpose(Ma) -> Mb (自身を転置することはできません)
CvScalar t = cvTrace(Ma); // track(Ma) - > t. val[0]
double d = cvDet(Ma); // det(Ma) -> d
cvInvert(Ma, Mb); // inv(Ma) -> Mb

非均質線形システムの解:
CvMat* A = cvCreateMat(3,3,CV_32FC1);
CvMat* x = cvCreateMat(3,1,CV_32FC1);
CvMat* b = cvCreateMat(3,1,CV_32FC1);
cvSolve(&A, &b, &x); // x について (Ax=b) を解きます。

固有値解析 (対称行列の場合):
CvMat* A = cvCreateMat(3,3,CV_32FC1);
CvMat* E = cvCreateMat(3,3,CV_32FC1);
CvMat* l = cvCreateMat(3,1,CV_32FC1);
cvEigenVV( &A , &E, &l); // l = A の固有値 (降順)
// E = 対応する固有ベクトル (行ごと)

特異値分解 SVD:
CvMat* A = cvCreateMat(3,3,CV_32FC1);
CvMat* U = cvCreateMat(3,3,CV_32FC1);
CvMat* D = cvCreateMat(3,3,CV_32FC1);
CvMat* V = cvCreateMat( 3,3,CV_32FC1);
cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = UDV^T
ラベルは、戻るときに U と V を転置します (転置ラベルがない場合、問題なく成功します) !!!)。

ビデオシーケンスの操作

ビデオ シーケンスからフレームを取得する

OpenCV は、Web カメラまたはビデオ ファイル (AVI) からの画像の取得をサポートしています。

カメラから初期化を取得:
CvCapture* Capture = cvCaptureFromCAM(0); // ビデオ デバイス #0 からキャプチャ

ビデオ ファイルから初期化を取得します:
CvCapture* Capture = cvCaptureFromAVI(“infile.avi”);

フレームを取得します:
IplImage* img = 0;
if(!cvGrabFrame(capture)){ // フレームを取得します
printf("フレームを取得できませんでした/n/7");
exit(0);
}
img=cvRetrieveFrame( Capture ); // キャプチャしたフレーム画像を復元する
複数のカメラから同時に画像を取得するには、まず各カメラからフレームをキャプチャし、すべてのキャプチャ操作が完了した後にフレーム画像を復元します。

キャプチャソースの解放
cvReleaseCapture(&capture);
なお、デバイスでキャプチャした画像はキャプチャ関数によって自動的に割り当てられ、解放されますので、自分で解放しようとしないでください。

フレーム情報の取得/設定

デバイス プロパティの取得:
cvQueryFrame(capture); // この呼び出しは正しいプロパティを取得するために必要です
// キャプチャ プロパティ
int FrameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int FrameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_W IDTH);
int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
すべてのフレーム番号はビデオ ファイルにのみ関連しているようです。カメラを使用する場合は間違っています。奇妙です。

フレーム情報の取得:
float posMsec = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
int posFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
float posRatio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO) ;
キャプチャされたフレームの位置を取得します。ビデオ シーケンス、から最初のフレームはミリ秒単位でカウントされます。または、最初のフレームの番号 0 から開始して、キャプチャされたフレームの番号を取得します。または、相対位置を取得します。最初のフレームは 0、最後のフレームは 1 です。これは、単にビデオ ファイルに有効です。

最初にキャプチャしたフレームのラベルを設定します:
// ビデオ ファイルの相対位置 0.9 からキャプチャ
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9); は
ビデオ ファイルからのキャプチャにのみ有効ですが、失敗しているようです。 !

ビデオファイルを保存する

ビデオ メモリの初期化:
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 25; // または 30
int FrameW = 640; // Firewire カメラの場合は 744
int FrameH = 480; // Firewire カメラの場合は 480
Writer=cvCreateVideoWriter( "out.avi"、CV_FOURCC('P','I','M','1')、
fps、cvSize(frameW,frameH),isColor);
他の有効なエンコーディング:

CV_FOURCC('P','I','M','1') = MPEG-1 コーデック
CV_FOURCC('M','J','P','G') = motion-jpeg コーデック (機能しません)よく)
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 コーデック CV_FOURCC
('D', 'I', 'V', '3') = MPEG-4.3 コーデック
CV_FOURCC( 'D', 'I', 'V', 'X') = MPEG-4 コーデック
CV_FOURCC('U', '2', '6', '3') = H263 コーデック
CV_FOURCC('I', '2 ', '6', '3') = H263I コーデック
CV_FOURCC('F', 'L', 'V', '1') = FLV1 コーデック ビデオ コーデックが
-1 に設定されている場合、コーデック選択ウィンドウが開きます。 (Windows システム下)。

ビデオ ファイルの保存:
IplImage* img = 0;
int nFrames = 50;
for(i=0;i<nFrames;i++){ cvGrabFrame(capture); // フレームをキャプチャimg=cvRetrieveFrame(capture); // 画像を復元cvWriteFrame ( Writer,img); // ビデオ ファイルにフレームを追加}キャプチャ中にキャプチャされた画像を表示するには、ループに次のコードを追加します。




cvShowImage(“mainWin”, img);
key=cvWaitKey(20); // 20 ミリ秒待つ
20[ミリ秒] の遅延がないと、ビデオ シーケンスは正しく表示されません。

ビデオ メモリの解放:
cvReleaseVideoWriter(&writer);

その他の行列演算関数一覧

add

矩阵加法,A+B的更高级形式,支持mask

scaleAdd

矩阵加法,一个带有缩放因子dst(I) = scale * src1(I) + src2(I)

addWeighted

矩阵加法,两个带有缩放因子dst(I) = saturate(src1(I) * alpha + src2(I) * beta + gamma)

subtract

矩阵减法,A-B的更高级形式,支持mask

multiply

矩阵逐元素乘法,同Mat::mul()函数,与A*B区别,支持mask

gemm

一个广义的矩阵乘法操作

divide

矩阵逐元素除法,与A/B区别,支持mask

abs

对每个元素求绝对值

absdiff

两个矩阵的差的绝对值

exp

求每个矩阵元素 src(I) 的自然数 e 的 src(I) 次幂 dst[I] = esrc(I)

pow

求每个矩阵元素 src(I) 的 p 次幂 dst[I] = src(I)p

log

求每个矩阵元素的自然数底 dst[I] = log|src(I)| (if src != 0)

sqrt

求每个矩阵元素的平方根

min, max

求每个元素的最小值或最大值返回这个矩阵 dst(I) = min(src1(I), src2(I)), max同

minMaxLoc

定位矩阵中最小值、最大值的位置

compare

返回逐个元素比较结果的矩阵

bitwise_and, bitwise_not, bitwise_or, bitwise_xor

每个元素进行位运算,分别是和、非、或、异或

cvarrToMat

旧版数据CvMat,IplImage,CvMatND转换到新版数据Mat

extractImageCOI

从旧版数据中提取指定的通道矩阵给新版数据Mat

randu

以Uniform分布产生随机数填充矩阵,同 RNG::fill(mat, RNG::UNIFORM)

randn

以Normal分布产生随机数填充矩阵,同 RNG::fill(mat, RNG::NORMAL)

randShuffle

随机打乱一个一维向量的元素顺序

theRNG()

返回一个默认构造的RNG类的对象

 theRNG()::fill(...)

reduce

矩阵缩成向量

repeat

矩阵拷贝的时候指定按x/y方向重复

split

多通道矩阵分解成多个单通道矩阵

merge

多个单通道矩阵合成一个多通道矩阵

mixChannels

矩阵间通道拷贝,如Rgba[]到Rgb[]和Alpha[]

sort, sortIdx

为矩阵的每行或每列元素排序

setIdentity

设置单元矩阵

completeSymm

矩阵上下三角拷贝

inRange

检查元素的取值范围是否在另两个矩阵的元素取值之间,返回验证矩阵

checkRange

检查矩阵的每个元素的取值是否在最小值与最大值之间,返回验证结果bool

sum

求矩阵的元素和

mean

求均值

meanStdDev

均值和标准差

countNonZero

统计非零值个数

cartToPolar, polarToCart

笛卡尔坐标与极坐标之间的转换

flip

矩阵翻转

transpose

矩阵转置,比较 Mat::t() AT

trace

矩阵的迹

determinant

行列式 |A|, det(A)

eigen

矩阵的特征值和特征向量

invert

矩阵的逆或者伪逆,比较 Mat::inv()

magnitude

向量长度计算 dst(I) = sqrt(x(I)2 + y(I)2)

Mahalanobis

Mahalanobis距离计算

phase

相位计算,即两个向量之间的夹角

norm

求范数,1-范数、2-范数、无穷范数

normalize

标准化

mulTransposed

矩阵和它自己的转置相乘 AT * A, dst = scale(src - delta)T(src - delta)

convertScaleAbs

先缩放元素再取绝对值,最后转换格式为8bit型

calcCovarMatrix

计算协方差阵

solve

求解1个或多个线性系统或者求解最小平方问题(least-squares problem)

solveCubic

求解三次方程的根

solvePoly

求解多项式的实根和重根

dct, idct

正、逆离散余弦变换,idct同dct(src, dst, flags | DCT_INVERSE)

dft, idft

正、逆离散傅立叶变换, idft同dft(src, dst, flags | DTF_INVERSE)

LUT

查表变换

getOptimalDFTSize

返回一个优化过的DFT大小

mulSpecturms

两个傅立叶频谱间逐元素的乘法

上の表は http://blog.sina.com.cn/s/blog_7908e1290101i97z.html から引用しました。

転載元を明記してください (この記事はリンクを更新します): http://blog.csdn.net/iracer/article/details/51296631

おすすめ

転載: blog.csdn.net/jiyanghao19/article/details/130887926