1. 程式人生 > >Opencv學習(一)之Mat類

Opencv學習(一)之Mat類

作為初學者,我對於Opencv的學習總是比較迷茫,還好可以借鑑別人的部落格。

Mat類的內容比較多,這次我也只是對它有個基礎、淺層的認識,在以後的學習和應用中我會根據需要和例項再不斷補充學習。

一 背景

    在Opencv1.X時代,資料型別為 IpIImage;

    在Opencv2.X時代,資料型別為Mat.現在Mat更為常見。

二 用途

    Mat類最重要的用途是作為儲存影象的資料結構。至於Mat類如何儲存影象(灰度圖/彩色圖),我參考的是別人的一篇部落格。

    http://lib.csdn.net/article/opencv/42000

    暫且知道Mat由矩陣頭(包含矩陣的大小、儲存方法等)和一個指向矩陣的指標構成。

三 Mat如何讀取影象的內容

    在此主要介紹兩種方法(借鑑別人的部落格寫了個例程供自己學習)

    方法一:at操作(操作物件:灰度影象)

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

int main()
{
	Mat image = imread("D:\\Tencent\\test.jpg");  //存放自己影象的路徑 
	//namedWindow("Show");//在這裡加不加這條語句,效果一樣
	imshow("Show", image);
	waitKey(0);
	resize(image, image, Size(375, 500));//resize為500*375的影象
	cvtColor(image, image, CV_RGB2GRAY);//轉為灰度圖
	imshow("image_ori", image);
	waitKey(0);
	for (int i = 0; i < image.rows; i++)
	{
	
		for (int j = 0; j < image.cols; j++)
		{
			image.at<uchar>(i, j) = i + j;
		}
	}
	imshow("image_res",image);
	waitKey(0);
	return 0;
}

以上是對於灰度影象的處理,對於彩色影象的處理只需要把at<型別>中的型別改為Vec3b即可

例程如下:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

int main()
{
	Mat image = imread("D:\\Tencent\\test.jpg");  //存放自己影象的路徑 
	/*namedWindow("Show");*/
	imshow("Show", image);
	resize(image, image, Size(375, 500));//resize為500*375的影象
	//cvtColor(image, image, CV_RGB2GRAY);//轉為灰度圖
	//imshow("image_ori", image);
	for (int i = 0; i < image.rows; i++)
	{
	
		for (int j = 0; j < image.cols; j++)
		{
			/*image.at<uchar>(i, j) = i + j;*/
			//iamge.at<Vec3b>(i, j)[0] = 255;//對於藍色通道進行操作
		 image.at<Vec3b>(i, j)[1] = 255;//對於綠色通道進行操作
		 //img.at<Vec3b>(i, j)[2] = 255;//對於紅色通道進行操作
		}
	}
	imshow("image_res",image);
	waitKey(0);
	return 0;
}

方法二:採用指標對影象進行訪問

        以下給出對彩色影象操作的例程

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>

using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("D:\\Tencent\\test.jpg");
	int rows = img.rows;//矩陣行
	int cols = img.cols * img.channels();//彩色影象的列
	if (img.isContinuous())//判斷是否在記憶體中連續
	{
		cols = cols * rows;
		rows = 1;//如果連續,則為一行
	}
	imshow("ori", img);
	for (int i = 0; i<rows; i++)//控制行
	{
		//調取儲存影象記憶體的第i行的指標
		uchar *pointer = img.ptr<uchar>(i);

		for (int j = 0; j<cols; j += 3)
		{
			//pointer[j] = 255;//對藍色通道進行操作
			//pointer[j+1] = 255;//對綠色通道進行操作
			pointer[j + 2] = 255;//對紅色通道進行操作
		}
	}
	imshow("result", img);
	waitKey();
	return 0;
}

四 Mat類中常用的變數引數(Mat的宣告在core.hpp中)

      Mat類中有很多的變數引數,先熟悉以下幾個:

  1.  size(cols,rows)   cols-列數,rows-行數
  2. CV_8UC3 其中8U表示8位無符號整數,C後為通道數
  3. Mat M1(3,2,cv_8uc3,scalar(0,0,225)); 定義Mat類的M為一個3行,2列,每列由3個元素(0,0,225)構成的 矩陣,其中的scalar()完成對每個元素的賦值。
  4. Mat M2(size(3,2),cv_8uc3,scalar(1,2,3));
  5. Mat M3(M2);  
  6. step1(i)表示的是Mat中的每一維的通道數
  7. step[i]表示Mat中的每一維的大小(以位元組為單位)
  8. size[i]表示Mat中元素的個數
  9. elemSize()表示每個元素的大小(以位元組為單位)

通過例項理解上面定義物件的含義

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>
#include <time.h>

using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("D:\\Tencent\\test.jpg");
	cout << "img.rows: " << img.rows <<endl<< " img.cols: " << img.cols <<endl<< " img.channels(): " << img.channels() << endl;
	cout << "**********************" << endl;
	cout << "img.step1(0): " << img.step1(0) << endl;
	cout << "img.step1(1): " << img.step1(1) << endl;
	cout << "img.step[0]: " << img.step[0] << endl;
	cout << "img.step[1]: " << img.step[1] << endl;
	cout << "img.size[0]: " << img.size[0] << endl;
	cout << "img.size[1]: " << img.size[1] << endl;
	cout << "img.elemSize(): " << img.elemSize() << endl;
	cout << "img.elemSize1(): " << img.elemSize1() << endl;
	uchar response;
	cin >> response;
	return 0;
}
由於剛學者用部落格,只會載入圖片,還不知道咋載入執行視窗,所以目前所有的例項都沒有上傳執行結果,但親測無誤。部落格是一個很好的平臺,寫部落格對自己的知識是一種歸練,對別人也是一種幫助,我會緊跟大神步伐不斷完善的。