Mat 简介:##### Mat 用于管理图像在内存中的存储,在Opencv 3 中由于使用了内存自动管理机制,所以不必像最早的Opencv一样需要手动分配和释放内存空间,Mat是由两个部分组成的。一个图像数据矩阵头包括(矩阵尺寸、存储方法、存储地址等信息),另一个是指向存储图像所有像素值的矩阵空间的指针。 这样设计是由于一般图像数据都是比较大的,并且很多时候都是需要经过多个不同的函数处理,这就导致了需要在不同的函数间传递这个大数据结构,除非万不得已不会选择去传递比较大的Mat。所以Opencv设计了这种结构来完成Mat的快速传递,Mat矩阵头是一个常数值,而矩阵保存了图像所有的像素值,这部分通常会比矩阵头大几个数量级,在函数间传递参数的时候每个Mat都有自己的信息头,但是矩阵数据是共享的,也就是在传递Mat时,只复制矩阵头和指向矩阵的指针。
在Mat的实现中使用了引用计数机制,每次Mat对象的信息头被复制了,都会增加矩阵的引用次数加1;反之,当一个Mat的信息头被释放后,引用计数就会被减1;当计数被减到0时,矩阵就会被释放。
上述的方式我们可以知道这种情况下矩阵数据是共享的,任何一个函数改动都会影响到这个矩阵,但是有时候我们需要独立的矩阵空间,这时候可以使用clone和 copyTo。通过clone和copyTo创建的Mat,都有自己的矩阵,修改其中一个的矩阵不会对其他的造成影响。
Mat 属性:#####
data uchar型的指针。就是上面提到的指向矩阵数据的指针。 dims 矩阵的维度 rows 矩阵的行数 cols 矩阵的列数 size 矩阵的大小 channels 矩阵元素通道数
type 命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:它表示的是每个像素的元素的存储方式 CV_8UC1 CV_8UC2 CV_8UC3 CV_8UC4 CV_8SC1 CV_8SC2 CV_8SC3 CV_8SC4 …
depth 色彩深度 depth 的类型如下所示: CV_8U CV_8S CV_16U CV_16S CV_32S CV_32F CV_64F elemSize 矩阵一个元素占用的字节数 elemSize1 矩阵元素一个通道占用的字节数
Mat 创建和初始化:##### cv ::Mat img(20 ,20 ,CV_8UC3,cv::Scalar(255 ,255 ,255 ));
上述代码创建了一个20行20列的矩阵,矩阵元素使用8位无符号char类型保存,具有3通道,每个像素的初始值是(255,255,255)黑色,这里需要注意Scalar的表示顺序为BGR 构造函数的前两个参数指定了矩阵的行和列 第三个参数指定矩阵元素的数据类型以及通道数,其指定规则如下:
img .create (20 ,20 ,CV_8UC(3 ));该方法不能为矩阵设置初始值
特殊矩阵的创建:
cv:: Mat e = cv:: Mat:: eye(20 ,20 ,CV_64F) cv:: Mat z = cv:: Mat:: ones(20 ,20 ,CV_32F) cv:: Mat o = cv:: Mat:: zeros(20 ,20 ,CV_8UC3)
小矩阵的创建: 一些如核等小矩阵的创建还可以使用如下方式:
Mat c =(Mat_<double>(3 ,3 )<<1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 );
矩阵的直观表示:#####
颜色空间缩减:##### 将现有的颜色空间进行映射,以获得较少的颜色数,目的是为了加快部分算法的处理速度
矩阵的遍历:##### #include <QCoreApplication> #include <opencv2/highgui/highgui.hpp> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> void changeImageUsePointer(cv ::Mat& sourceImage ,cv ::Mat& dstImage ,uchar radio ) { dstImage = sourceImage.clone() ; int rows = dstImage.rows; int cols = dstImage.cols * dstImage.channels() ; for (int rowindex = 0 ;rowindex < rows ;rowindex++) { uchar *element = dstImage.ptr<uchar>(rowindex); for (int colindex = 0 ; colindex < cols;colindex++) { element[colindex ] = static_cast<uchar>(element[colindex ] /radio)*radio; } } } void changeImageByIterator(cv ::Mat& sourceImage ,cv ::Mat& dstImage ,uchar radio ) { dstImage = sourceImage.clone() ; cv::MatIterator_<cv::Vec3b> beginIterator = dstImage.begin <cv::Vec3b>() ; cv::MatIterator_<cv::Vec3b> endIterator = dstImage.end <cv::Vec3b>() ; cv::MatIterator_<cv::Vec3b> iterator; for (iterator = beginIterator ;iterator != endIterator; ++iterator) { (*iterator)[0 ] = ((*iterator)[0 ] /radio)*radio; (*iterator)[1 ] = ((*iterator)[1 ] /radio)*radio; (*iterator)[2 ] = ((*iterator)[2 ] /radio)*radio; } } void changeImageByLocation(cv ::Mat& sourceImage ,cv ::Mat& dstImage ,uchar radio ) { dstImage = sourceImage.clone() ; int cols = dstImage.cols; int rows = dstImage.rows; for (int row = 0 ;row < rows;row++) { for (int col = 0 ;col < cols;col++) { uchar b = dstImage.at<cv::Vec3b>(row,col)[0 ] ; dstImage.at<cv::Vec3b>(row,col)[0 ] = (b/radio)*radio; uchar g = dstImage.at<cv::Vec3b>(row,col)[1 ] ; dstImage.at<cv::Vec3b>(row,col)[1 ] = (g/radio)*radio; uchar r = dstImage.at<cv::Vec3b>(row,col)[2 ] ; dstImage.at<cv::Vec3b>(row,col)[2 ] = (b/radio)*radio; } } } int const PROCESS_TIME = 10 ;int const COLOR_REDUCE = 10 ;int main(int argc, char *argv[] ) { cv::Mat srcImage = cv::imread("/home/jimmy/QtOpenCV/image/test_access.png" ); if (!srcImage.data) { return -1 ; } cv::Mat dstImage; dstImage.create(srcImage.rows,srcImage.cols,srcImage.type () ); int64 startTime = cv::getTickCount() ; for (int i = 0 ;i< PROCESS_TIME; i++) { changeImageUsePointer(srcImage ,dstImage ,COLOR_REDUCE) ; } int64 endTime = cv::getTickCount() ; qDebug("Consume Time by Pointer= %f" ,(endTime -startTime ) /cv::getTickFrequency() /PROCESS_TIME); startTime = cv::getTickCount() ; for (int i = 0 ;i< PROCESS_TIME; i++) { changeImageByIterator(srcImage ,dstImage ,COLOR_REDUCE) ; } endTime = cv::getTickCount() ; qDebug("Consume Time by Pointer= %f" ,(endTime -startTime ) /cv::getTickFrequency() /PROCESS_TIME); startTime = cv::getTickCount() ; for (int i = 0 ;i< PROCESS_TIME; i++) { changeImageByLocation(srcImage ,dstImage ,COLOR_REDUCE) ; } endTime = cv::getTickCount() ; qDebug("Consume Time by Pointer= %f" ,(endTime -startTime ) /cv::getTickFrequency() /PROCESS_TIME); cv::namedWindow("Test Access SRC" ) ; cv::namedWindow("Test Access Dest" ) ; cv::imshow("Test Access SRC" ,srcImage); cv::imshow("Test Access Dest" ,dstImage); int keycode = cv::waitKey(0) ; if (keycode == 27 ) { cv::destroyAllWindows() ; } }