在opencv中,reshape函数比较有意思,它既可以改变矩阵的通道数,又可以对矩阵元素进行序列化,非常有用的一个函数。

函数原型:

C++: Mat Mat::reshape(int cn, int rows=) const

参数比较少,但设置的时候却要千万小心。

cn: 表示通道数(channels), 如果设为0,则表示保持通道数不变,否则则变为设置的通道数。

rows: 表示矩阵行数。 如果设为0,则表示保持原有的行数不变,否则则变为设置的行数。

首先设置一个初始矩阵:一个20行30列1通道的一个矩阵

int main()
{
Mat data = Mat(, , CV_32F); //设置一个20行30列1通道的一个矩阵
cout << "行数: " << data.rows << endl;
cout << "列数: " << data.cols << endl;
cout << "通道: " << data.channels() << endl;
system("pause");
return ;
}

输出:

第一次变化:通道数不变,将矩阵序列化1行N列的行向量。

int main()
{
Mat data = Mat(, , CV_32F); //设置一个20行30列1通道的一个矩阵
cout << "行数: " << data.rows << endl;
cout << "列数: " << data.cols << endl;
cout << "通道: " << data.channels() << endl;
cout << endl;
Mat dst = data.reshape(, );
cout << "行数: " << dst.rows << endl;
cout << "列数: " << dst.cols << endl;
cout << "通道: " << dst.channels() << endl;
system("pause");
return ;
}

第二次变化:通道数不变,将矩阵序列化N行1列的列向量。

int main()
{
Mat data = Mat(, , CV_32F); //设置一个20行30列1通道的一个矩阵
cout << "行数: " << data.rows << endl;
cout << "列数: " << data.cols << endl;
cout << "通道: " << data.channels() << endl;
cout << endl;
Mat dst = data.reshape(, data.rows*data.cols);
cout << "行数: " << dst.rows << endl;
cout << "列数: " << dst.cols << endl;
cout << "通道: " << dst.channels() << endl;
system("pause");
return ;
}

可见,序列成列向量比行向量要麻烦一些,还得去计算出需要多少行。但我们可以先序列成行向量,再转置

    Mat dst = data.reshape(, );      //序列成行向量
Mat dst = data.reshape(, ).t(); //序列成列向量

第三次变化:通道数由1变为2,行数不变。

int main()
{
Mat data = Mat(, , CV_32F); //设置一个20行30列1通道的一个矩阵
cout << "行数: " << data.rows << endl;
cout << "列数: " << data.cols << endl;
cout << "通道: " << data.channels() << endl;
cout << endl;
Mat dst = data.reshape(, 0);
cout << "行数: " << dst.rows << endl;
cout << "列数: " << dst.cols << endl;
cout << "通道: " << dst.channels() << endl;
system("pause");
return ;
}

从结果可以看出,列数被分出一半,放在第二个通道里去了。

同理,如果通道数由1变为3,行数不变。则每通道的列数变为原来的三分之一。

需要注意的是,如果行保持不变,改变的通道数一定要能被列数整除,否则会出错。

第四次变化:通道数由1变为2,行数变为原来的五分之一。

int main()
{
Mat data = Mat(, , CV_32F); //设置一个20行30列1通道的一个矩阵
cout << "行数: " << data.rows << endl;
cout << "列数: " << data.cols << endl;
cout << "通道: " << data.channels() << endl;
cout << endl;
Mat dst = data.reshape(, data.rows/);
cout << "行数: " << dst.rows << endl;
cout << "列数: " << dst.cols << endl;
cout << "通道: " << dst.channels() << endl;
system("pause");
return ;
}

可见,不管怎么变,都遵循这样一个等式:

变化之前的  rows*cols*channels = 变化之后的 rows*cols*channels

我们只能改变通道数和行数,列数不能改变,它是自动变化的。

但是要注意的是,在变化的时候,要考虑到是否整除的情况。如果改变的数值出现不能整除,就会报错。

最后,我们再验证一下:opencv在序列化的时候是行序列化还是列序列化呢?

我们知道,在matlab里面,是列序列化, 即取值为从上到下,从左到右,opencv又是怎么样的呢

int main()
{
Mat data = (Mat_<int>(, ) << , , , , , ); //2行3列的矩阵
cout << data << endl;
Mat dst1 = data.reshape(, ); //通道不变,序列成列向量
cout <<endl<< dst1 << endl;
Mat dst2 = data.reshape(, ); //通道不变,序列成行向量
cout << endl << dst2 << endl;
system("pause");
return ;
}

