opencv Mat 操作
Mat初始化
为空不赋值
cv::Mat skeleton3D(4, 17, CV_64F);
直接赋值:
double a[] = {1,2,3,4};
Mat test(2,2,CV_64_F); cv::Mat mtest(3, 1, CV_64F, cv::Scalar::all(0)); cv::Mat mtest(3, 1, CV_64F, cv::Scalar(1,2,3)); 特殊矩阵 cv::Mat mz = cv::Mat::zeros(cv::Size(w,h), CV_8UC1); // 全零矩阵 【或者:Mat tmpdata = Mat::zeros(h, w, CV_8UC1);//h行w列的全0矩阵】 cv::Mat mo = cv::Mat::ones(cv::Size(w,h),CV_8UC1); // 全1矩阵 【或者:Mat tmpdata = Mat::ones(h, w, CV_8UC1);//h行w列的全1矩阵】 cv::Mat me = cv::Mat::eye(cv::Size(w,h),CV_32FC1); // 对角线为1的对角矩阵 【或者:Mat tmpdata = Mat::eye(h, w, CV_32FC1);//h行w列的对角矩阵
数据格式
CV_8UC1\CV_8UC2\CV_8UC3\CV_8UC4
CV_8S\--------
CV_16U\----------
CV_16S\-----------
CV_32S\----------
CV_32F\-----------
CV_64F\----------
8\16\32\64:表示位数
S:符号,
U:无符号整形
F:浮点型
表头的 C1, C2, C3, C4 指的是通道(Channel)数,
比如灰度图像只有 1 个通道,是 C1;
JPEG格式 的 RGB 彩色图像就是 3 个通道,是 C3;
PNG 格式的彩色图像除了 RGB 3个通道外,还有一个透明度通道,所以是 C4。
大家还会发现 7 怎么没有被定义类型,这个可以看 OpenCV 源码,有如下所示的一行,说明 7 是用来给用户自定义的
片选
某一行
cv::Mat m0 = m.row(i)
某一列
cv::Mat m0 = m.col(j)
某几行
cv::Mat m0 = m.rowRange(i0, i1)
某几列
cv::Mat m0 = m.colRange(j0, j1)
行列同时选择
cv::Mat m0 = m.colRange(cv::Range(j0, j1))
拼接
cv::hconcat(intrinsicCam, mtest, intrinsicCam);
乘除法
点乘
AB= A*B;//返回值是Mat类型的
AB=A.dot(B);//返回值是double类型的
对应位置相乘
AB = A.mul(B);
转置
cv::transpose(m1, m3);
翻转
cv::flip(m1, m2,1);
遍历
方式一 :最慢,最容易理解
for (int j = 0; j< image.rows; j++){
for (int i = 0; i< image.cols; i++) {
image.at<cv::Vec3b>(j, i)[0] = image.at<cv::Vec3b>(j, i)[0] / div*div + div / 2;
image.at<cv::Vec3b>(j, i)[1] = image.at<cv::Vec3b>(j, i)[1] / div*div + div / 2;
image.at<cv::Vec3b>(j, i)[2] = image.at<cv::Vec3b>(j, i)[2] / div*div + div / 2;
} // end of line
}
at <>里面对应关系
方式二:使用Mat的成员函数ptr<>()
cv::Mat中提供ptr函数访问任意一行像素的首地址,特别方便图像的一行一行的横向访问,如果需要一列一列的纵向访问图像,就稍微麻烦一点。但是ptr访问效率比较高,程序也比较安全,有越界判断
push back出错, 浅拷贝、深拷贝
Mat 的各种运算,包括加减乘除、.t(),.inv()等都会创造一个临时结果变量,但仍然存在大量的成员函数返回的只是一个Mat头指针比如A.rowrange(0,3)。因此初次使用时需要注意甄别,对后者使用clone()深度拷贝一份。
Mat m(1,1);
vector<Mat>vecMatrix;
for(int i = 0; i < 10; i++){
m.at<float>(0) = float(i);
vecMatrix.push_back(m);
}
正确的
Mat m(1,1);
vector<Mat>vecMatrix; for(int i = 0; i < N; i++){ m.at<float>(0) = float(i); vecMatrix.push_back(m.clone()); }
方法一
:使用Mat的成员函数ptr<>()
cv::Mat中提供ptr函数访问任意一行像素的首地址,特别方便图像的一行一行的横向访问,如果需要一列一列的纵向访问图像,就稍微麻烦一点。但是ptr访问效率比较高,程序也比较安全,有越界判断。