【学习OpenCV】高效遍历Mat

用指针来遍历图像

方法:取出图像中第i行数据的指针:image.ptr<uchar>(i),再访问各列元素。

unsigned char * pData = BmpStream+1078;
int nr=img1.rows;
int nc=img1.cols;

for(int i=nr-1;i>=0;i--)	//遍历mat
{
	const uchar* inData=img1.ptr<uchar>(i);
	for(int j=0;j<nc;j++)
	{
		*pData++= inData[j];			
	}
}

一般来说图像行与行之间往往存储是不连续的,但是有些图像可以是连续的,Mat提供了一个检测图像是否连续的函数isContinuous()。当图像连通时,我们就可以把图像完全展开,看成是一行。

unsigned char * pData = BmpStream+1078;
int nr=img1.rows;
int nc=img1.cols;
if(img1.isContinuous())
{
	nr=1;
        nc=nc*img1.rows*img1.channels();
}
for(int i=0;i<nr;i++)	//遍历mat
{
	const uchar* inData=img1.ptr<uchar>(i);
	for(int j=0;j<nc;j++)
	{
		*pData++= * inData ++;			
	}
}

注:若算法对行列敏感,不能采用第2种方法,因为已经转换为1维!


用指针除了用上面的方法外,还可以用指针来索引固定位置的像素:


image.step返回图像一行像素元素的个数(包括空白元素),image.elemSize()返回一个图像像素的大小。


&image.at<uchar>(i,j)=image.data+i*image.step+j*image.elemSize();


实验证明

虽然把遍历方式改为指针,但发现release下的速度与at方法差不多(快一点点);而debug下的确是快很多;这说明,在编译的时候,release会对at方法进行优化的!所以,在满足算法的实时性要求的条件下,为了代码的可读性,还是直接用at方法吧,而且用着还方便。


另一个比较at方法与指针方法的例子:

1000*1000矩阵的16位整型转换32位浮点,输入Mat src为1000*1000的CV_16U类型,输出Mat dst

	//方式一 : at方法
	for(int i=0;i<h;i++)	//遍历行
	{		
		for(int j=0;j<w;j++)	//遍历列
		{
			dst.at<float>(i,j) = (float)src.at<unsigned short>(i,j);
		}
	}
速度最慢

	//方式二 : converTo方法
	src.convertTo(dst,CV_32F);
比at方法快

	//方式三 : 指针
	unsigned short* psrc = (unsigned short*)src.data;
	//float *pdst = new float [src.total()];
	float *pdst = (float*)dst.data;
	for(int i=0;i<h;i++)	//遍历行
	{		
		const unsigned short* p0 = psrc + i*w;
		float* p1 = pdst + i*w;
		for(int j=0;j<w;j++)	//遍历列
		{	
				*p1++= (float)p0[j];		
		}
	}
速度与convertTo差不多


-------------------------END---------------------------------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值