opencv之访问图像像素的 三种方法

访问像素的三种方法

①指针访问:最快

②迭代器iterator:较慢,非常安全,指针访问可能出现越界问题

③动态地址计算:更慢,通过at()实现。适用于访问具体某个第i行,j列的像素,而不适用遍历像素

 

Mat在内存中存储形式

  灰度图的存储形式

    

 

  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;
        }
    }
}

4. 测试代码

#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;
        }
    }
}

原文链接:http://www.cnblogs.com/kuotian/p/6389260.html?utm_source=itdadao&utm_medium=referral

首次接触图像处理,通过次来记录自己的学习记录,以方便回忆。 //指针访问像素 void colorReduce(Mat& temImage, int div) { //行数 int rowNumber = temImage.rows; cout << "图像通道数:" << temImage.channels() << endl; //列数*通道数=每一行的元素个数 int colNumber = temImage.cols * temImage.channels(); for (int row = 0; row < rowNumber;row++) { uchar* data = temImage.ptr<uchar>(row); for (int col = 0; col < colNumber;col++) { data[col] = data[col] / div*div + div / 2; } } } //迭代器iterator操作像素 void iterColorReduce(Mat& temImage,int div) { Mat_<Vec3b>::iterator it = temImage.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = temImage.end<Vec3b>(); //存取彩色图像像素 while (it != itend) { //开始处理每个像素 (*it)[0] = (*it)[0] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; (*it)[2] = (*it)[2] / div*div + div / 2; ++it; } } //动态地址计算像素 void atColorReduce(Mat& temImage, int div) { int rowNumber = temImage.rows; int colNumber = temImage.cols; //存取彩色图像 for (int row = 0; row < rowNumber; row++) { for (int col = 0; col < colNumber; col++) { //开始处理每个图像 //蓝色通道 temImage.at<Vec3b>(row, col)[0] = temImage.at<Vec3b>(row, col)[0] / div*div + div / 2; //绿色通道 temImage.at<Vec3b>(row, col)[1] = temImage.at<Vec3b>(row, col)[1] / div*div + div / 2; //红色通道 temImage.at<Vec3b>(row, col)[2] = temImage.at<Vec3b>(row, col)[2] / div*div + div / 2; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值