#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
//******1.扫描图像——指针访问******//
//减色函数,image为源图像,div为减色因子,最终的颜色总数由256*256*256减少到(256/div)*(256/div)*(256/div)种。
//v1.0 :对输入图像就地转换,直接对输入图像进行修改,好处:减少内存的使用。
void colorReduce1(cv::Mat image, int div)
{
int nr = image.rows;
//每行的元素数量
int nc = image.cols* image.channels();
//在彩色图像中,图像数据缓存区的前3个字节表示左上角像素的三通道(BGR),接下来的3个字节表示第一行第2个像素的三通道,以此类推。
for (int j = 0; j < nr; j++)
{
//取得行j的地址,ptr函数可以得到图像中某一行的首地址。
uchar *data = image.ptr<uchar>(j);
for (int i = 0; i < nc; i++)
{
//处理每个像素
data[i] = (data[i] / div)*div + div / 2;//将区间[0,256]划分为(256/div)个子区间,每个子区间中的像素值在新图像(减色后)中都转变为该子区间的中间值。
//也可直接用指针运算,与上一行代码等价
//*data = (*data/div)*div + div/2;data++;
}
}
}
//v2.0 :有时候不希望对原始图像进行修改,有时候需要修改。因此我们定义一个可供用户选择是否就地处理的函数
void colorReduce2(const cv::Mat &image, cv::Mat &result, int div)
{
result.create(image.rows, image.cols, image.type());
int nr = image.rows;
//每行的元素数量
int nc = image.cols* image.channels();
for (int j = 0; j < nr; j++)
{
//获得的输入图像和输出图像第j行的地址
const uchar *dataIn = image.ptr<uchar>(j);
uchar *dataOut = result.ptr<uchar>(j);
for (int i = 0; i < nc; i++)
{
dataOut[i] = (dataIn[i] / div)*div + div / 2;
}
}
}
//******2.扫描图像——运用迭代器******//
void colorReduce3(cv::Mat image, int div)
{
//在初始位置获得迭代器
cv::MatIterator_<cv::Vec3b> itBegin = image.begin<cv::Vec3b>();
//获得结束位置
cv::MatIterator_<cv::Vec3b> itEnd = image.end<cv::Vec3b>();
while (itBegin != itEnd)
{
(*itBegin)[0] = (*itBegin)[0] / div*div + div / 2;
(*itBegin)[1] = (*itBegin)[1] / div*div + div / 2;
(*itBegin)[2] = (*itBegin)[2] / div*div + div / 2;
itBegin++;
}
}
int main()
{
//读取图像
cv::Mat image = cv::imread("Z:\\openCV_test\\t1\\Lisar.jpg");
if (!image.data)
return -1;
//******V1.0减色******//
/*
colorReduce1(image, 64);
cv::imshow("减色后图像", image);
*/
//******V2.0减色******//
/*
//1> 就地处理
//colorReduce2(image, image, 64);
cv::imshow("减色后图像", image);
//2> 不就地处理
cv::Mat result;//先创建一个目标图像
colorReduce2(image, result, 64);
cv::imshow("减色后源图", image);
cv::imshow("减色后目标图像", result);
*/
//******V3.0减色******//
colorReduce3(image, 64);
cv::imshow("减色后图像", image);
cv::waitKey(0);
return 0;
}