當前位置:首頁 » 密碼管理 » opencv訪問mat的元素

opencv訪問mat的元素

發布時間: 2024-09-05 11:14:43

A. opencv 中 Mat 數據結構的用法

#include "stdafx.h"

#include <string>
#include <iostream>

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int _tmain(int argc, _TCHAR* argv[])
{
//創建一個用1+3j填充的 7 x 7 復矩陣-----1
Mat M(7, 7, CV_32FC2, Scalar(1,3));

//現在將 M轉換為100 x 60的CV_8UC(15)的矩陣,舊內容將會被釋放
M.create(100, 60, CV_8UC(15));//不能為矩陣設置初值

//第 5行,乘以 3,加到第 3 行,
M.row(3) = M.row(3) + M.row (5) * 3;

//現在將第7列復制到第1列, M.col(1) = M.col(7);//這個不能實現,對列操作時要新建一個Mat
Mat M1 = M.col(1);
M.col(7).To(M1);

//創建一種新的 320 x 240 圖像-----2
Mat img(Size(320,240), CV_8UC3, Scalar::all(255));

string strWindowName = "ShowImage";

namedWindow(strWindowName, WINDOW_AUTOSIZE);
imshow(strWindowName, img);
waitKey(0);

//選擇ROI(region of interest)
Mat roi(img, Rect(10, 10, 100, 100));

//填充 (0,255,0) 的ROI (這是RGB 空間中的綠色),320 x 240 原始圖像將被修改
roi = Scalar(0, 255, 0) ;

imshow(strWindowName, img);
waitKey(0);

//獲取數組中的子塊-----3
Mat A = Mat::eye(10, 10, CV_32S);

//提取 A 的1 (含)到 3 (不包含)列
Mat B = A(Range::all(), Range(1, 3));

//提取 B 的5 (含)到 9 (不包含)行,即 C ~ A(Range(5,9),Range (1,3))
Mat C = B(Range(5, 9), Range::all());

Size size;
Point ofs;

C.locateROI(size, ofs);//使用locateROI() 計運算元數組在主容器數組中的相對的位置
cout<<size.width<<" "<<size.height<<" "<<ofs.x<<" "<<ofs.y<<endl;

//快速初始化小矩陣-----4
double m[3][3] = {{1, 2, 3}, {1, 2, 5}, {3, 4, 6}};

Mat M2 = Mat(3, 3, CV_64F, m);//.inv();

Mat E = Mat::eye(4, 4, CV_64F);
cout<<"E = "<<endl<<" "<<E<<endl;

Mat O = Mat::ones(2, 2, CV_32F);
cout<<"O = "<<endl<<" "<<O<<endl;

Mat Z = Mat::zeros(3,3, CV_8UC1);
cout<<"Z = "<<endl<<" "<<Z<<endl;

//IplImage、Mat、CvMat互轉-----5
IplImage *img1 = cvLoadImage("aa.jpg", 2 | 4);

Mat mtx(img1);//IplImage *-> Mat,新的Mat類型與原來的IplImage類型共享圖像數據,轉換只是創建一個Mat矩陣頭// or : Mat mtx = img1;

CvMat oldmat = mtx;//Mat-> CvMat //只是創建矩陣頭,而沒有復制數據,oldmat不用手動釋放

CV_Assert((oldmat.cols == img1->width) && (oldmat.rows == img1->height) && (oldmat.data.ptr == (uchar *)img1->imageData) && (oldmat.step == img1->widthStep));

imshow(strWindowName, mtx);
waitKey(0);

cvNamedWindow(strWindowName.c_str(), 0);
cvShowImage(strWindowName.c_str(), &oldmat);
cvWaitKey(0);

IplImage img2 = mtx;//Mat->IplImage //只是創建圖像頭,而沒有復制數據,img2不用手動釋放

cvShowImage(strWindowName.c_str(), &img2);
cvWaitKey(0);

Mat mat3(&oldmat);//CvMat->Mat

imshow(strWindowName, mat3);
waitKey(0);

cvDestroyWindow(strWindowName.c_str());
cvReleaseImage(&img1);

//創建 3 x 3 雙精度恆等矩陣-----6
Mat M3 = (Mat_ <double>(3,3) <<1,0,0, 0,1,0, 0,0,1);

//訪問數組元素-----7
M2.at<double>(0, 0) += 10.f;

double sum = 0;//計算元素和,方法一

for (int i=0; i<M2.rows; i++)
{
const double *Mi = M2.ptr<double>(i) ;

for (int j=0; j<M2.cols; j++)
{
sum += std::max(Mi[j], 0.);
}
}
cout<<sum<<endl;

sum = 0;//計算元素和,方法二

int cols =M2.cols, rows = M2.rows ;

if (M2.isContinuous())
{
cols *= rows;

rows = 1 ;
}

for (int i=0; i<rows; i++)
{
const double *Mi = M2.ptr <double>(i);

for (int j=0; j<cols; j++)
{
sum += std::max(Mi[j], 0.);
}
}
cout<<sum<<endl;

sum = 0;//計算元素和,方法三

MatConstIterator_<double> it = M2.begin<double>(), it_end = M2.end<double>();

for(; it != it_end; ++it)
{
sum += std::max(*it, 0.);
}
cout<<sum<<endl;

return 0;

}

