该文章参考毛星云著《OpenCV3编程入门》,电子工业出版社。
图像是以像素为单位储存的,访问图像中的每个像素是处理图像的基础,一般有三种访问图像像素的方法:
方法一:指针访问:C操作符[ ]
方法二:迭代器iterator
方法三:动态地址计算
下面直接上代码,代码的目的是减少图像的颜色种类数,即减少颜色的细分。
- #include<opencv2/opencv.hpp>
- #include<iostream>
- using namespace cv;
- using namespace std;
- void colorreduce(Mat& inputImage, Mat& outputImage, int div);
- int main()
- {
- Mat srcimage = imread("1.jpg");
- imshow("srcimage", srcimage);
- Mat dstimage;
- dstimage.create(srcimage.rows, srcimage.cols, srcimage.type());
- double time0 = static_cast<double>(getTickCount());
- colorreduce(srcimage, dstimage, 32);
- time0 = ((double)getTickCount() - time0) / getTickFrequency();
- cout << "Time = " << time0 << "seconds" << endl;
- imshow("dstimage", dstimage);
- waitKey(0);
- }
- void colorreduce(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); //获取行地址
- for (int j = 0; j < colNumber; j++)
- {
- data[j] = data[j] / div*div + div / 2;
- }
- //*data++ = *data / div*div + div / 2; //所有方法中最快的
- }
- /*
- //方法二:迭代器
- 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 + div / 2;
- (*it)[1] = (*it)[1] / div*div + div / 2;
- (*it)[2] = (*it)[2] / div*div + div / 2;
- }
- */
- /*
- //方法三:动态地址计算
- 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 + div / 2;
- outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div*div + div / 2;
- outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div*div + div / 2;
- }
- }
- */
- }
程序运行的效果如下:
从结果上看,减小颜色种类后,图像变得更模糊了。
在程序中,需要注意的是colorreduce函数的形参是Mat&,而不是Mat,这是C++的知识,因为需要传入函数的图片在主函数中也发生变化,即函数外部的数据随函数内部的操作而变化。