1、图像在内存之中的存储方式
图像矩阵的大小取决于所用的颜色模型,确切的说,取决于所用通道数。如果是灰度图像,矩阵就如图所示:
对于多通道来说,矩阵中的列会包含多个子列,其子列个数与通道数相等,如图RGB颜色模型的矩阵:
可以看到,OpenCV中子列的通道顺序是反过来的-----BGR 而不是 RGB。
2、颜色空间缩减
如果矩阵元素存储的是单通道像素,使用C或者C++的无符号字符类型,像素可有256个不同值。
如果是三通道图像,这种存储格式的颜色数就太多了。256 * 256 * 256个不同颜色值
3、计时函数
4、访问图像中像素的三类方法
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;
//方法一,用指针访问像素
void colorReduce1(Mat& inputImage, Mat& outputImage, int div);
//方法二,用迭代器操作像素
void colorReduce2(Mat& inputImage, Mat& outputImage, int div);
//方法三,动态地址计算
void colorReduce3(Mat& inputImage, Mat& outputImage, int div);
int main(int argc, char** argv)
{
//1.创建原始图并显示
Mat srcImage = imread("erha.jpg");
imshow("name1", srcImage);
//2.按原始图的参数规格来创建效果图
Mat dstImage1, dstImage2, dstImage3;
dstImage1.create(srcImage.rows, srcImage.cols, srcImage.type());//大小类型和原图片相同
//3.记录起始时间
double time0 = static_cast<double>(getTickCount());
//4.调用颜色控件缩减函数
colorReduce1(srcImage, dstImage1, 20);
colorReduce2(srcImage, dstImage2, 40);
colorReduce3(srcImage, dstImage3, 60);
//5.计算运行时间并输出
time0 = (double(getTickCount()) - time0) / getTickFrequency();
cout << "此方法运行时间为: " << time0 << " 秒" << endl;
//6.显示效果图
imshow("效果图1", dstImage1);
imshow("效果图2", dstImage2);
imshow("效果图3", dstImage3);
waitKey(0);
return 0;
}
void colorReduce1(Mat& inputImage, Mat& outputImage, int div) {
//参数准备
outputImage = inputImage.clone(); //复制实参到临时变量
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols * outputImage.channels();//列数 * 通道数 = 每一行元素的个数
//双重循环,遍历所有像素值
for (int i = 0; i < rowNumber; i++)
{
uchar* data = outputImage.ptr<uchar>(i);//获取第i行的首地址
for (int j = 0; j < colNumber; j++) {
//处理每个像素
data[j] = data[j] / div * div;
}
}
}
void colorReduce2(Mat& inputImage, Mat& outputImage, int div) {
outputImage = inputImage.clone();
Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();//初始位置的迭代器
Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();//终止位置的迭代器
//存取彩色图像像素
for (; it != itend; ++it)
{
//开始处理每个像素
(*it)[0] = (*it)[0] / div * div;
(*it)[1] = (*it)[1] / div * div;
(*it)[2] = (*it)[2] / div * div;
}
}
void colorReduce3(Mat& inputImage, Mat& outputImage, int div) {
outputImage = inputImage.clone();
int rowNumber = outputImage.rows; // 行数
int colNumber = outputImage.cols; //列数
//存取彩色图像像素
for (int i = 0; i < rowNumber; i++)
{
for (int j = 0; j < colNumber; j++) {
//开始处理每个像素
outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div * div; //蓝色通道
outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div * div; //绿色通道
outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div * div; //红色通道
}
}
}