opencv基础02-Mat及其原理
一段测试程序
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
Mat function1() {
Mat ima(500, 500, CV_8U, 50);
return ima;
}
int main() {
//创建一个行240*320列的新图像
Mat image1(240, 320, CV_8U, 100);
imshow("Image",image1);
cv::waitKey(0);
//重新分配一个新图像
image1.create(200, 200, CV_8U);
image1 = 200;
imshow("Image", image1);
waitKey();
//创建一个红色图像
// 通道依次为BGR
Mat image2(240, 320, CV_8UC3, Scalar(0, 0, 255));
//Mat image2(Size(320,240), CV_8UC3, Scalar(0, 0, 255));
//image2 = Scalar(0,0,255)
imshow("Image", image2);
waitKey();
//读入一幅图像
Mat image3 = imread("lena.jpg");
image1 = image3;
image3.copyTo(image2);
//所有图像都指向同一个数据块
Mat image4(image3);
image1 = image3;
//这些图像是原图像的副本图像
image3.copyTo(image2);
Mat image5 = image3.clone();
flip(image3, image3, 1);
imshow("image1",image1);
imshow("image2", image2);
imshow("image3", image3);
imshow("image4", image4);
imshow("image5", image5);
waitKey(0);
//从函数中读取一个灰度图像
Mat gray = function1();
imshow("gray", gray);
waitKey();
//作为灰度图像读入
image1 = imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
image1.convertTo(image2, CV_32F, 1 / 255.0, 0.0);
imshow("Image",image2);
waitKey();
return 0;
}
下面主要就是这五张图片
下面来说说原理
Mat 有两个必不可少的组成部分 一个头部、一个数据块。
头部白喊了句正的所有相关信息(大小、通道数量、数据类型),这些信息可以直接操作。
数据块包含了图像中所有像素的值。头部有一个指向数据块的指针,即 data 属性。 cv::Mat 有一个很重要的属性,即只有在明确要求时,内存块才会被复制。大多数操作仅仅复制了 cv::Mat 的头部,因此多个对象会指向同一个数据块。这种内存管理模式可以提高应用程序的运行效率,避免内存泄漏。
新建一个Mat对象的大小默认为0,也可以设定初始值。需要指定每个矩阵元素的类型,像 CV_8U表示每个像素对应一个字节(灰度图像),U无符号,S表示有符号,彩色图像可以用三通道类型(CV_8UC3),同样16位 32位整数有符号无符号可以类似 CV_16SC3。32位64位浮点数也是支持的 CV_32F。
图像或矩阵的而每个元素都可以包含多个值(彩色图像的三个通道),cv::Scalar 这个数据结构就可以用于调用函数时传递参数像素值,该结构通常包含一个或三个值。如果要创建一个彩色图像并用红色填充的话可以使用如下
cv::Mat image(cv::Size(320,240),CV_8UC3,cv::Scalar(0,0,255))//注意opencv中三通道图像排序是b g r
初始化灰度图像可以使用这个数据结构cv:Scalar(100)
图像的尺寸信息通常也需要传递给参数函数。虽然我们可以通过属性cols和rows来获取cv:Mat的实例大小。cv::Size()结构包含了矩阵的高度和宽度。同样可以提供图形学的尺寸信息。另外可以使用Size()方法得到当矩阵的大小,当需要知道那个矩阵的大小的时候,很多方法都使用如下的格式
cv::Mat image(cv::Size(320,240),CV_8UC3);
可以随时使用create方法分配或重新分配图像的数据块,如果图像的数据块已被分配,其原来的内容会被释放。出于对性能的考虑,如果新的尺寸和类型与原来的相同,就不会重新分配内存。
image.create(200,100,CV_8UC3);//仅仅在大小和类型不同时会重新分配内存