1. 总结
先贴上我总结的Opencv的数据类型, 主要是针对不同Mat类型进行新建,修改和访问时使用, 更详细的数据访问见下文:
2. CV_8UC3解说
新建一个CV_8UC3型的cv::Mat, 其中U代表了unsigned char型的数据, 其表示的范围为0 到 255; C3表示三个通道, 也就是同一个位置能存放几个数字;
最常见的使用位置是用于保存图像类型, C3用于存储RGB彩色图像, C1用于存储灰度图像, 为什么用uchar型数据来存储图像数据, 这里有详细的解释.
总结来讲,就是int型的数据表示范围过大, 如果使用int型, 一副图像所占内存有点大, 而 uchar型数据范围刚好用来保存256级的像素, 节省空间;
具体的访问:
std::string image_path = myRGBimagePath;
cv::Mat input_image = cv::imread(image_path, -1);
std::cout << "input_image type: "<< input_image.type() << std::endl;
cv::Vec3b a_pixel = input_image.at<cv::Vec3b>(0,0);
std::cout << "pixel in center: " << (int)a_pixel[0] << ", "<< (int)a_pixel[1] << ", " << (int)a_pixel[2] << std::endl;
cv::Mat input_gray(input_image.size(), CV_8UC1);
cv::cvtColor(input_image,input_gray,CV_RGB2GRAY);
std::cout << "input_gray <0,0> " << (int)input_gray.at<uchar>(0,0) <<std::endl;
3. CV_8SC2详解
接下来说一下不常见的CV_8S类型的数据, 以CV_8SC2为例, S代表了有符号 signed char, 8就代表了这个数据可以用8bit表示, 上面的unsigned char 型, 8bits 表示范围是0~255, 那么这里的signed char型表示的范围自然就正负各一半: - 128 到 127; C2代表了两个通道; 下面举个例子:
其中的每个元素都是8位的有符号整型;
假如这是5*5的Mat, 那么(0,0) 位置上有两个元素存放, 为(-85, -127);
这里对signed char型多通道Mat的访问, 如何用at实现,我还不太清楚, 这也就是为什么上面表格中第二行没有对应的Vec, 有了解的欢迎不吝赐教啊!!
这里举一个用行指针实现的Mat的访问:
cv::Mat input_image_schar;
input_image.convertTo(input_image_schar, CV_8SC3);
schar* mypixel = input_image_schar.ptr<schar>(0);
std::cout << "mypixel = " << (int)mypixel[0] << "," <<(int)mypixel[1] << ","<<(int)mypixel[2] << "," << std::endl;
有更多基础知识想要了解的,可以看这个OpenCV Tutorial (查看图片可能需要翻墙)
4. InputArray 与cv::Mat
cv::InputArray() 是opencv建立的一个更包容的类, 一般用在OpenCV的函数接口处; 可以承接Mat、Mat_、Mat_<T, m, n>、vector <T>、vector<vector<T>、vector<Mat> 类型的数据; 这里简单地与Mat做一个转换:
std::vector<cv::Point2f> myPoints_xy;
myPoints_xy.push_back(cv::Point2f(2.45,3.7));
myPoints_xy.push_back(cv::Point2f(3.68,8.8));
myPoints_xy.push_back(cv::Point2f(8.55,8.12));
cv::InputArray myArray_xy(myPoints_xy);
std::cout << "myArray_xy type: " << myArray_xy.type() << "myArray_xy size: " << myArray_xy.size()<< std::endl;
cv::Mat myMat_xy;
myArray_xy.getMat().convertTo(myMat_xy,CV_32FC2);
cv::Vec2f tmpPoint = myMat_xy.at<cv::Vec2f>(0,0);
std::cout << "tmpPoint is " << tmpPoint[0] << "," << tmpPoint[1] << std::endl;
output:
myArray_xy.type() = 13: CV_32FC2 size: [3 x 1]
tmpPoint is 2.45,3.7
5. Mat的不同访问方式
int main()
{
cv::Mat matF(3, 3, CV_32F);
randu(matF, Scalar(0), Scalar(10));
int rowIdx = 1;
int colIdx = 1;
float f1 = matF.at<float>(rowIdx, colIdx);
float* fData2 = (float*)matF.data;
float f2 = fData2[rowIdx*matF.step1() + colIdx];
float* fData3 = matF.ptr<float>(0);
float f3 = fData3[rowIdx*matF.step1() + colIdx];
float* fData4 = matF.ptr<float>(rowIdx);
float f4 = fData4[colIdx];
Mat1f mm(matF);
float f5 = mm(rowIdx, colIdx);
return 0;
}
这部分代码参考: SO上的问题
对于Mat的访问想进一步了解的, 可以参考我的这篇小白学习OpenCV Mat, 可能对于Step, Channel那些会有进一步的了解.
有什么问题,欢迎大家多多交流~~
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)