B. 安卓opencvmat怎麼取值最快

安卓opencvmat取值如下。
1、利用at函數取值,單通道圖像讀取方式和三通道圖像讀取方式。
2、使用指針取值。
3、使用迭代器取值。
4、使用矩陣元素的地址定位知識取值。

C. Opencv中數據結構Mat的相關屬性

搬運自本人 CSDN 博客: 《Opencv中數據結構Mat的相關屬性》

以上摘自OpenCV 2.4.9的官方文檔opencv2refman.pdf。

以前雖然能夠比較熟練的使用OpenCV,但是最近感覺其實筆者自己對OpenCV的最底層數據結構Mat與IplImage都不怎麼熟悉…… 由於筆者比較反感總是需要管理內存的IplImage,所以對Mat數據結構做一下學習工作還是有必要的。

官方說明文檔opencv2refman.pdf中,寫出了Mat的定義如下:

下面筆者將從幾個方面總結Mat數據結構的主要組成。

參考網址:
《OpenCV中對Mat裡面depth,dims,channels,step,data,elemSize和數據地址計算的理解 》
《OpenCV Mat的常見屬性》
《OpenCV學世拿早習筆記(四十)——再談OpenCV數據結構Mat詳解》

參考文檔:
《opencv2refman.pdf》

如上面的Mat定義源碼,Mat類中有很多重要的數據類型成員。
下面進行簡單的列舉。

把這四個數據成員放在一起,是因為這四個數據成員相互之間有關系。

數據的存儲一直都是個值得關注的問題,所以數據元素存儲的位數和范圍就十分重要了。depth就體現了每一個像素的位數,即深度。
Mat中包含的圖像深度如下所示:

另外還需要注意:大部分OpenCV的函數支持的數據深度只有8位和32位,所以盡量使用CV_64F。

channels表示了矩陣擁有的通道數量,這個比較容易理解:

type表示矩陣中元素的類型(depth)與矩陣的通道個數(channels),可以理解成上面的depth與channels的綜合說明。type是一系列預定義的常量,命名規則如下:
<code>CV_+位數+數據類型+通敏簡道數</code>
具體有如下值:

表格中,行代表了通道數量channels,列代表了圖像深度depth。
例如CV_8UC3,可以拆分為:

註:type一般是在創建Mat對象時設定,若要去搜雀的Mat的元素類型,可以不使用type,使用depth。

elemSize表示了矩陣中每一個元素的數據大小,單位是位元組。公式如下:
<code>elemSize = channels * depth / 8</code>
例如type == CV_16SC3,則elemSize = 3 * 16 / 8 = 6 Bytes。

elemSize1表示了矩陣元素的一個通道佔用的數據大小,單位是位元組。公式如下:
<code>elemSize = depth / 8</code>
例如type == CV_16SC3,則elemSize1 = 16 / 8 = 2 Bytes。

使用OpenCV處理圖像時,最普遍的處理方式便是遍歷圖像,即訪問所有的圖像像素點。但有的演算法還需要訪問目標像素的鄰域,所以這時候就需要了解訪問Mat數據元素地址的方式。

假設有矩陣M,則數據元素的地址計算公式如下:
$$ addr(M_{i_{0}, i_{1}, ... i_{m-1}}) = M.data + M.step[0] * i_{0} + M.step[1] * i_{1} + ... + M.step[M.dims - 1] * i_{M_{dims-1}} $$
如果是二維數組,則上述公式就簡化成:
$$ addr(M_{i,j}) = M.data + M.step[0] * i + M.step[1] * j $$

註:式中m = M.dims,即矩陣的維度。

假設存在一個二維矩陣如下圖所示:

上面是一個3 × 4的矩陣。此時我們按照數據類型為CV_8U, CV_8UC3的情況,分別對其進行討論。

首先假設其數據類型為CV_8U,也就是單通道的uchar類型,則可以得出上面的數據成員情況分別為:

若假設其數據類型為CV_8UC3,也就是三通道的uchar類型,則可以得出上面的數據成員情況分別為:

假設存在一個三維矩陣如下圖所示:

上面是一個3 × 4 × 6的矩陣。假設其數據類型為CV_16SC4,此時對其進行討論。

關於OpenCV地址訪問方法及效率的部分,請見筆者的博文 《OpenCV像素點鄰域遍歷效率比較,以及訪問像素點的幾種方法 》 。

熱點內容
androidforvs2010 發布:2024-11-24 21:06:05 瀏覽:285
安裝MySqllinux 發布:2024-11-24 21:05:51 瀏覽:325
聯通網洛盒的密碼在哪裡 發布:2024-11-24 21:05:12 瀏覽:180
牌順編程 發布:2024-11-24 20:56:23 瀏覽:728
金庫門鎖如何配置 發布:2024-11-24 20:55:46 瀏覽:952
如何編寫伺服器安裝文檔 發布:2024-11-24 20:46:09 瀏覽:470
什麼安卓手機全方面可以超過蘋果 發布:2024-11-24 20:30:35 瀏覽:800
面窩麻將腳本 發布:2024-11-24 20:29:16 瀏覽:234
安卓手機處理器八核是什麼意思 發布:2024-11-24 20:29:11 瀏覽:175
安卓手機怎麼內錄直播 發布:2024-11-24 20:29:08 瀏覽:894