OpenCv003-指针遍历图像

把问题基本都记录在程序的注释中了,主要是掌握如何使用指针来遍历图像,以及如何压缩颜色空间。 

/*使用指针遍历图像
先说一下这个遍历嘛意思,蠢笨的我以为是好多图片,然后搞一遍呢 哈哈  
其实就是遍历一张图片中所有的像素点  高效的遍历及其重要,暂时先不管高效,先学会遍历,下面学习指针的办法来遍历图像
*/
#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

*/

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首次接触图像处理,通过次来记录自己的学习记录,以方便回忆。 //指针访问像素 void colorReduce(Mat& temImage, int div) { //行数 int rowNumber = temImage.rows; cout << "图像通道数:" << temImage.channels() << endl; //列数*通道数=每一行的元素个数 int colNumber = temImage.cols * temImage.channels(); for (int row = 0; row < rowNumber;row++) { uchar* data = temImage.ptr<uchar>(row); for (int col = 0; col < colNumber;col++) { data[col] = data[col] / div*div + div / 2; } } } //迭代器iterator操作像素 void iterColorReduce(Mat& temImage,int div) { Mat_<Vec3b>::iterator it = temImage.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = temImage.end<Vec3b>(); //存取彩色图像的像素 while (it != itend) { //开始处理每个像素 (*it)[0] = (*it)[0] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; (*it)[2] = (*it)[2] / div*div + div / 2; ++it; } } //动态地址计算像素 void atColorReduce(Mat& temImage, int div) { int rowNumber = temImage.rows; int colNumber = temImage.cols; //存取彩色图像 for (int row = 0; row < rowNumber; row++) { for (int col = 0; col < colNumber; col++) { //开始处理每个图像 //蓝色通道 temImage.at<Vec3b>(row, col)[0] = temImage.at<Vec3b>(row, col)[0] / div*div + div / 2; //绿色通道 temImage.at<Vec3b>(row, col)[1] = temImage.at<Vec3b>(row, col)[1] / div*div + div / 2; //红色通道 temImage.at<Vec3b>(row, col)[2] = temImage.at<Vec3b>(row, col)[2] / div*div + div / 2; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值