【学习OpenCV】与matlab风格一致的函数

matlab被广泛用于算法的仿真,往往是整个项目的最上层设计时使用到的工具;而具体的高效的代码实现则要借助C\C++,而opencv提供了很多这方面的接口函数,里面有一部分是与matlab相对应的,这一点更进一步方便了算法的代码实现过程。当然,首先不考虑代码的效率,因为本来opencv就不见得具有多高的效率,更何况是再进一步封装成matlab风格的接口呢?但对于项目开发还是有一定的便利性的。

1、用得最多的莫过于——imread、imshow

区别在于数据结构:matlab中是N维数组,CV中是Mat类

2、矩阵运算

这里有大量的矩阵运算、矩阵变换函数,因为matlab名字就是矩阵实验室,在矩阵运算的效率上非常可观。其本质也是C++,估计CV会用到相似的算法,正如乔布斯说的:好的艺术家抄袭,伟大的艺术家剽窃。

如,两矩阵点乘、减法;矩阵乘方;等等。参考:http://blog.csdn.net/kelvin_yan/article/details/41726843

3、矩阵赋值

matlab中又一使用率很高的操作——zeros、ones、eye,CV中Mat下有对应方法

另外,matlab中a=[1,2,3;4,5,6],CV中则麻烦一点 Mat a = (Mat_<double>(2,3) << 1, 4, 2, 5, 3, 6);  

4、矩阵元素寻访

matlab中B(5:9, :) ,CV中B(Range(4, 9), Range::all())

注意,Range的区间定义为:[left,right),右边界不是刚好等于right噢,实际是right-1,如上面的例子是取B的第5到第9个行,在matlab中下标是从1开始算的,所以直接是5:9,但在opencv里,下标从0开始,其数组下标范围是 i = 4:8,由于Range的区间定义,所以应写为 Range(4,9)

opencv这样定义Range区间主要是为了更好地表示单一一行或者一列,如,表示第10行,记为Range(10,11),如果按照我们习惯应该是Range(10,10),这样明显存在歧义不利于编程

还需要注意的是,matlab里面我们可以这样来赋值:

B(5:9,:) = C(5:9,:);

但opencv里不行,这样做没有任何意义,B的值不会改变,要用copyTo方法:

C(Range(4,9),Range::all()).copyTo(B(Range(4,9),Range::all()));

往往“简单易用”与“效率”是矛盾的,那Range方法又是不是中看不中用呢?下面做个小测试,跟指针方式访问相比较:

建立两个Mat

Mat D(h,w,CV_64F,cv::Scalar(0));	
Mat E(h,w,CV_64F,cv::Scalar(0));

具体任务是把D的第1~500行、第5~700列的值拷贝至E的相同位置,分别通过指针访问Mat和Range访问Mat的方式实现,测量运行5000次的平均耗时:

	double tcnt=0;
	for(int cnt=0;cnt<5000;cnt++)
	{
	tt.interval();  //定时函数

	D(Range(0,500),Range(4,700)).copyTo(E(Range(0,500),Range(4,700)));

	tcnt += tt.interval();
	}
	cout<<"ptr time: "<<tcnt/5000<<endl;

指针方式:

	double tcnt=0;
	for(int cnt=0;cnt<5000;cnt++)
	{
	tt.interval();  //定时函数

	double* ptr1 = (double*)E.data;
	double* ptr0 = (double*)D.data;
	for(int y=0;y<500;y++)
	{
		for(int x=4;x<700;x++)
		{
			*(ptr1 + y*w+x) = *(ptr0 + y*w+x);
		}
	}
	
	tcnt += tt.interval();
	}


结果显示,Range比指针的效率更高!!!不过也就高出10%,两者效率还是比较相近的,当然实际中采用Range会提高代码的可读性

5、reshape

改变已有矩阵的形状,例如一维变二维、三维变一维,又或者改变矩阵的尺寸

但与matlab不一样,opencv需要考虑数据在内存中的排列方式,所以cv::Mat本身不仅只有行、列两个参数,它还有type、step、channel等等参数。cv::Mat::reshape不会重新分配内存,它是在已有内存的基础上,根据用户输入的channel、rows参数,重新计算cv::Mat的头信息

如,一个500*400的二维矩阵,希望将其大小改为400*500

cv::Mat mat(500, 400, CV_8UC1);  //单通道的500*400矩阵
mat = mat.reshape(1, 400);   //调整mat的行数为400,通道数仍然是1,内部会根据mat原来的大小rows*cols*channels() 计算新的列数,即500*400*1 / 1 / 400 = 500,同时mat的另外一些成员变量也会更新,如step、elemenSize等

6、高级操作

奇异值分解

矩阵求逆

(to be continued)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值