访问像素的三种方法
①指针访问:最快
②迭代器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