深入了解cv::Mat

一、代码实现

cv::Mat类是用来存放图像(以及其他矩阵数据)的数据结构。在所有的OpenCV类和函数中,这个数据结构具有核心地位。
上代码:

#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

// test function that creates an image
cv::Mat function() {

	// create image
	cv::Mat ima(500, 500, CV_8U, 50);
	// return it
	return ima;
}

int main() {

	// define image windows
	cv::namedWindow("Image 1");
	cv::namedWindow("Image 2");
	cv::namedWindow("Image 3");
	cv::namedWindow("Image 4");
	cv::namedWindow("Image 5");
	cv::namedWindow("Image");

	// create a new image made of 240 rows and 320 columns
	cv::Mat image1(240, 320, CV_8U, 100);
	// or:
	// cv::Mat image1(240,320,CV_8U,cv::Scalar(100));

	cv::imshow("Image", image1); // show the image
	cv::waitKey(0); // wait for a key pressed

	// re-allocate a new image
	// (only if size or type are different)
	image1.create(200, 200, CV_8U);
	image1 = 200;

	cv::imshow("Image", image1); // show the image
	cv::waitKey(0); // wait for a key pressed

	// create a red color image
	// channel order is BGR
	cv::Mat image2(240, 320, CV_8UC3, cv::Scalar(0, 0, 255));

	// or:
	// cv::Mat image2(cv::Size(320,240),CV_8UC3);
	// image2= cv::Scalar(0,0,255);

	cv::imshow("Image", image2); // show the image
	cv::waitKey(0); // wait for a key pressed

	// read an image
	cv::Mat image3 = cv::imread("G:\\OpenCV2pictures\\puppy.bmp");

	// all these images point to the same data block
	cv::Mat image4(image3);
	image1 = image3;

	// these images are new copies of the source image
	image3.copyTo(image2);
	cv::Mat image5 = image3.clone();

	// transform the image for testing
	cv::flip(image3, image3, 1);

	// check which images have been affected by the processing
	cv::imshow("Image 3", image3);
	cv::imshow("Image 1", image1);
	cv::imshow("Image 2", image2);
	cv::imshow("Image 4", image4);
	cv::imshow("Image 5", image5);
	cv::waitKey(0); // wait for a key pressed

	// get a gray-level image from a function
	cv::Mat gray = function();

	cv::imshow("Image", gray); // show the image
	cv::waitKey(0); // wait for a key pressed

	// read the image in gray scale
	image1 = cv::imread("G:\\OpenCV2pictures\\puppy.bmp", CV_LOAD_IMAGE_GRAYSCALE);

	// convert the image into a floating point image [0,1]
	image1.convertTo(image2, CV_32F, 1 / 255.0, 0.0);

	cv::imshow("Image", image2); // show the image
	cv::waitKey(0); // wait for a key pressed

	return 0;
}

运行结果:
在这里插入图片描述

二、实现原理

1、cv::Mat有两个必不可少的组成部分:一个头部和一个数据块。头部包含了矩阵的所有相关信息(大小、通道数量、数据类型)。数据块包含了图像中所有像素的值。头部有一个指向数据块的指针,即data属性。

2、cv::Mat有一个很重要的属性,即只有在明确要求时,内存块才会被复制。实际上,大多数操作仅仅复制了cv::Mat的头部,因此多个对象会同时指向同一个数据块。这种内存管理模式可以提高应用程序的运行效率,避免内存泄漏。

3、指定元素的类型时,用CV_8U表示每个像素对应1字节,用字母U表示无符号,字母S表示有符号。对于彩色图,可以用三通道类型:CV_8UC3,16位的整数:CV_16SC3,32位的浮点数:CV_32F。

4、当两个图像之间赋值时,图像数据(即像素)并不会被复制,此时两个图像都指向同一个内存块。对其中的任何一个做转换都会影响到其他图像。如果要对图像内容做一个深复制,可以使用copyTo方法。

参考书:《OpenCV计算机视觉编程攻略》


版权声明:本文为weixin_38952721原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。