1. 程式人生 > >OpenCV學習(5) Mat的基本操作(2)

OpenCV學習(5) Mat的基本操作(2)

http://www.cnblogs.com/mikewolf2002/p/3320734.html

     本章我們學習一下Mat中的常用操作,因為在後面其它的教程中,我們經常要對影象進行各種處理,也要使用這些操作。

 

一、 Mat的複製,就是從一個矩陣A,生成相關的另一個矩陣B。

(1)使用賦值的方法,比如通過建構函式生成矩陣N,通過複製生成矩陣P

cv::Mat N(M);
cv::Mat P;
P=M;

     這樣生成的矩陣,只是新生成一個矩陣頭,它的data依然指向矩陣M的data,類似C++中的淺拷貝,比如矩陣M,N,P它們的data都指向地址0x00badd50

imageimageimage

(2) 使用copyTo和clone函式

cv::Mat F = M.clone();
cv::Mat G;
F.copyTo(G);

      這樣可以生成一個全新的矩陣,不但複製矩陣的頭資訊,而且會生成一個data的拷貝。比如矩陣F和M,它們的data指標地址和F是不同的。

imageimage

      注意:copyTo函式,它還可以帶有掩碼矩陣copyTo(G, maskImage), maskImage是一個單通道的矩陣,值為0的位置,在拷貝時候並不會拷貝。

image

 

二、Mat中常用的幾個函式

1. convertTo(OutputArray m, int rtype, double alpha=1, double beta=0 )

生成一個新矩陣,矩陣的中值為原矩陣中的值乘以alpha,然後再加上beta

484B0C~1

imageMask.convertTo(mark1,CV_8U);

 

2. Mat::reshape(int cn),改變矩陣的維數,比如把二維矩陣改變成一維矩陣。這個操作只是改變矩陣的頭資訊,比如在沒有padding資料情況下,便於資料處理,有時候我們會把二維矩陣變成一維矩陣。

imageMask.reshape(1);

 

3. isContinous,檢測矩陣是否有padding資料。

double sum=0;
int cols = M.cols, rows = M.rows;
if(M.isContinuous())
{
    cols *= rows;
    rows = 1;
}
for(int i = 0; i < rows; i++)
{
    const double* Mi = M.ptr<double>(i);
    for(int j = 0; j < cols; j++)
        sum += std::max(Mi[j], 0.0);
}

 

4. 用下面的程式碼,可以取出矩陣的某個ROI區域,以便進行處理。

cv::Rect rect(100, 100, 100, 100); 

srcImage(rect).copyTo(roiImage); 

5.下面的程式碼,實現一個矩陣的子矩陣賦值,矩陣roi的data指標會指向result1的data的50行,70列處。

cv::Mat result1= cv::Mat(image1.rows, image1.cols,CV_8UC1, cv::Scalar(cv::GC_BGD));
//注意給子矩陣賦值的方法
cv::Mat roi(result1, cv::Rect(50,70,result1.cols-150,result.rows-180));
roi = cv::Scalar(cv::GC_PR_FGD);

 

三、簡單的三維矩陣示例

//建立一個3維矩陣,每維都是長度為2
int sz[3] = {3,3,3};
cv::Mat L(3,sz, CV_8UC(1), cv::Scalar::all(1));

//列印多維陣列
for(i=0; i< 3; i++)
    {
    for(j=0; j<3; j++)
        {
          for(k=0; k<3; k++)
              {
               // printf("%d \n", L.data[i*3*3 + j*3 +k]);
              }
        }
    }

四、稀疏矩陣

      有時候,我們需要使用多維矩陣儲存一些值,比如三維BGR影象的直方圖,由於每維的索引數都是256,所以矩陣元素數量達到256*256*256,如果用普通矩陣儲存,需要分配很大的空間,這時候,最好使用稀疏矩陣sparseMat,因為在稀疏矩陣中只儲存非零的值。

下面是使用稀疏矩陣的簡單例子:

//稀疏矩陣的操作
//建立一個三維的稀疏矩陣

const int dims = 3;
int size[] = {256, 256, 256};
SparseMat sparse_mat(dims, size, CV_32F);
//20個非0的值,注意:稀疏矩陣儲存非零的值
for(int i = 0; i < 20; i++)
    {
    int idx[dims];
    for(int k = 0; k < dims; k++)
        idx[k] = rand()%256;
    sparse_mat.ref<float>(idx) = 2.f;
    }

//顯示稀疏矩陣的結果
SparseMatConstIterator_<float> it1 = sparse_mat.begin<float>(),    it_end = sparse_mat.end<float>();
double s = 0;
int dims1 = sparse_mat.dims();
for(; it1 != it_end; ++it1)
    {
    // 列印索引和元素的值
    const SparseMat::Node* n = it1.node();
    printf("(");
    for(int i = 0; i < dims1; i++)
        printf("%d%s", n->idx[i], i < dims-1 ? ", " : ")");
    printf(": %g\n", it1.value<float>());
    s += *it1;
    }
printf("元素的個數 %g\n", s);

程式執行的結果:

image