【OpenCV】访问图像中像素的三种方法

版权声明:最终版权归YBAidam所有 https://blog.csdn.net/Aidam_Bo/article/details/89088792

访问像素的三种方法

  1. 指针访问:最快
  2. 迭代器iterator:较慢,非常安全,指针访问可能出现越界问题
  3. 动态地址计算:更慢,通过at()实现。适用于访问具体某个第i行,j列的像素,而不适用遍历像素

这里可以参考毛星云的OpenCV入门编程中的这三种方法的访问时间

https://download.csdn.net/download/aidam_bo/11097032

Mat在内存中存储形式

  灰度图的存储形式

    

灰度图的存储形式

  RGB的存储形式

  

RGB的存储形式

一般情况下,Mat是连续存储的,按行连接。可以通过isContinuous()函数,判断矩阵是否连续存储,若连续返回true。

访问像素的三种方法

1.指针访问

void VisitImgByPointer(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    int rows = dstImg.rows;
    int cols = dstImg.cols * dstImg.channels();

    for(int i = 0; i < rows; i++)
    {
        uchar* data = dstImg.ptr<uchar>(i);
        for(int j = 0; j < cols; j++)
        {
            data[j] = 0;  //处理每一个像素
            //add code
        }
    } 
}

当Mat按行连续存储时,可以用指针直接访问所有数据。

void VisitContinueImgByPointer(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    int rows = dstImg.rows;
    int cols = dstImg.cols;
    int channels = dstImg.channels();

    if(dstImg.isContinuous())
    {
        cols *= rows;
        rows = 1;
        //cout << "is continuous " << endl;
    }

    for(int i = 0; i < rows; i++)
    {
        uchar* data = dstImg.ptr<uchar>(i);
        for(int j = 0; j < cols * channels; j++)
        {
            data[j] = 155;  //处理每一个像素
            //add code
        }
    } 
    //若存储连续,等效于以下代码
    //uchar* data = dstImg.data;
    //for(int i = 0; i < cols * rows * channels; i++)
    //    data[i] = 155;    //处理每一个像素

}

2.迭代器访问

void VisitImgByIterator(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    const int channels = dstImg.channels();
  
    switch(channels)
    {
    case 1:
        {
            Mat_<uchar>::iterator it= dstImg.begin<uchar>();
            Mat_<uchar>::iterator itend= dstImg.end<uchar>();
            for ( ; it!= itend; it++) //处理每一个像素
            {
                *it = 150;
            }
            break;
        }
    case 3:
        {
            Mat_<Vec3b>::iterator it3= dstImg.begin<Vec3b>();
            Mat_<Vec3b>::iterator itend3= dstImg.end<Vec3b>();
            for ( ; it3!= itend3; it3++) //处理每一个像素
            { 
                (*it3)[0]= 255;
                (*it3)[1]= 0;
                (*it3)[2]= 0;
            }
            break;
        }
    }
}

3.动态地址访问

void VisitImgByAt(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    int rows = dstImg.rows;
    int cols = dstImg.cols;
    int channels = dstImg.channels();

    switch(channels)
    {
    case 1:
        {
            for(int i = 0; i < rows; i++)
                for(int j = 0; j < cols; j++)
                    dstImg.at<uchar>(i,j) = 150;
            break;
        }
    case 3:
        {
            for(int i = 0; i < rows; i++)
                for(int j = 0; j < cols; j++)
                {
                    dstImg.at<Vec3b>(i,j)[0] =  0;
                    dstImg.at<Vec3b>(i,j)[1] =  0;
                    dstImg.at<Vec3b>(i,j)[2] = 255;
                }
            break;
        }
    }
}

测试代码-总

#include <iostream>
#include <opencv2/opencv.hpp>  
using namespace cv;
using namespace std;

void VisitImgByPointer(Mat &inputImg, Mat &dstImg);
void VisitContinueImgByPointer(Mat &inputImg, Mat &dstImg);
void VisitImgByIterator(Mat &inputImg, Mat &dstImg);
void VisitImgByAt(Mat &inputImg, Mat &dstImg);

int main()
{
    Mat srcImg = imread("pig.png"), dstImg;
    Mat grayImg;
    cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    //VisitImgByPointer(srcImg,dstImg);
    //VisitContinueImgByPointer(grayImg,dstImg);
    
    //VisitImgByIterator(srcImg,dstImg);
    //VisitImgByIterator(grayImg,dstImg);
    
    //VisitImgByAt(srcImg,dstImg);
    VisitImgByAt(grayImg,dstImg);

    //imshow("原始图", srcImg);
    //imshow("灰度图", grayImg);
    imshow("生成图", dstImg);

    waitKey(0);
    return 0;
}

void VisitImgByPointer(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    int rows = dstImg.rows;
    int cols = dstImg.cols * dstImg.channels();

    for(int i = 0; i < rows; i++)
    {
        uchar* data = dstImg.ptr<uchar>(i);
        for(int j = 0; j < cols; j++)
        {
            data[j] = 0;  //处理每一个像素
            //add code
        }
    } 
}

void VisitContinueImgByPointer(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    int rows = dstImg.rows;
    int cols = dstImg.cols;
    int channels = dstImg.channels();

    if(dstImg.isContinuous())
    {
        cols *= rows;
        rows = 1;
        //cout << "is continuous " << endl;
    }

    for(int i = 0; i < rows; i++)
    {
        uchar* data = dstImg.ptr<uchar>(i);
        for(int j = 0; j < cols * channels; j++)
        {
            data[j] = 155;  //处理每一个像素
            //add code
        }
    } 
    //若存储连续,等效于一下代码
    //uchar* data = dstImg.data;
    //for(int i = 0; i < cols * rows * channels; i++)
    //    data[i] = 155;    //处理每一个像素

}


void VisitImgByIterator(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    const int channels = dstImg.channels();
  
    switch(channels)
    {
    case 1:
        {
            Mat_<uchar>::iterator it= dstImg.begin<uchar>();
            Mat_<uchar>::iterator itend= dstImg.end<uchar>();
            for ( ; it!= itend; it++) //处理每一个像素
            {
                *it = 150;
            }
            break;
        }
    case 3:
        {
            Mat_<Vec3b>::iterator it3= dstImg.begin<Vec3b>();
            Mat_<Vec3b>::iterator itend3= dstImg.end<Vec3b>();
            for ( ; it3!= itend3; it3++) //处理每一个像素
            { 
                (*it3)[0]= 255;
                (*it3)[1]= 0;
                (*it3)[2]= 0;
            }
            break;
        }
    }
}

void VisitImgByAt(Mat &inputImg, Mat &dstImg)
{
    dstImg = inputImg.clone();
    int rows = dstImg.rows;
    int cols = dstImg.cols;
    int channels = dstImg.channels();

    switch(channels)
    {
    case 1:
        {
            for(int i = 0; i < rows; i++)
                for(int j = 0; j < cols; j++)
                    dstImg.at<uchar>(i,j) = 150;
            break;
        }
    case 3:
        {
            for(int i = 0; i < rows; i++)
                for(int j = 0; j < cols; j++)
                {
                    dstImg.at<Vec3b>(i,j)[0] =  0;
                    dstImg.at<Vec3b>(i,j)[1] =  0;
                    dstImg.at<Vec3b>(i,j)[2] = 255;
                }
            break;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Aidam_Bo/article/details/89088792
今日推荐