ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

访问图像中的像素

2019-05-05 14:50:10  阅读:283  来源: 互联网

标签:Mat int 像素 访问 图像 div outputImage 函数


文章目录

摘要

  • 修改图片路径

颜色空间缩减

  • 其实,仅用这些颜色中具有代表性的很小的部分,就足以达到同样的效果。
  • 如此,颜色空间缩减(color space reduction)便可以派上用场了,它在很多应 "用中可以大大降低运算复杂度。
  • 颜色空间缩减的做法是:将现有颜色空间值除以某个输入值,以获得较少的颜色数。
  • 也就是“做减法”,比如颜色值0到9可取为新值0, 10到19可取为10,以此类推。

Inew=(Iold10)10 I_{new} = (\frac{I_{old}}{10}) * 10 Inew​=(10Iold​​)∗10

  • 在处理图像像素时,每个像素需要进行一遍上述计算,也需要一定的时间花销。但我们注意到其实只有0~255种像素,即只有256种情况。进一步可以把 256种计算好的结果提前存在表中table中,这样每种情况不需计算,直接从table中取结果即可。
  • 查表操作
int divideWith = 10;
uchar table[256];
for (int i= 0; i < 256; ++i)
    table[i] - divideWith * (i/divideWith);
  • 于是table[i]存放的是值为i的像素减小颜色空间的结果,这样也就可以理解上述方法中的操作:
p[j] = table[p[j]];
  • 这样,简单的颜色空间缩减算法就可由下面两步组成:
    1. 遍历图像矩阵的每一个像素
    2. 对像素应用上述公式。

LUT函数

  • Look up table 操作
  • 一个原型为**operationsOnArrays:LUT()<lut>**的函数来进行。它用于批量进行图像元素查找、扫描与操作图像。其使用方法如下:
//首先我们建立一个mat型用于查表
Mat lookUpTable(1, 256, CV_8U);
uchar * p = lookUpTable.data;
for( int i=0; i < 256; ++i)
    p[i] = table[i];
//然后我们调用函数(I是输入 J是输出):
for(int i =0; i < times; ++i)
    LUT (I, lookUpTable, J);

计时函数

  • getTickCount()函数返回CPU自某个事件(如启动电脑)以来走过的时钟周期数
  • getTickFrequency()函数返回CPU一秒钟所走的时钟周期数。这样,我们就能轻松的以秒为单位对某运算计时。
//记录起始时间
double time0 = static_cast(getTickCount ());
//进行图像处理操作...
time0 = ((double)getTickCount() - time0) /getTickFrequency();
 //输出运行时间
cout<<"此方法运行时间为: "<<time0<<"秒"<<endl;
   

访问图像中的像素的三类方法

  • 方法一:指针访问:C操作符[];
  • 方法二:代器iterator;
  • 方法三:动态地址计算。
  • 这三种方法在访问速度上略有差异。debug模式下,这种差异非常明显,不过在release模式下,差异不明显

主函数部分

//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:《OpenCV3编程入门》OpenCV3版书本配套示例程序21
//		程序描述:用指针访问像素
//		开发测试所用IDE版本:Visual Studio 2010
//		开发测试所用OpenCV版本:	3.0 beta
//		2014年11月 Created by @浅墨_毛星云
//		2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】--------------------------
//		描述:包含程序所使用的头文件和命名空间
//-----------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <iostream>  
using namespace std;  
using namespace cv;  

//-----------------------------------【全局函数声明部分】-----------------------------------
//          描述:全局函数声明
//-----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div);  
void ShowHelpText();



//--------------------------------------【main( )函数】---------------------------------------
//          描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( )  
{  
	//【1】创建原始图并显示
	Mat srcImage = imread("1.jpg");  
	imshow("原始图像",srcImage);  

	//【2】按原始图的参数规格来创建创建效果图
	Mat dstImage;
	dstImage.create(srcImage.rows,srcImage.cols,srcImage.type());//效果图的大小、类型与原图片相同 

	ShowHelpText();

	//【3】记录起始时间
	double time0 = static_cast<double>(getTickCount());  

	//【4】调用颜色空间缩减函数
	colorReduce(srcImage,dstImage,32);  

	//【5】计算运行时间并输出
	time0 = ((double)getTickCount() - time0)/getTickFrequency();
	cout<<"\t此方法运行时间为: "<<time0<<"秒"<<endl;  //输出运行时间

	//【6】显示效果图
	imshow("效果图",dstImage);  
	waitKey(0);  
}  


//-----------------------------------【ShowHelpText( )函数】----------------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
	printf("\n\n\t\t\t此为本书OpenCV3版的第21个配套示例程序\n");
	printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION );
	printf("\n\n  ----------------------------------------------------------------------------\n");
}

用指针访问像素


//---------------------------------【colorReduce( )函数】---------------------------------
//          描述:使用【指针访问:C操作符[ ]】方法版的颜色空间缩减函数
//----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div)  
{  
	//参数准备
	outputImage = inputImage.clone();  //拷贝实参到临时变量
	int rowNumber = outputImage.rows;  //行数
	int colNumber = outputImage.cols*outputImage.channels();  //列数 x 通道数=每一行元素的个数

	//双重循环,遍历所有的像素值
	for(int i = 0;i < rowNumber;i++)  //行循环
	{  
		uchar* data = outputImage.ptr<uchar>(i);  //获取第i行的首地址
		for(int j = 0;j < colNumber;j++)   //列循环
		{  	
			// ---------【开始处理每个像素】-------------     
			data[j] = data[j]/div*div + div/2;  
			// ----------【处理结束】---------------------
		}  //行处理结束
	}  
}  

用迭代器访问像素

  • 第二种方法为用迭代器操作像素,这种方法与STL库的用法类似。
  • 在迭代法中,我们所需要做的仅仅是获得图像矩阵的begin和end,然后增加迭代直至从begin到end,将*操作符添加在迭代指针前,即可访问当前指向的内容。
  • 相比用指针直接访问可能出现越界问题,迭代器绝对是非常安全的方法。
  • 不熟悉面向对象编程中迭代器的概念的读者,可以阅读与STL中迭代器相关的入门书籍和文字。用关键字"STL迭代器”进行搜索可以找到各种相关的博文和资料。
//-------------------------------------【colorReduce( )函数】-----------------------------
//		描述:使用【迭代器】方法版的颜色空间缩减函数
//----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
	//参数准备
	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;
		// ------------------------【处理结束】----------------------------
	}
}

动态地址计算

  • 第三种方法为用动态地址计算来操作像素。
  • 下面是使用动态地址运算配合at方法的colorReduce函数的代码。
  • 这种方法简洁明了,符合大家对像素的直观认识。
//----------------------------------【colorReduce( )函数】-------------------------------
//          描述:使用【动态地址运算配合at】方法版本的颜色空间缩减函数
//----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
	//参数准备
	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;  //红是通道
			// -------------------------【处理结束】----------------------------
		}  // 行处理结束     
	}
}

  • 加入了如下代码,变为蓝色背景:
system("color 9F");

标签:Mat,int,像素,访问,图像,div,outputImage,函数
来源: https://blog.csdn.net/weixin_41995541/article/details/89844559

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有