灰度图在内存中的存储形式
3通道图在内存中的存储形式
1. 通过 .at<typename>(i,j) 遍历
void colorReduce(Mat& image,int div)
{
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
image.at<Vec3b>(i,j)[0]=image.at<Vec3b>(i,j)[0]/div*div+div/2;
image.at<Vec3b>(i,j)[1]=image.at<Vec3b>(i,j)[1]/div*div+div/2;
image.at<Vec3b>(i,j)[2]=image.at<Vec3b>(i,j)[2]/div*div+div/2;
}
}
}
image.at<uchar>(i,j):取出灰度图像中i行j列的点。
image.at<Vec3b>(i,j)[k]:取出彩色图像中i行j列第k通道的颜色点,k=[0,1,2],分别代表B,G,R。
uchar,Vec3b都是图像像素值的类型,在core里它是通过typedef Vec<T,N>来定义的,N代表元素的个数,T代表类型。
OpenCV定义了一个Mat的模板子类为Mat_,它重载了operator()让我们可以更方便的取图像上的点。
Mat m2(300, 500, CV_8UC3, Scalar(0, 0, 0));
Mat_<Vec3b> im = m2;
for (int i = 0; i < im.rows; i++) {
for (int j = 0; j < im.cols; j++) {
im(i, j)[0] = im(i, j)[0] + (uchar) (255 / 2);
im(i, j)[1] = im(i, j)[1] + (uchar) 0;
im(i, j)[2] = im(i, j)[2] + (uchar) (111 / 2);
}
}
2. 通过行指针 .ptr<uchar>(k)来遍历
void colorReduce(const Mat& image,Mat& outImage,int div)
{
// 创建与原图像等尺寸的图像
outImage.create(image.size(),image.type());
int nr=image.rows;
// 将3通道转换为1通道
int nl=image.cols*image.channels();
for(int k=0;k<nr;k++)
{
// 每一行图像的指针
const uchar* inData=image.ptr<uchar>(k);
uchar* outData=outImage.ptr<uchar>(k);
for(int i=0;i<nl;i++)
{
outData[i]=inData[i]/div*div+div/2;
}
}
}
3. 通过迭代器Mat_iterator来遍历
void colorReduce(const Mat& image,Mat& outImage,int div)
{
outImage.create(image.size(),image.type());
// 获得迭代器
MatConstIterator_<Vec3b> it_in=image.begin<Vec3b>();
MatConstIterator_<Vec3b> itend_in=image.end<Vec3b>();
MatIterator_<Vec3b> it_out=outImage.begin<Vec3b>();
MatIterator_<Vec3b> itend_out=outImage.end<Vec3b>();
while(it_in!=itend_in)
{
(*it_out)[0]=(*it_in)[0]/div*div+div/2;
(*it_out)[1]=(*it_in)[1]/div*div+div/2;
(*it_out)[2]=(*it_in)[2]/div*div+div/2;
it_in++;
it_out++;
}
}