任何图像处理算法,都是从操作图像中的每个像素开始的。
图像的存储:
1.单通道图像
2.多通道图像
-
【方法1】指针访问像素:
访问速度最快
-
用指针访问像素是C语言中操作符[ ]。
图像中每行像素的个数:每行像素数=列数 X 通道数
Mat类提供了ptr函数可得到图像任意行的首地址。
// 获取i行的首地址
uchar *data = image.ptr<uchar>(i);
//--------------【colorReduce()函数】---------------//
// Description:通过指针实现颜色空间缩减函数
//-------------------------------------------------
void colorReduce(Mat &srcImg, Mat &dstImg, int div)
{
// 设置参数
dstImg = srcImg.clone(); // 设置目标图像与源图像一样
int rowNum = dstImg.rows; // 行数
int colNum = dstImg.cols * dstImg.channels(); // 每行像素数 = 列数 x 通道数
// 双重循环,遍历所有的像素值
for (int i = 0; i < rowNum; i++) // 行循环
{
uchar *data = dstImg.ptr<uchar>(i); // 获取第i行的首地址
for (int j = 0; j < colNum; j++) // 列循环
{
// 开始处理每个像素
data[j] = data[j] / div * div + div / 2;
} // 处理完一行,进行下一行像素处理
}
}
- 【方法2】 迭代器操作像素
-
在迭代法中,我们只需获取图像矩阵的begin和end,然后增加迭代直至从begin到end。将*操作符添加在迭代指针前,即可访问当前指向的内容。
相比用指针直接访问像素可能出现越界问题,迭代器绝对是非常安全的方法。
该方法与STL库的用法类似
//--------------【colorReduce()函数】---------------//
// Description:通过迭代器实现颜色空间缩减函数
//-------------------------------------------------
void colorReduce(Mat &srcImg, Mat &dstImg, int div)
{
// 设置参数
dstImg = srcImg.clone(); // 设置目标图像与源图像一样
// 获取迭代器
Mat_<Vec3b>::iterator it = dstImg.begin<Vec3b>(); // 初始位置的迭代器
Mat_<Vec3b>::iterator itEnd = dstImg.end<Vec3b>(); // 终止位置的迭代器
// 存取彩色图像像素
for (; it != itEnd; it++) // 行循环
{
// 开始处理每个像素
(*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)[0]代表蓝色通道像素值,(*it)[1]代表绿色通道像素值,(*it)[2]代表红色通道像素值。在OpenCV中,RGB存储是顺序是BGR
- 【方法3】 动态地址访问
- 该方法较直观,但耗时最长。
//--------------【colorReduce()函数】---------------//
// Description:通过动态地址实现颜色空间缩减函数
//-------------------------------------------------
void colorReduce(Mat &srcImg, Mat &dstImg, int div)
{
// 设置参数
dstImg = srcImg.clone(); // 设置目标图像与源图像一样
int rowNum = dstImg.rows; // 行数
int colNum = dstImg.cols ; // 列数
// 存取彩色图像像素
for (int i = 0; i < rowNum; i++) // 行循环
{
for (int j = 0; j < colNum; j++) // 列循环
{
// 开始处理每个像素
dstImg.at<Vec3b>(i,j)[0] = dstImg.at<Vec3b>(i,j)[0] / div * div + div / 2; // 蓝色通道
dstImg.at<Vec3b>(i,j)[1] = dstImg.at<Vec3b>(i,j)[1] / div * div + div / 2; // 绿色通道
dstImg.at<Vec3b>(i,j)[2] = dstImg.at<Vec3b>(i,j)[2] / div * div + div / 2; // 红色通道
} // 处理完
}
}
Mat 类中的cols和rows给出了图像的宽和高。而成员函数at(int y, int x)可用来存取图像元素,但必须在编译期知道图像的数据类型。
在OpenCV将彩色图像的类型的向量定义为Vec3b,即由三个unsigned char 组成的向量。
image.at<Vec3b>(i, j)[channel] = value;
【摘引:】
- 《OpenCV3编程入门》
- https://www.cnblogs.com/skyfsm/p/7082914.html