Lecture 3 opencv2系列之遍历Mat

来源:互联网 发布:成都专业seo外包 编辑:程序博客网 时间:2024/06/05 05:13

阅读本节内容,建议先阅读Lecture 2 opencv2系列之初识Mat,了解图像像素数据在Mat中的存储方式。

《The OpenCV Tutorials》给出3种遍历Mat中图像像素矩阵的方法,分别是指针遍历(ptr)、迭代器(MatIterator)、
at函数,前两者亦分别称作高效方法、安全方法。其中最为高效的是指针方法。
本文只介绍指针方法。

以下代码实现对图像像素数据的遍历,我们打印图像的红色分量。

代码

#include <iostream>#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"using namespace std;using namespace cv;int main(int argc, const char *argv[]){    if (argc != 2)    {        cout<<"Number of Parameters is Wrong!"<<endl;        return -1;    }    Mat src = imread(argv[1],IMREAD_COLOR);    int channels = src.channels();    int nRows = src.rows;    //图像数据列需要考虑通道数的影响;    int nCols = src.cols * channels;        if (src.isContinuous())//连续存储的数据,按一行处理    {        nCols *= nRows;        nRows = 1;    }    int i,j;    uchar* p;    for( i = 0; i < nRows; ++i)    {        p = src.ptr<uchar>(i);        for ( j = 2; j < nCols; j+=3)//注意通道顺序为BGR,红色为第三个数据;        {            cout<<int(p[j])<<" ";           }        cout<<endl;    }    return 0;}

释义

  1. 如果只是单纯打印图像数据的话,可以直接用cout<<src来实现,OpenCV2重定义了<<运算符,实现
    了矩阵的格式化输出。
    详细内容参见The OpenCV Tutorials Release 2.4.9.0,p.148。
  2. 图像坐标系和像素矩阵。
    图像左上角作为原点,按行和列展开。故图像左上角像素对应矩阵的0行0列数据,这里列不计通道。
  3. OpenCV默认使用BGR的通道顺序。
  4. 行数据的填补。
    宽W高H的真彩色图像,像素数据存储需要WxHx3个uchar构成的内存块,但是出于效率考虑,每行可能
    会填补一些额外像素,亦即存储像素数据的宽度不一定是W,往往填补为4或8的倍数,因为这样一些多
    媒体处理芯片可以更高效的处理图像。
    图像的宽高分别由colsrows给出,行像素个数由cols*channels()给出,实际行的字节数由step[0]
    给出。对于有额外填补的行数据,cols!= step[0]/elemSize(),反之,cols==step[0]/elemSize()
    我们可以用成员函数isContinuous()判断图像是否对行进行了填补,对于没有进行填补的图像,我们视其
    像素数据为一个长为WxHxchannels()的一维数组,加快循环速度。
  5. 行首地址。
    Mat的成员函数ptr(int j)返回第j行的首地址。
  6. 如果仔细阅读过Lecture 2 opencv2系列之初识Mat,对于遍历Mat,自然想到用data+step+elemSize()
    实现,这也是基于指针的方法。
    核心循环代码为:
   int i,j;   uchar *p;   for (i = 0; i < nRows; i++)   {       p = src.<uchar>data + i * src.step[0];       for (j = 2; j < nCols; j += 3)       {                       cout<<int(p[j*src.elemSize1()])<<" ";//本例中,src.elemSize1()=1;故可简写为p[j]。       }   }

本质上是因为src.ptr(i) == src.data + i * src.step[0]
在《OpenCV2 计算机视觉编程手册》一书中,Laganiere不建议用这种方法,原因是:容易出错,并且不适用于带“感兴趣
区域”的图像。

参考文献

  1. The OpenCV Reference Manual Release 2.4.9.0。
  2. The OpenCV Tutorials Release 2.4.9.0。
  3. 加拿大, Laganiere, R., & 张静. OpenCV2 计算机视觉编程手册.
0 0
原创粉丝点击