opencv image 指针 像素

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)

pic

逐像素操作为:

#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表示float4个字节,不过这里没用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;
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值