cv::Mat——Mat對象創建方法 OpenCV (一)

OpenCV (一)——Mat對象創建方法

1.cv::Mat優點及原理(本質類)

  • 不需要手動申請一塊內存;
  • 在不需要時不用再手動釋放內存;
  • 可以通過類的封裝,方便的獲取到數據的相關信息。

  它利用了類的特性,將內存管理和數據信息封裝在類的內部,用戶只需要對Mat類對象進行數據或面向對象操作即可。
Mat類分爲兩個部分:矩陣頭矩陣數據。如果我們在操作一副圖像的數據量時,矩陣數據量一般很大,那麼針對拷貝和賦值函數的操作如果的深拷貝的話,效率會大大的降低。所以,Opencv的做法是只複製其矩陣頭信息,而矩陣數據採用引用的方式,即多個Mat對象共享同一個矩陣數據,這裏使用的原理類似c++11中的共享指針(本質類)

	cv::Mat A = cv::imread("image.jpg");
	cv::Mat B(A);
//淺層拷貝:Mat B=A;B就是淺層拷貝A,B只拷貝了A的的頭部和地址,當B被操作後A也隨之改變。

memcpy(A.data, output.data(), rows * cols * sizeof(uint16_t));

	cv::Mat C = A;
//深層拷貝:Mat A=imread("x.jpg"); Mat B=A.clone();B是開闢了新的內存完全的複製了A的內容,操作B不會對A造成影響。
	printf("A.data = %p\nB.data = %p\nC.data = %p\n", A.data, B.data, C.data);
output:
A.data =  00240AA0ADHH00C0
B.data =  00240AA0ADHH00C0
C.data =  00240AA0ADHH00C0

釋放內存原則:由於內部使用了引用計數的方法,類似共享指針,當引用計數變爲0的時候纔會真正的釋放內存。

temp_thin.convertTo(temp_thin_image, CV_8UC1, 1, 0);

Mat F = A.clone();
Mat G;
A.copyTo(G);
  • 輸出圖像分配 OpenCV 功能是自動 (除非另行指定,否則)。
  • 用c + + OpenCV的接口就無需考慮內存釋放。
  • 賦值運算符和複製構造函數 (構造函數)只複製頭。
  • 使用clone () 或copyTo () 函數將複製的圖像的基礎矩陣。
//二值化,類型轉換,賦值
    memcpy(cv_thin_image_rgb_.data, output.data(), rows * cols * sizeof(uint16_t));
    temp_thin = cv_thin_image_rgb_;
    uint16_t* tdata = (uint16_t*) (temp_thin.data);
    uint8_t* bdata = cv_binary_image_rgb_.data;
    for (int i = 0; i < cols; i++) {
      for (int j = 0; j < rows; j++) {
        if (*tdata == 0) {
          *bdata = 0;
        } else {
          *bdata = 1;
        }
        tdata++;
        bdata++;
      }
    }
    temp_binary = cv_binary_image_rgb_;

2.cv::Mat 類對象的創建方法

cv::Mat roi_image_color = temp_thin_image_color(cv::Rect(119, 69, 210, 260));//139,129,168,168

Mat E = A(Range:all(), Range(1,3)); // 用行和列來界定

 上文中的所有對象,以相同的單個數據矩陣的結束點。他們頭不同,但是使用的其中任何一個對矩陣進行任何修改,也將影響所有其他的。在實踐中的不同對象只是提供相同的底層數據不同的訪問方法,然而,它們的頭部是不同的。真正有趣的部分是您可以創建僅指向完整數據的一小部分的頭。例如,要在圖像中創建興趣區域 ( ROI) 您只需創建一個新頭設置新邊界: 

cv::Mat M4 = (cv::Mat_<double>(3, 3) << 0, -1, 0, -1, 0, 0, 0, 0, 1);
std::cout << "M4 = " << std::endl << M4 << std::endl;

Mat drawing_poly_color = Mat::zeros(roi_image_color.size(), CV_8UC1);

cv::Mat temp_thin_image_color = cv::imread("../example/mask.bmp", CV_LOAD_IMAGE_UNCHANGED);


//這裏是將PCL的點雲數據中的RGB信息提取出來進行賦值輸出圖片
cv::Mat gray(cloud->height, cloud->width, CV_8UC1);
//前兩個參數是矩陣的行數和列數,後一個矩陣類型8U 8位無符號整數,c1表示1個channel,rgb圖片這裏就需要設置爲CV_8UC3

for (int i = 0; i < cloud->points.size(); i++){
	uchar* grayrowptr = gray.ptr<uchar>(i / cloud->width);//提取行指針
	grayrowptr[i%cloud->width] = cloud->points[i].r;
}

cv::imwrite("gray_zxr.bmp", gray);

3.cv::Mat 類對象元素訪問方法

ptr訪問效率比較高,程序也比較安全,有越界判斷。

//方法1:
	Mat img(1000, 1000, CV_32F);
	
	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			img.at<float>(i,j) = 3.2f;//方法1:
            img.ptr<float>(i)[j] = 3.2f;//方法2:
		}
	}
	//***方法3********推薦使用。耗時最短******************************
	Mat img3(1000, 1000, CV_32F);
	float* pData = (float*)img3.data;

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			*(pData) = 3.2f;
			pData++;
		}
	}
	//***方法4************************************************************
	Mat img4(1000, 1000, CV_32F);

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			((float*)img3.data)[i*1000+j] = 3.2f;
		}
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章