#include<opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void colorReduce(Mat &image, int div = 64)
{
int nl = image.rows;
int nc = image.cols;//;*image.channels();
if (image.isContinuous())
{
nc = nc *nl;
nl = 1;
}
/*因为 这里 少写了 一个log 找了一天的错误*/
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
uchar mask = 0xff << n;
for (int j = 0; j < nl; j++)
{
/*这里有一个 疑问 这里定义了一个指向 uchar数据类型的指针 那么指针本身data是几位呢 待会测试一下
还有就是这个data是这一行的首地址 */
/*非常 好奇 传进来 彩色和 灰色 地址都是一样的 并且是连续的 彩色的不是三通道吗 灰色的一个地址可以存取一个值
彩色的一个地址可以存下三个通道的值?
答案 是不能的 一个地址只能存放一个通道的值
RGB三个通道 是如何合成一个彩色的像素值呢
*/
uchar * data = image.ptr<uchar>(j);
for (int i = 0; i < nc; i++)
{
/*这里傻X了好长时间 在开始写列nc =image.cols 如果这样写 那么循环体内就得按照下面这种方式写
因为这样才能全部遍历图像 如果只写*data++ = *data & mask + div / 2;这一句 那么只能遍历三分之一的
图像 可以自己试着看一下 nc =image.cols*image.channels()就可以只写一句了
*/
*data++ = *data & mask + div / 2;
*data++ = *data & mask + div / 2;
*data++ = *data & mask + div / 2;
/*data[i] = data[i] & mask + div / 2;
data[i+1] = data[i+1] & mask + div / 2;
data[i+2] = data[i+2] & mask + div / 2;
data++;*/
}
}
}
int main()
{
Mat image;
image = imread("Test.jpg");
//(getTickCount())需要加上 括号
double Time1 = static_cast<double>(getTickCount());
colorReduce(image);
Time1 = static_cast<double>(getTickCount()) - Time1;
Time1 /= getTickFrequency();
cout << "运行时间:" << Time1 << endl;
namedWindow("高效遍历图像");
imshow("高效遍历图像", image);
waitKey(0);
return 0;
}
/*
1: *data++ ++和*的优先级相同 遵循自右向左执行的规则 等价于*(data++) 首先引用data的值 实现*data的运算 再使data+1
2:输出单个像素时 cout<<int(*data++); 要在前面加上 强制类型转换 否则输出乱码
3:了解记住 时间是怎么计算的 前一篇文章中 就是不理解 才出错
*/