OpenCV Mat數據相關


       OpenCV中常見的與圖像操作有關的數據容器有Mat,cvMat和IplImage。這三種類型都可以代表和顯示圖像,區別是:Mat類型側重於計算,數學性較高,OpenCV對Mat類型的計算進行了優化;CvMat和IplImage類型更側重於“圖像”,opencv對其中的圖像操作(縮放、單通道提取、圖像閾值操作等)進行了優化。在opencv2.0之前,opencv是完全用C實現的,但是,IplImage類型與CvMat類型的關系類似於面向對象中的繼承關系。實際上,CvMat之上還有一個更抽象的基類----CvArr,這在源代碼中會常見。

1. opencv文檔中明確聲明,CvMat已經過時了(CvMat is now obsolete, consider using Mat instead)不建議用;
2. 派生關系:CvArr -> CvMat -> IplImage
3. Mat用的一套東西是imread,imshow等,有別於CvArr及其子類的cvLoadImage(),cvShowImage()...

Mat類型:矩陣類型,Matrix。

     在openCV中,Mat是一個多維的密集數據數組。可以用來處理向量和矩陣、圖像、直方圖等等常見的多維數據。
Mat有3個重要的方法:
1、Mat mat = imread(const String* filename); 讀取圖像
2、imshow(const string frameName, InputArray mat); 顯示圖像
3、imwrite (const string& filename, InputArray img); 儲存圖像
Mat類型較CvMat與IplImage類型來說,有更強的矩陣運算能力,支持常見的矩陣運算。在計算密集型的應用當中,將CvMat與IplImage類型轉化為Mat類型將大大減少計算時間花費。

 

1.像素值的讀取可使用at()函數:

uchar value = grayim.at<uchar>(i,j);  //讀出第i行第j列像素值
graym.at<uchar>(i,j) = 128; //將第i行第j列像素值設置為128

 2.使用Mat的成員函數ptr<>()

uchar* data = image.ptr<uchar>(j);

 3.使用迭代器遍歷圖像

cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
for (; it != itend; ++it)
{
    (*it)[0] = (*it)[0] / div*div + div / 2;
    (*it)[1] = (*it)[1] / div*div + div / 2;
    (*it)[2] = (*it)[2] / div*div + div / 2;
}

 

 4.圖像的載入、顯示和輸出到文件。   imread、imshow、imwrite

 5.滑動條的創建和使用。

int createTrackbar(const string& trackbarname,const string& winname,int* value,int count,TrackbarCallback onChange=0,void* userdata=0);

第一個參數::軌跡名稱

第二個參數:窗口名字

第三個參數:一個指向整型的指針,表示滑塊位置。

第四個參數:int類型的count表示滑塊可以達到的最大位置值。

第五個參數:指向回調函數的指針,每次滑塊位置改變時,這個函數都會進行回調,默認值是0。

第六個參數:用戶傳給回調函數的數據,用來處理軌跡條事件。如果第三個參數value實參是全局變量的話,完全可以不用去管userdata參數。

 

1、Mat類常用的構造方法
Mat();//無參數構造
Mat(int rows, int cols, int type);//創建行數為rows,列數為cols,類型為type的圖像
Mat(Size size, int type);//創建大小為size,類型為type的圖像
Mat(int rows, int cols, int type, const Scalar& s);//創建創建行數為rows,列數為cols,類型為type的圖像,且全部元素(像素)初始化為 s
Mat(Size size, int type, const Scalar& s);//創建大小為size,類型為type的圖像,且全部元素(像素)初始化為 s
Mat(const Mat& m);//將m賦值給新創建的對象,是淺拷貝


#include
<iostream> #include<opencv2/core/core.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; int main() { //創建空矩陣 Mat img1; //創建6x6的8位單通道矩陣(圖像) Mat img2(6, 6, CV_8UC1); //創建7x7的8位三通道矩陣(圖像) Mat img3(cv::Size(7, 7), CV_8UC3); //創建8x8的32位三通道矩陣(圖像),並且用cv::Scalar(0,255)填充 Mat img4(8, 8, CV_8UC3,cv::Scalar(0,255)); //創建7x7的8位三通道矩陣(圖像),並且用填充cv::Scalar(1, 2, 3)填充 Mat img5(cv::Size(7, 7), CV_8UC3, cv::Scalar(1,2,3)); Mat img6(img2); cout << img1 << endl; cout << img2 << endl; cout << img3 << endl; cout << img4 << endl; cout << img5 << endl; cout << img6 << endl; return 0; }

 6.常用數據結構和函數

   1)Point類 

Point point;
point.x = 10;
point.y = 8;
Point_<int>、Point2i、Point互相等價;Point_<float>、Point2f互相等價。

2)顏色表示 Scalar類

Scalar(b,g,r);

3)尺寸:Size類 

typedef Size_<int> Size2i;
typedef Size2i Size;
Size_<int>、Size2i、Size三個類等價

4)矩形:Rect類

