OpenCV学习C++接口 Mat像素遍历详解

    IplImage像素遍历和Mat之间的转换请看下一篇博文,

学习总结:

  

  1. 当Mat为多通道时,如3通道,如果我们将其内容输出到终端,则可以看出其列数为Mat::colsn倍,意思是说显示数据的时候r、g、b安顺输出,然后输出下一个像素的r、g、b,当然nMat的通道数。虽是如此,但是Mat::cols的数值并没有随之改变。
  2. 当复制一副图像时,利用函数cv::Mat::clone(),则将在内存中重新开辟一段新的内存存放复制的图像(图像数据也将全部复制),而如果利用cv::Mat::copyTo()复制图像,则不会在内存中开辟一段新的内存块,同时也不会复制图像数据,复制前后的图像的指针指向同一个内存块。使用的时候需注意两个函数的区别。
  3. 因为自从openCv可以用c++方式实现之后,我们可以使用迭代器和at的方式方式遍历像素,不过at几乎是所有方式中效率最低的一种,iterator的方式比使用at的方式好一点,这种方式比较安全和简单易懂明了。
  4. 在openCv 2计算机视觉一书中降到的像素压缩:利用位操作的算法效率最高,其次是利用整数除法中向下取整,效率最低的是取模运算。
代码如下,可以仔细研究一下和分析一下:
/***************************************************************
*
*    内容摘要:本例采用8种方法对图像Mat的像素进行扫描,并对像素点的像
*            素进行压缩,压缩间隔为div=64,并比较扫描及压缩的效率,效
*            率最高的是采用.ptr及减少循环次数来遍历图像,并采用位操
*            作来对图像像素进行压缩。
*   参考资料:《OpenCV 2 computer Vision Application Programming
*              cookbook》
*
***************************************************************/
#include 
#include 
#include 
#include 


//利用.ptr和数组下标进行图像像素遍历
void colorReduce0(cv::Mat &image, int div = 64)
{
    int nl = image.rows;
    int nc = image.cols * image.channels();
    
    //遍历图像的每个像素
    for(int j=0; j(j);
        for(int i=0; i(j);
        for(int i=0; i(j);
        for(int i=0; i(log(static_cast(div))/log(2.0));   //div=64, n=6
    uchar mask = 0xFF<(j);
        for(int i=0; i(j);
        uchar *data_out = result.ptr(j);
        for(int i=0; i(j);
        for(int i=0; i::iterator it = image.begin();    //由于利用图像迭代器处理图像像素,因此返回类型必须在编译时知道
    cv::Mat_::iterator itend = image.end();

    for(;it != itend; ++it)
    {
        (*it)[0] = (*it)[0]/div*div+div/2;        //利用operator[]处理每个通道的像素
        (*it)[1] = (*it)[1]/div*div+div/2;
        (*it)[2] = (*it)[2]/div*div+div/2;
    }
}

//利用.at(j,i)进行图像像素遍历
void colorReduce7(cv::Mat &image, int div = 64)
{
    int nl = image.rows;
    int nc = image.cols;
    
    //遍历图像的每个像素
    for(int j=0; j(j,i)[0] = image.at(j,i)[0]/div*div + div/2;
            image.at(j,i)[1] = image.at(j,i)[1]/div*div + div/2;
            image.at(j,i)[2] = image.at(j,i)[2]/div*div + div/2;
        }
    }
}

//减少循环次数,进行图像像素遍历,调用函数较少,效率最高。
void colorReduce8(cv::Mat &image, int div = 64)
{
    int nl = image.rows;
    int nc = image.cols;

    //判断是否是连续图像,即是否有像素填充
    if(image.isContinuous())
    {
        nc = nc*nl;
        nl = 1;
    }

    int n = static_cast(log(static_cast(div))/log(2.0));
    uchar mask = 0xFF<(j);
        for(int i=0; i


你可能感兴趣的:(opencv进化之旅)