opencv image 指针 像素
opencv 中3通道image,image中每个点包含3个值
,这上个值分别是B G R
例如:2x2 CV_8UC3(uchar channels=3)的图像
Mat img_8UC3(2, 2, CV_8UC3, Scalar(0, 255, 255)); //初始化为(B G R)=(0, 255, 255)
数据排列方式:
(0,255,255)(0,255,255)
(0,255,255)(0,255,255)
逐像素操作为:
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp" // #include "opencv2/core.hpp"
#include <stdio.h>
#include<iostream>//标准输入输出
//命名空间
using namespace cv;
using namespace std;
int main(int argc, char const *argv[])
{
//创建一个2*2 类型为8位的uchar类型三通道的 颜色为黄色
Mat img_8UC3(2, 2, CV_8UC3, Scalar(0, 255, 255));
imshow("img_8UC3",img_8UC3);
Mat img_32FC3(2,2,CV_32FC3,Scalar(255,0,0));
imshow("img_32FC3",img_32FC3);
for (int i = 0; i<img_32FC3.rows; i++)
{
for (int j = 0; j < img_32FC3.cols; j++)
{
static float t;
static int cn=0;
static int ch =img_32FC3.channels();
for(int k =0;k<ch;k++){
//t=img_32FC3.at<Vec3f>(i,j)[k];
//t=((Vec3f*)(img_32FC3.data + img_32FC3.step.p[0] * i))[j][k];
t=((float*)(img_32FC3.data + img_32FC3.step.p[0] * i))[ch*j+k];
cout<<"t"<<cn<<"="<<t<<endl;
cn++;
}
}
}
//cout<<"last_t"<<t<<"last_cn"<<cn<<"last_ch"<<ch<<endl;
waitKey();
return 0;
}
output:
t0=255
t1=0
t2=0
t3=255
t4=0
t5=0
t6=255
t7=0
t8=0
t9=255
t10=0
t11=0
t=((float*)(img_32FC3.data + img_32FC3.step.p[0] * i))[ch*j+k];
这里有个Mat.data
的Mat类成员,是指向图像数据的首地址,地址类型是uchar
。在上面个的例子中是img_32FC3
的首地址。
Mat.step.p[0]
代表图像每一行所占的字节数,而Mat.step.p[1]
和Mat.elemSize()
一样,表示image中每个点所占的字节数,对于img_32FC3
, img_32FC3.step.p[1]
=3*4
=12
,3
表示3
通道,4
表示float
有4
个字节,不过这里没用Mat.step.p[1]
.
img_32FC3.data + img_32FC3.step.p[0] * i)
表示第i+1
行的首地址,img_32FC3.data + img_32FC3.step.p[0] * i)
地址类型还是uchar
,而(float*)
表示强制转换,因为图像img_32FC3
是3通道的float
类型
[ch*j+k]
表示第j列第k(0,1,2)个通道的值。
也可以通过vec
的方式操作:
t=((Vec3f*)(img_32FC3.data + img_32FC3.step.p[0] * i))[j][0];
t=((Vec3f*)(img_32FC3.data + img_32FC3.step.p[0] * i))[j][1];
t=((Vec3f*)(img_32FC3.data + img_32FC3.step.p[0] * i))[j][2];
或者使用Mat.at
的方式,和vec
的方式等价
at操作要比指针的操作慢很多,所以对于不连续数据或者单个点处理,可以考虑at操作,对于连续的大量数据,不要使用它
img_32FC3.at<Vec3f>(i,j)[0]
img_32FC3.at<Vec3f>(i,j)[1]
img_32FC3.at<Vec3f>(i,j)[2]
如果数据类型是CV_8UC3
,Mat img_8UC3;
类似的:
//(i,j)表示行列
t=(img_8UC3.data + img_8UC3.step.p[0] * i)[ch*j+k]//k=0,1,2
t=((Vec3b*)(img_8UC3.data + img_8UC3.step.p[0] * i))[j][k];//k=0,1,2
t=img_8UC3.at<Vec3f>(i,j)[k];//k=0,1,2
数据类型参考:
- If matrix is of type `CV_8U` then use `Mat.at<uchar>(y,x)`.
- If matrix is of type `CV_8S` then use `Mat.at<schar>(y,x)`.
- If matrix is of type `CV_16U` then use `Mat.at<ushort>(y,x)`.
- If matrix is of type `CV_16S` then use `Mat.at<short>(y,x)`.
- If matrix is of type `CV_32S` then use `Mat.at<int>(y,x)`.
- If matrix is of type `CV_32F` then use `Mat.at<float>(y,x)`.
- If matrix is of type `CV_64F` then use `Mat.at<double>(y,x)`.
typedef Mat_<uchar> Mat1b;
typedef Mat_<Vec2b> Mat2b;
typedef Mat_<Vec3b> Mat3b;
typedef Mat_<Vec4b> Mat4b;
typedef Mat_<short> Mat1s;
typedef Mat_<Vec2s> Mat2s;
typedef Mat_<Vec3s> Mat3s;
typedef Mat_<Vec4s> Mat4s;
typedef Mat_<ushort> Mat1w;
typedef Mat_<Vec2w> Mat2w;
typedef Mat_<Vec3w> Mat3w;
typedef Mat_<Vec4w> Mat4w;
typedef Mat_<int> Mat1i;
typedef Mat_<Vec2i> Mat2i;
typedef Mat_<Vec3i> Mat3i;
typedef Mat_<Vec4i> Mat4i;
typedef Mat_<float> Mat1f;
typedef Mat_<Vec2f> Mat2f;
typedef Mat_<Vec3f> Mat3f;
typedef Mat_<Vec4f> Mat4f;
typedef Mat_<double> Mat1d;
typedef Mat_<Vec2d> Mat2d;
typedef Mat_<Vec3d> Mat3d;
typedef Mat_<Vec4d> Mat4d;