訪問像素的三種方法
①指針訪問:最快
②迭代器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