从结果看出,不管是变化成行向量还是列向量,opencv都是行序列化,即从左到右,从上到下,与matlab是不一样的。

简单的一个函数,功能却很强大!你会用了吗

opencv3学习:reshape函数的更多相关文章

  1. JavaScript学习09 函数本质及Function对象深入探索

    JavaScript学习09 函数本质及Function对象深入探索 在JavaScript中,函数function就是对象. JS中没有方法重载 在JavaScript中,没有方法(函数)重载的概念 ...

  2. Matlab 的reshape函数

    看Matlab的help文档讲得不是清楚. 先给上一段代码: >> a=[1 2 3;4 5 6;7 8 9;10 11 12]; >> b=reshape(a,2,6); 这 ...

  3. Matlab 的reshape函数(转)

    看Matlab的help文档讲得不是清楚. 先给上一段代码: >> a=[1 2 3;4 5 6;7 8 9;10 11 12]; >> b=reshape(a,2,6); 这 ...

  4. C++学习之函数指针

     C++学习之函数指针          和数据项类似,函数也有地址,函数的地址是存储在机器语言代码的内存的开始地址.通常,这些地址对用户而言,不重要也没什么用处,但对程序而言,它却很有用. 一.函数 ...

  5. Javascript学习5 - 函数

    原文:Javascript学习5 - 函数 在Javascript中,函数和对象是交织在一起的.有些函数的特性与对象相关联.这一点的内容在第六部分会讨论到. 这一部分主要讨论函数与其它比较熟悉的语言( ...

  6. OpenCV3学习笔记

    http://blog.csdn.net/u010429424/article/details/73691001 http://blog.csdn.net/zhaoxfxy/article/detai ...

  7. 《python基础教程(第二版)》学习笔记 函数(第6章)

    <python基础教程(第二版)>学习笔记 函数(第6章) 创建函数:def function_name(params):  block  return values 记录函数:def f ...

  8. python学习8—函数之高阶函数与内置函数

    python学习8—函数之高阶函数与内置函数 1. 高阶函数 a. map()函数 对第二个输入的参数进行第一个输入的参数指定的操作.map()函数的返回值是一个迭代器,只可以迭代一次,迭代过后会被释 ...

  9. python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程

    python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...

随机推荐

  1. C语言错误之--初始值(低级错误)

    今天犯了一个低级错误,虽然低级,但是也不能忽视,一个低级错误以后可能小则浪费时间和精力,大则酿成整个app的项目bug.    

  2. iOS之学习资源收集--很好的IOS技术学习网站

    点击图片也能打开相关的网站: https://boxueio.com/skill/swift http://ios.b2mp.cn/ http://gold.xitu.io/welcome/?utm_ ...

  3. 使用eclipse遇到问题:the-package-collides-with-a-type

    相似问题:http://stackoverflow.com/questions/12236909/the-package-collides-with-a-type

  4. Hadoop从伪分布式到真正的分布式

    对这两天学习hadoop的一个总结,概念就不提了.直接说部署的事,关于如何部署hadoop网上的资料很多, 比较经典的还是Tim在IBM developworks上的系列文章 http://www.i ...

  5. 学习HTML5必读之《HTML5设计原理》

    引子:很久前看过的一遍受益匪浅的文章,今天再次转过来,希望对学习HTML5的朋友有所帮助. 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一方面,当然了,就是HTML5.我可以站在这儿只讲HT ...

  6. 【MySQL】MySQL忘记root密码解决方案

    转眼间从实习到现在已经快两年了.两年的工作做遇到过很多很多的拦路虎,大部分也通过搜索引擎找到了解决的方案.奈何大脑不是硬盘,偶尔有的问题第二次遇到还是有点抓蒙...所以决定把这些东西记录在博客上.这样 ...

  7. 【Android】 Android实现录音、播音、录制视频功能

    智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...

  8. Json常用的转换

    简单记录一下jquery里面的JSON.parse()和JSON.stringify()函数,和js中的eval()函数的用法 1,JSON.parse 函数(常用) 作用:将 JavaScript ...

  9. poj 2342 Anniversary party 简单树形dp

    Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3862   Accepted: 2171 ...

  10. 探索 OpenStack 之(9):深入块存储服务Cinder (功能篇)

    继研究了Neutron之后,继续Nova的外围研究之旅.本站是研究块存储服务Cinder. 0.验证环境 环境包括: 1.一个controller节点,运行nova-api, nova-schedul ...