OpenCV的基本矩陣操作與示例
OpenCV中的矩陣操作非常重要,本文總結了矩陣的創建、初始化以及基本矩陣操作,給出了示例代碼,主要內容包括:
- 創建與初始化
- 矩陣加減法
- 矩陣乘法
- 矩陣轉置
- 矩陣求逆
- 矩陣非零元素個數
- 矩陣均值與標準差
- 矩陣全局極值及位置
- 其他矩陣運算函數列表
1. 創建與初始化矩陣
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:三通道、C4:四通道。
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;
2. 矩陣運算
2.1 基本概念
OpenCV的Mat類允許所有的矩陣運算。
2.2 矩陣加減法
我們可以使用"+"和"-"符號進行矩陣加減運算。- 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;
2.3 矩陣乘法
使用"*"號計算矩陣與標量相乘,矩陣與矩陣相乘(必須滿足矩陣相乘的行列數對應規則)
- 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;
2.4 矩陣轉置
矩陣轉置是將矩陣的行與列順序對調(第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");
2.5 求逆矩陣
逆矩陣在某些算法中經常出現,在OpenCV中通過Mat類的inv()方法實現- // 求逆
- Mat meinv = me.inv();
- cout<<"me = "<<endl<<me<<endl<<endl;
- cout<<"meinv = "<<endl<<meinv<<endl<<endl;
- system("pause");
單位矩陣的逆就是其本身。
2.6 計算矩陣非零元素個數
計算物體的像素或面積常需要用到計算矩陣中的非零元素個數,OpenCV中使用countNonZero()函數實現。- // 非零元素個數
- int nonZerosNum = countNonZero(me); // me爲輸入矩陣或圖像
- cout<<"me = "<<endl<<me<<endl;
- cout<<"me中非零元素個數 = "<<nonZerosNum<<endl<<endl;
- system("pause");
2.7 均值和標準差
OpenCV提供了矩陣均值和標準差計算功能,可以使用meanStdDev(src,mean,stddev)函數實現。參數
- src – 輸入矩陣或圖像
- mean – 均值,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");
多通道矩陣運算結果:
2.8 求最大最小值
求輸入矩陣的全局最大最小值及其位置,可使用函數:- 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();
3. 其他矩陣運算
其他矩陣運算函數見下表:Function (函數名) | Use (函數用處) |
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
//////////////////////////////////////////////////////////////////
轉載:https://blog.csdn.net/iracer/article/details/51296631