把问题基本都记录在程序的注释中了,主要是掌握如何使用指针来遍历图像,以及如何压缩颜色空间。
/*使用指针遍历图像
先说一下这个遍历嘛意思,蠢笨的我以为是好多图片,然后搞一遍呢 哈哈
其实就是遍历一张图片中所有的像素点 高效的遍历及其重要,暂时先不管高效,先学会遍历,下面学习指针的办法来遍历图像
*/
#include <opencv.hpp>
#include <windows.h>
using namespace std;
using namespace cv;
void colorReduce(Mat &image, int div = 64)
{
int n1 = image.rows; //行数
int nc = image.cols * image.channels();//计算一行多少个元素
for (int j = 0; j < n1; j++)
{
uchar * data = image.ptr<uchar>(j);//获取第j行的地址
for (int i = 0; i < nc; i++)
{
data[i] = data[i] / div *div + div / 2;
}
}
}
int main()
{
Mat image;
image = imread("C:\\Users\\Administrator\\Pictures\\test1.jpg");
DWORD Start_time = GetTickCount();
colorReduce(image,10);
DWORD End_time = GetTickCount();
cout << End_time << endl;
cout << "指针遍历图像时间:" << End_time - Start_time << endl;
namedWindow("指针遍历的图像");
imshow("指针遍历的图像",image);
waitKey(0);
return 0;
}
/*知识注释
1:uchar * data = image.ptr<uchar>(j);//获取第j行的地址
for (int i = 9; i < nc; i++)
{
data[i] = data[i] / div *div + div / 2;
}
这段非常典型的代码,经过一番查抄,基本查出了里面所有疑问的知识点,现在记录下来;
问题1:ptr就是image对象的一个函数哈,<uchar> 说明类型
问题2:data作为一个指针变量,我把一行理解成一个一维数组,这样说似乎又不太恰当,这一行里面的每一个元素不是又有三个数组组合而成吗,这不成二维的啦!a哎呀不管了,按照程序中的写法,就是一个一维数组的姓氏,我们就把所有的数据当做顺序排列的吧,找到每一行的首地址,挨个访问元素就是了!
data作为指向数组的指针,可以写成data[i] 这种形式吗?不应该是* data吗?
在C语言中有这样的知识点,当一个指针指向数组的首地址的时候可以这样用!
当然也可以写成 *data++ = *data/div * div + div/2
问题3:data[i] = data[i] / div *div + div / 2;这个表达式什么意思,为什么 要加上一个div/2
这个表达式的作用是用来降低颜色空间,或者我觉得用来降低颜色的种类。举个例子来说,一个彩色图像的像素点有三个通道,每一个像素点都是由RGB三种通道组合而成,
每种通道颜色程度的取值范围是0-255也就是256种颜色等级。所以可能的颜色数目达到了256 * 256 *256中,这个表达式就是用来对颜色种类进行降维处理;具体如下
假设每个颜色通道都/64 ,那么三个通道的颜色可能的数目就变成了 256/64 * 256/64 * 256/64种,此时颜色程度在0-63之间的经过这个表达式处理之后统一
都变成了32;可以想象一下,如果不加上后面的div/2 这个值0-63之间的值就全部变成了0;这样可能误差较大吧,取一个中间值可能更加均衡吧;
至于说那个到底压缩多少倍,这个我觉得需要根据个人的需要来决定,没有一个严格的界限。
问题4:如何获取遍历图像执行的时间?
GetTickcount函数:它返回从操作系统启动到当前所经过的毫秒数,常常用来判断某个方法执行的时间,其函数原型是DWORD GetTickCount(void),
返回值以32位的双字类型DWORD存储,因此可以存储的最大值是(2^32-1) ms约为49.71天,因此若系统运行时间超过49.71天时,这个数就会归0
*/