Rect類的成員變量 x,y,width,height,成員函數Size()返回尺寸,area()返回面積,contains(Ponit)點是否在矩形中,inside(Rect)矩形是否在該矩形內,tl()返回左上角點坐標,br()返回右下角點坐標;
Rect rect = rect1 & rect2;求交集
Rect rect = rect1 | rect2;求並集
Rect rectShift = rect + point;
Rect rectScale = rect + size;

5)顏色空間轉換:cvtColor()函數

     可以實現RGB顏色向HSV、HSI等顏色空間的轉換,也可以轉換成灰度顏色。

cvtColor(srcImage,dstImage,COLOR_GRAY2BGR);

 

問題:

如果Mat 中想存小數,那么聲明是就要用CV_32FC1等浮點數的類型,並且在訪問像素的時候,指向每一行(i行)的指針:

不再是: uchar *data = src.ptr<uchar>(i); 了 (uchar 是0~255的無符號整數)

而是用:float *data = src.ptr<float>(i)。(以前不懂也沒注意這個,程序一直出錯)。

PS:因為再寫顏色相關圖的程序,需要保存一個掩碼mark 矩陣,其中每個元素存一個【0~1】的權重,用以前的遍歷圖片像素的代碼改的,結果總不對,后來才發現是新創建的矩陣的元素用的 uchar ,是無符號整型,不能存小數的,才恍然大悟,也才有了這篇blog,內容比較簡單,僅供自己學習,也供有需求的人參考。

以下參考自:http://www.cnblogs.com/wangguchangqing/p/4016179.html

TYPE表示了矩陣中元素的類型以及矩陣的通道個數,它是一系列的預定義的常量,其命名規則為CV_(位數)+(數據類型)+(通道數)。具體的有以下值

CV_8UC1     CV_8UC2     CV_8UC3     CV_8UC4
CV_8SC1     CV_8SC2     CV_8SC3     CV_8SC4
CV_16UC1    CV_16UC2    CV_16UC3    CV_16UC4
CV_16SC1    CV_16SC2    CV_16SC3    CV_16SC4
CV_32SC1    CV_32SC2    CV_32SC3    CV_32SC4
CV_32FC1    CV_32FC2    CV_32FC3    CV_32FC4
CV_64FC1    CV_64FC2    CV_64FC3    CV_64FC4
 
這里U(unsigned integer)表示的是無符號整數,S(signed integer)是有符號整數,F(float)是浮點數。 
例如:CV_16UC2,表示的是元素類型是一個16位的無符號整數,通道為2. 
C1,C2,C3,C4則表示通道是1,2,3,4 
type一般是在創建Mat對象時設定,如果要取得Mat的元素類型,則無需使用type,使用下面的depth
depth 
矩陣中元素的一個通道的數據類型,這個值和type是相關的。例如 type為 CV_16SC2,一個2通道的16位的有符號整數。那么,depth則是CV_16S。depth也是一系列的預定義值, 
將type的預定義值去掉通道信息就是depth值: 
CV_8U CV_8S CV_16U CV_16S CV_32S CV_32F CV_64F
elemSize 
矩陣一個元素占用的字節數,例如:type是CV_16SC3,那么elemSize = 3 * 16 / 8 = 6 bytes
elemSize1 
矩陣元素一個通道占用的字節數,例如:type是CV_16CS3,那么elemSize1 = 16  / 8 = 2 bytes = elemSize / channels
Mat的常見屬性
data     uchar型的指針。Mat類分為了兩個部分:矩陣頭和指向矩陣數據部分的指針,data就是指向矩陣數據的指針。
dims     矩陣的維度,例如5*6矩陣是二維矩陣,則dims=2,三維矩陣dims=3.
rows     矩陣的行數
cols     矩陣的列數
size     矩陣的大小,size(cols,rows),如果矩陣的維數大於2,則是size(-1,-1)
channels 矩陣元素擁有的通道數,例如常見的彩色圖像,每一個像素由RGB三部分組成,則channels = 3

 

關於將mat數據存放到xml中

void CapVideoFace()
{
  int indexNum = 0; //跳幀數.
  VideoCapture capture;
  cv::Mat frame;
  capture.open("resource/999.mp4");//讀取視頻文件
  //capture.open("rtsp://admin:admin123@10.129.74.198:554/cam/realmonitor?channel=1&subtype=1"); //讀取rtsp流
  if (!capture.isOpened())
  {
    LoggerN("capture open failed.");
    return;
  }
  while (capture.read(frame)) {
  //cv::Mat frame = imread("resource/2.jpg",1);
  if (frame.data != NULL && indexNum++%3 ==0) {

      FileStorage fs("xuchao.xml", FileStorage::WRITE);
          fs << "vocabulary" << frame; fs.release(); FileStorage fsRead("xuchao.xml", FileStorage::READ); Mat mat_vocabulary; fsRead["vocabulary"] >> mat_vocabulary; fsRead.release();

    indexNum == 0;
    std::string strPic = Mat2Base64(frame, "jpg");
    char* pBuffer = new char[3*1024*1024];
    memcpy(pBuffer,strPic.c_str(),strPic.length());

    detector[detectorIndex++].Put(pBuffer);
    if(detectorIndex == THREADNUM)
    detectorIndex = 0;
   }
  }
}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM