-
Mat数据格式
2019-08-19 16:29:29目录1 图片格式转换2 png格式转换为Mat3 读写Mat格式的数据 1 图片格式转换 以下代码为Mat、QImage、QPixmap图片格式之间的转换函数: #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp...1 row、col 和 x、y 的关系
- rows:表示图像有多少行
- cols: 表示图像有多少列
- heigh: 高度
- width: 宽度
关系:
rows == heigh == Point.y cols == width == Point.x Mat::at(Point(x, y)) == Mat::at(y,x)
2 创建Mat图像
//创建Mat图像(像素值自定义) Mat MM(5, 5, CV_8UC1, Scalar(128,0,0));// 参数(int rows, int cols, int type, const Scalar& s) cout << "MM = " << endl << " " << MM << endl; //创建Mat图像(像素值205) Mat MC; MC.create(5, 5, CV_8UC1); cout << "MC = "<< endl << " " << MC << endl; //创建Mat图像(像素值单位矩阵) Mat E = Mat::eye(5, 5, CV_8UC1); cout << "E = " << endl << " " << E << endl; //创建Mat图像(像素值全1矩阵) Mat O = Mat::ones(5, 5, CV_32FC1); cout << "O = " << endl << " " << O << endl; //创建Mat图像(像素值全0矩阵) Mat Z = Mat::zeros(5, 5, CV_64FC1); cout << "Z = " << endl << " " << Z << endl;
3 读写Mat数据
cv::Mat mat = ...; mat.at<cv::Vec3b>(0, 3)[3] = 0; std::cout << mat.rows << std::endl;//行数 std::cout << mat.cols << std::endl;//列数 std::cout << mat.channals() << std::endl;//通道数
4 遍历Mat数据
at 的方式:
int i; for (int m = 0; m < mat.cols; m++) { for (int n = 0; n < mat.rows; n++) { for (int c = 0; c < mat.channels(); c++) { //Vec3b:表示mat的向量格式,也就是读写的数据格式,这里表示一个像素有3个byte; i = mat_RGB.at<cv::Vec3b>(n, m)[c]; } // 若为单通道 // i = mat_RGB.at<cv::Vec3b>(n, m); } }
ptr 的方式(效率更高):
for (int i =0; i < img.rows; ++i) { const int * ptr = img.ptr<int>(i); for (int j = 0; j < img.cols * img.channels(); ++j) { int data = ptr[j]; } }
5 图片 0-1 和 0-255 的转换
// 0~255 -> 0~1 img.convertTo(img, CV_32F, 1.0/255); // 0~1 -> 0~255 color.convertTo(color, CV_8U, 255);
6 改变 Mat 尺寸
// img1是输入图像,img2是输出图像,后面那个是尺寸 cv::resize(img1, imgc2, cv::Size(500,311));
7 读取 Mat 类型
myMat = imread("C:\someimage.jpg"); int type = myMat.type();
返回的类型是个数字,数字的含义可以在下面表格中查找:
- C1 C2 C3 C4 C5 C6 C7 C8 CV_8U 0 8 16 24 32 40 48 56 CV_8S 1 9 17 25 33 41 49 57 CV_16U 2 10 18 26 34 42 50 58 CV_16S 3 11 19 27 35 43 51 59 CV_32S 4 12 20 28 36 44 52 60 CV_32F 5 13 21 29 37 45 53 61 CV_64F 6 14 22 30 38 46 54 62 C1~C8是通道数,CV_8U ~ CV_64F是图像的数据格式;
8 色彩空间的转换
//将RGB格式的图像转换成BGR格式 cvtColor(RGB_image, BGR_image, COLOR_RGB2BGR); //将BGR格式的图像转换成灰度图 cvtColor(BGR_imgage, gray_image, COLOR_BGR2GRAY); //将BGR格式的图像转换为BGRA cvtColor(BGR_imgage, gray_image, COLOR_BGR2BGRA);
- HSV六棱锥
H参数表示色彩信息,即所处的光谱颜色的位置,用一角度量来表示;红绿蓝间隔隔120度,互补色分别相差180度;
S纯度为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率,S=0时,只有灰度;
V表示色彩的明亮程度,范围从0到1;有一点要注意:它和光强度之间并没有直接的联系。
-
I420(YUV420P)
相比于 RGB 格式,I420 所需要的物理内存更小,当然也有一定精度的损失。I420 格式的内存分布如下,y1 - y16 是图像的尺寸(w * h),也就是一副黑白图,u1 - u4 可以计算蓝色像素的分量,v1 - v4 可以计算红色像素的分量,YUV 和 RGB 的转换公式:R = Y + 1.403V G = Y - 0.344U - 0.714V B = Y + 1.770U
y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 y11 y12 y13 y14 y15 y16 u1 u2 u3 u4 v1 v2 v3 v4 可能会有一个疑问,为什么 U、V 的数量都是 Y 的 ?
我们首先将 Y 的尺寸 (w * h) 全部划分为 (2*2) 小矩形,每一个小矩形(4像素)分别对应了一个 u、v,所以是 4 被倍关系。从内存分布上看,RGB 占用了 (w * h * 3) 的空间,而 YUV 占用了 (w * h * 1.5) 的空间,缩减了一半。注意:转换时需要划分为小矩形,所以图片的尺寸要求一定是偶数。
-
420SP
420SP 只是在 I420 的基础上改变了 U、V 的分布:y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 y11 y12 y13 y14 y15 y16 u1 v1 u2 v2 u3 v3 u4 v4
9 数据格式的转换
//将[0,1]范围内的浮点表示的图像转换成8bit整数表示的图像 float_image.convertTo(integer_image, CV_8U, 255.0); convertTo函数定义如下: /** @brief Converts an array to another data type with optional scaling. The method converts source pixel values to the target data type. saturate_cast\<\> is applied at the end to avoid possible overflows: \f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) + \beta )\f] @param m output matrix; if it does not have a proper size or type before the operation, it is reallocated. @param rtype desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input. @param alpha optional scale factor. @param beta optional delta added to the scaled values. */ void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
10 单通道转换为多通道
// 把传入的单通道灰度图转换为3通道RGB cv::Mat convertTo3Channels(const cv::Mat& binImg) { cv::Mat three_channel = cv::Mat::zeros(binImg.rows,binImg.cols,CV_8UC3); std::vector<cv::Mat> channels; for (int i=0;i<3;i++) { channels.push_back(binImg); } merge(channels,three_channel); return three_channel; }
11 从多通道中分离单通道
cv::Mat img = ...; std::vector<cv::Mat> channals[0]); cv::split(img, channals); cv::imshow("通道0", channals[0]); cv::imshow("通道1", channals[1]); cv::imshow("通道2", channals[2]);
12 Mat、QImage、QPixmap 之间的转换
:::details 头文件
#include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <imgproc/types_c.h> #include <QtGui/QImage> #include <QtWidgets/QFileDialog> cv::Mat QImage2cvMat(QImage image); cv::Mat QPixmapcvMat(QPixmap image); QImage cvMat2QImage(const cv::Mat& mat); QPixmap cvMat2QPixmap(const cv::Mat& mat); QImage QPixmapQImage(QPixmap image); QPixmap QImageQPixmap(QImage image);
:::
:::details c文件
#include "ImaRormConv.h" cv::Mat QImage2cvMat(QImage image) { cv::Mat mat; switch(image.format()) { case QImage::Format_ARGB32: case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); break; case QImage::Format_RGB888: mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(mat, mat, CV_BGR2RGB); break; case QImage::Format_Indexed8: mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; } return mat; } cv::Mat QPixmapcvMat(QPixmap image) { QImage img = image.toImage(); cv::Mat mat = QImage2cvMat(img); return mat; } QImage cvMat2QImage(const cv::Mat& mat) { // 8-bits unsigned, NO. OF CHANNELS = 1 if(mat.type() == CV_8UC1) { QImage image(mat.cols, mat.rows, QImage::Format_Indexed8); // Set the color table (used to translate colour indexes to qRgb values) image.setColorCount(256); for(int i = 0; i < 256; i++) { image.setColor(i, qRgb(i, i, i)); } // Copy input Mat uchar *pSrc = mat.data; for(int row = 0; row < mat.rows; row ++) { uchar *pDest = image.scanLine(row); memcpy(pDest, pSrc, mat.cols); pSrc += mat.step; } return image; } // 8-bits unsigned, NO. OF CHANNELS = 3 else if(mat.type() == CV_8UC3) { // Copy input Mat const uchar *pSrc = (const uchar*)mat.data; // Create QImage with same dimensions as input Mat QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); return image.rgbSwapped(); } else if(mat.type() == CV_8UC4) { // Copy input Mat const uchar *pSrc = (const uchar*)mat.data; // Create QImage with same dimensions as input Mat QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32); return image.copy(); } else { return QImage(); } } QPixmap cvMat2QPixmap(const cv::Mat& mat) { QImage img = cvMat2QImage(mat); QPixmap pix = QPixmap::fromImage(img); return pix; } QImage QPixmapQImage(QPixmap image) { QImage img = image.toImage(); return img; } QPixmap QImageQPixmap(QImage image) { QPixmap pix = QPixmap::fromImage(image); return pix; }
:::
13 Mat 和 Vector 互换
/***************** Mat转vector **********************/ template<typename _Tp> vector<_Tp> convertMat2Vector(const Mat &mat) { return (vector<_Tp>)(mat.reshape(1, 1));//通道数不变,按行转为一行 } /****************** vector转Mat *********************/ template<typename _Tp> cv::Mat convertVector2Mat(vector<_Tp> v, int channels, int rows) { cv::Mat mat = cv::Mat(v);//将vector变成单列的mat cv::Mat dest = mat.reshape(channels, rows).clone();//channels是通道数,rows是行数,这里的.clone是防止下面的return出错 return dest; }
-
官网Mnist的数据格式ubyte转为matlab适用的.mat数据格式的代码
2018-11-29 10:00:47从官网下载的mnist数据集格式是ubyte格式,本代码可以将其转换为.mat数据集格式,从而用于matlab的训练 -
matlab中.mat数据格式转换为txt格式
2013-07-30 11:21:13不用修改就可以用的 mat简单方便的转换为txt格式的代码 -
读取 txt/其他格式数据,(以opencv 指针显示数据格式或 Mat数据格式)转为图片显示
2020-07-11 11:30:48cv::Mat image1; image1.create(Width, eHeight, CV_8U); ifs.open(path, std::ios::binary); if (!ifs.is_open()) { std::cout << "Cannot open file " <<path << std::endl; return image1...cv::Mat image1; image1.create(Width, eHeight, CV_8U); ifs.open(path, std::ios::binary); if (!ifs.is_open()) { std::cout << "Cannot open file " <<path << std::endl; return image1; } ifs.read((char *)image1.data, Width *Height); cv::Mat src2(imageHeight,imageWidth,CV_8U, image1.data); src = src2.clone(); ifs.close();
src 为转化后的 Mat 类型数据
可对其进行 常规 Mat操作或者 选择 image1也可以,
auto p =img1.ptrcv::Vec3b(i,j);
cPointB = p[j][0];
cPointG = p[j][1];
cPointR = p[j][2];
来进行像素读取 -
将图片转化为pickle或者mat数据格式
2018-11-05 16:21:25为了做小样本的实验,所以需要先将图片数据转化为pickle或者mat格式的数据,便于以后的读取,避免每次训练的时候,都要重新挨个图片读取在给标注。 这里我是看的tensorflow和Udacity合作的视频教程,所以学习到了将...原文地址:https://blog.csdn.net/weixin_36193572/article/details/82110656
为了做小样本的实验,所以需要先将图片数据转化为pickle或者mat格式的数据,便于以后的读取,避免每次训练的时候,都要重新挨个图片读取在给标注。
这里我是看的tensorflow和Udacity合作的视频教程,所以学习到了将数据做乘pickle格式的方法
try: with open(set_filename, 'wb') as f: pickle.dump(dataset, f, pickle.HIGHEST_PROTOCOL) except Exception as e: print("无法制作 :", set_filename, e)
其主要步骤就是将你想要存储的数据存到“dataset"变量中,然后利用pickle.dump函数进行存储,一开始我使用480张512×512×3的图像存储的时候没有问题,但是,当数据量增加,便出现啦如下错误SystemError: error return without exception set
查找资料之后,根据https://blog.csdn.net/lj695242104/article/details/43062059
据说是pickl的一个bug,所以我换了一个路子,把数据存储为mat格式,经学习,发现python可以直接读写mat个数数据,而不需要使用matlab(省了不少事情啊),下面给出存储和读取mat格式数据的代码
首先是存储,我这里是将之前做好的两个pickle文件合并为了一个mat文件,之前合并车给为pickle的时候是会报错的,但是mat就没事。
同时也是用randomize函数将数据集的顺序打乱
# --*--coding:utf-8--*-- from __future__ import print_function import imageio import matplotlib.pyplot as plt import numpy as np import os import sys import tarfile from IPython.display import display, Image from sklearn.linear_model import LogisticRegression from six.moves.urllib.request import urlretrieve from six.moves import cPickle as pickle import pprint import scipy.io as sio def randomize(dataset, labels): permutation = np.random.permutation(labels.shape[0]) # 根据labels的形状,获得一个随机的选取的顺序 shuffled_dataset = dataset[permutation,:,:] # 然后根据这个顺序依次取出dataset中中的数据放到shuffled_dataset中 shuffled_labels = labels[permutation] # 然后还是根据这个数据 将lable放到shuffled_labels中, # 这样就保证啦data与label的一一cuing挂希不改变 return shuffled_dataset, shuffled_labels folder = '你的路径' class0_filename = '0.pickle' class1_filename = '1.pickle' pk1 = os.path.join(folder,class0_filename) pk2 = os.path.join(folder,class1_filename) path_list =[] path_list.append(pk1) path_list.append(pk2) all_image = np.ndarray(shape=[960,512,512,3],dtype=np.float32) all_label = np.ndarray(shape=[960],dtype=np.int32) for index,pk in enumerate(path_list): pkl_file = open(pk, 'rb') images = pickle.load(pkl_file) label = np.ndarray(shape=[len(images)],dtype=np.int32) label[0:len(label)] = index all_image[index*480:(index+1)*480] = images all_label[index*480:(index+1)*480] = label # pprint.pprint(data1) print (pk,' 中images文件的形状是 ',images.shape) print (pk,' 中images[0]的形状是',images[0].shape) pkl_file.close() print ('all_image shape is ',all_image.shape) print ('all_label shape is ',all_label.shape) shuffled_dataset,shuffled_labels = randomize(all_image,all_label) print ('shuffed completed') data = { 'images':shuffled_dataset, 'label':shuffled_labels } print ('begin to save to mat file') sio.savemat('mattest.mat',data) print ('mat file saved success')
然后是读取数据,这里读取完之后还进行啦几个图片的展示,确认以下数据是否正确。
# --*--coding:utf-8--*-- from __future__ import print_function import imageio import matplotlib.pyplot as plt import numpy as np import os import sys import tarfile from IPython.display import display, Image from sklearn.linear_model import LogisticRegression from six.moves.urllib.request import urlretrieve from six.moves import cPickle as pickle import scipy.io as sio pkl_file = open('datadata', 'rb') # data = pickle.load(pkl_file) data = sio.loadmat('mattest.mat') print ('the keys in data is ', data.keys()) images = data['images'] label = data['label'] print ('image shape ',images.shape) print ('label shape ',label.shape) # 遍历读取到的data和label,证实文件存储内容没有问题 for index ,image in enumerate(images): if index >475 and index <485: print (index,' image size is ',image.shape) print (index,' the label is ', label[0][index]) plt.figure("class") plt.imshow(image) plt.show()
-
opencv——Mat数据格式及其遍历
2018-06-02 22:19:52上面的三个Mat对象srcImg,dstImg,C最终都只想同一个数据矩阵,虽然它们的headers是不同的。对它们其中的任意一个进行修改都会影响另外两个对象。上面程序的运行结果如图: 当然,如果想拷贝矩阵本身也是有办法的...在opencv早期的版本中,图像通过一个叫做IplImage的结构(structure)存储在内存中。由于C语言对程序员高度的信任,因此它需要手动地对内存进行管理,比如内存的分配和回收,这在大型程序设计中是比较麻烦的。幸运地是,C++可以很好地帮助程序员管理内存,因此opencv2.0后就引入了C++接口。但是C++也有缺点,比如说目前大部分的嵌入式系统只支持C语言,在这些平台上开发opencv程序的话用C++就不是很好。
cv::Mat是一个C++类,包含两部分:1)Matrix header,包括矩阵的size、存储方式、矩阵的存储地址等信息;2)指向Marix的指针ji。由于图像处理算法通常都是计算密集型算法,出于程序速度上的考虑,opencv的设计应尽可能地避免拷贝大图像,为了解决这个问题,opencv使用了引用计数机制(reference counter system)【python也使用了这个机制,参考之前的博客】。简单来说,灭个Mat对象都有自己的header,在进行copy运算时,只有headers和指向矩阵的指针会被拷贝,而矩阵本身不会被拷贝,举个栗子:
int main() { cv::Mat srcImg(2, 2, CV_8UC3, cv::Scalar(0, 0, 255)); cv::Mat dstImg(srcImg); cv::Mat C = srcImg; std::cout << srcImg << std::endl; std::cout << dstImg << std::endl; dstImg.ptr<uchar>(0)[0] = 255; dstImg.ptr<uchar>(0)[1] = 255; dstImg.ptr<uchar>(0)[2] = 0; std::cout << "After modified dstImg:" << std::endl; std::cout << srcImg << std::endl; std::cout << dstImg << std::endl; std::cout << C << std::endl; return 0; }
上面的三个Mat对象srcImg,dstImg,C最终都只想同一个数据矩阵,虽然它们的headers是不同的。对它们其中的任意一个进行修改都会影响另外两个对象。上面程序的运行结果如图:
当然,如果想拷贝矩阵本身也是有办法的,opencv提供了两个方法:clone()和copyTo():
Mat F = A.clone(); Mat G; A.copyTo(G);
最后总结一下:
1)opencv函数中输出图像的内存是自动分配的;
2)赋值运算和拷贝构造函数只是拷贝了header,我们可以把这种拷贝理解为一种浅拷贝;
3)如果想进行深拷贝,即拷贝矩阵本身的数据,可以采用clone()或copyTo()函数。
对1和2的理解可以很重要,这可以解释下面这个程序:
int main() { cv::String path = "E:/Data Sets/ORIGINAL/data_road_fisheye/training/image/"; std::vector<cv::String> filenames; cv::glob(path, filenames); cv::Mat srcImg(2, 2, CV_8UC3, cv::Scalar(0, 0, 255)); cv::Mat dstImg(srcImg); cv::Mat C = srcImg; std::cout << srcImg << std::endl; std::cout << dstImg << std::endl; std::cout << C << std::endl; dstImg.ptr<uchar>(0)[0] = 255; dstImg.ptr<uchar>(0)[1] = 255; dstImg.ptr<uchar>(0)[2] = 0; std::cout << "After modified dstImg:" << std::endl; std::cout << srcImg << std::endl; std::cout << dstImg << std::endl; std::cout << C << std::endl; cv::cvtColor(C, C, CV_RGB2GRAY); std::cout << "After call cv::cvtColor(C,C,CV_RGB2GRAY)" << std::endl; std::cout << srcImg << std::endl; std::cout << dstImg << std::endl; std::cout << C << std::endl; return 0; }
其运行结果为:
关于如何创建一个Mat对象,最好的办法就是看mat.hpp,因为实在有太多了...,这里在介绍一下opencv里面的一下data
type,比如说CV_8UC3,CV_32FC3,CV_32F是什么意思:
CV_[the number of bits per item][signed or unsigned][Type prefix]C[The channel number]
最后是一个大头部分:介绍如何遍历cv::Mat。
Q1:图像在Mat中是如何存储的呢?
A1:
通常我们有足够多的内存,使得上面这个矩阵可以一行接着一行地连续存储,具体是不是呢,可以用isContinous()函数来判断。因此最高效的遍历方法还是采用指针(还有迭代器方法):
Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); int channels = I.channels(); int nRows = I.rows * channels; int nCols = I.cols; if (I.isContinuous()) { nCols *= nRows; nRows = 1; } int i,j; uchar* p; for( i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); for ( j = 0; j < nCols; ++j) { p[j] = table[p[j]]; } } return I; } MatObject.ptr<type>(rowIndex)[columIndex] = a number
-
MFC显示Mat数据格式(Opencv)图片,保证4字节对齐,图片缩放不错行
2017-05-11 11:41:50在MFC的Picture Control控件中显示Mat数据 *! Mat img: 需要显示的Mat数据 *! UINT nID: 控件的ID号 *! 支持直接传入 BGR ,BGRA, GARY 三种颜色空间的Mat图 *! 如果你的Mat是其它颜色空间的,在调用该函数之前... -
海思Hi3516cv500使用IVE实现VIDEO_FRAME_INFO_S的yuv420sp转换rgb的opencv下Mat数据格式
2020-06-29 09:39:15海思平台从vpss取出的图像帧为yuv420sp,数据格式为VIDEO_FRAME_INFO_S,而opencv调用时多为rgb格式,所以在海思平台使用opencv时需要将VIDEO_FRAME_INFO_S的yuv420sp转为rgb格式,如果使用传统方法将VIDEO_FRAME_... -
mat格式转换到libsvm数据格式
2021-03-04 11:00:21mat格式转换到libsvm数据格式 mat format to libsvm mat格式转换到libsvm数据格式 mat format to libsvm -
python读取mat文件格式_python怎样读mat文件格式
2020-12-16 13:43:28mat数据格式是Matlab的数据存储的标准格式,在python中可以使用scipy.io中的函数loadmat()读取mat文件。importscipy.ioassciopath='ex3data1.mat'data=scio.loadmat(path)type(data)dict#data是字典格式data.keys().... -
Mat 数据类型格式
2018-07-03 10:12:311.Unsigned 8bits(一般的图像文件格式使用的大小) IplImage数据结构参数:IPL_DEPTH_8U CvMat数据结构参数:CV_8UC1,CV_8UC2,CV_8UC3,CV_8UC4 变量类型 空间大小 范围 其他 uchar 8bi...