opencv2-用指针来访问图像像素

opencv2-用指针来访问图像像素
//-----------------------------------【全局函数声明部分】-----------------------------------
//          描述:全局函数声明
//-----------------------------------------------------------------------------------------------
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);  
}  
//---------------------------------【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;  
// ----------【处理结束】---------------------
}  //行处理结束
}  
}  
//-----------------------------------【ShowHelpText( )函数】----------------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV2版的第21个配套示例程序\n");
printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION );
printf("\n\n  ----------------------------------------------------------------------------\n");
}

整个程序的主要部分在这里:
//双重循环,遍历所有的像素值
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;  
// ----------【处理结束】---------------------
}  //行处理结束

}  

主要思想是:双重循环遍历所有的像素值。

行循环是rows,列循环是cols。

首先,进入行循环的时候,找到每一行的行首地址:uchar* data = outputImage.ptr<uchar>(i)。存进data指针里面。注意指针类型是uchar类型。

然后,进入列循环的时候,data[]数组的元素就是每一列的图像像素。直接使用数组的方式来访问元素即可。

就这两步。


下面看一下这个头指针ptr<uchar>()

函数原型是:

template<typename _Tp> inline _Tp*  Mat::ptr(int y)
{
    CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
    return (_Tp*)(data + step.p[0]*y);
}

返回的是_Tp类型的指针。指针指向的是data数据的行首地址。step.p[0]是第一行的首地址,step是步长,最后乘以y是指向y行的首地址。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值