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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章