引言

opencv是计算机视觉中使用最广泛同时也是功能最全的一个开源库,为图像处理以及计算机视觉工作者提供了极大的方便,本文就opencv读取图像数据文件做一个总结,高年级同学以及大牛请无视。

opencv中图像的结构

图像的结构可以看作是一个2维矩阵,opencv在对图像的结构定义中也采用了这一方式。在总结之前,有必要对opencv中图像结构定义的一些成员变量意义进行说明,更详细的请参考opencv官方文档。
nChannels:图像通道数,可取1、2、3、4;
widthStep:可理解成相邻行,同列数据之间的字节数,为了高速的处理效率,图像在存储时会进行填充,保证每行是一个固定字节数,且通常维4的倍数;
width:图像宽;
height:图像高;

数据读取

1.点读取

// 单通道
uchar value = grayim.at<uchar>(i,j);
for( int i = 0; i < grayim.rows; ++i)
    for( int j = 0; j < grayim.cols; ++j )
        grayim.at<uchar>(i,j) = (i+j)%255;


//3通道 Vec3b可看作一个结构体,包含三个元素,分别对应彩色图像的B\G\R,且只能对8U的数据类型使用,如果是float数据的值,可以用Vec3f

for( int i = 0; i < colorim.rows; ++i)
    for( int j = 0; j < colorim.cols; ++j )
    {
        Vec3b pixel;
        pixel[0] = i%255; //Blue
        pixel[1] = j%255; //Green
        pixel[2] = 0; //Red
        colorim.at<Vec3b>(i,j) = pixel;
}

2.图像迭代器

// 单通道
cv::MatIterator_<uchar> grayit, grayend;
for( grayit = grayim.begin<uchar>(), grayend =
grayim.end<uchar>(); grayit != grayend; ++grayit)
    *grayit = rand()%255;

//3通道
cv::MatIterator_<Vec3b> colorit, colorend;
for( colorit = colorim.begin<Vec3b>(), colorend = colorim.end<Vec3b>(); colorit!=colorend; colorit++)
{
    (*colorit)[0]=rand()%255; //B
    (*colorit)[1]=rand()%255; //G
    (*colorit)[2]=rand()%255; //R
}

3.指针读取

for( int i = 0; i < grayim.rows; ++i)
{
    //获取第 i 行首像素指针
    uchar * p = grayim.ptr<uchar>(i);
    //对第 i 行的每个像素(byte)操作
    for( int j = 0; j < grayim.cols; ++j )
    p[j] = (i+j)%255;
}

4.按结构读取

这里写图片描述

addr(Mi0,i1,…im-1) = M.data + M.step[0] * i0 + M.step[1] * i1 + … +
M.step[m-1] * im-1 (其中 m = M.dims M的维度)

扩展到3维
这里写图片描述

单通道:
这里写图片描述

3通道:
这里写图片描述

5.Mat_读取

考虑下面一段代码:

// 由于数据类型转换,最后的像素值会发生改变
Mat M(600, 800, CV_8UC1);
for( int i = 0; i < M.rows; ++i)
{
    uchar * p = M.ptr<uchar>(i);
    for( int j = 0; j < M.cols; ++j )
    {
        double d1 = (double) ((i+j)%255);
        M.at<uchar>(i,j) = d1;
        double d2 = M.at<double>(i,j);
    }
}

如果采用Mat_模板类则可以避免这种情况:

Mat_<uchar> M1 = (Mat_<uchar>&)M; // 内存地址共享
for( int i = 0; i < M1.rows; ++i)
{
    uchar * p = M1.ptr(i);
    for( int j = 0; j < M1.cols; ++j )
    {
        double d1 = (double) ((i+j)%255);
        M1(i,j) = d1;
        double d2 = M1(i,j);
    }
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