OpenCV学习笔记(五十六)——InputArray和OutputArray的那些事core

看过OpenCV源代码的朋友,肯定都知道很多函数的接口都是InputArray或者OutputArray型的,这个接口类还是很强大的,今个就来说说它们的那些事。

InputArray这个接口类可以是Mat、Mat_<T>、Mat_<T, m, n>、vector<T>、vector<vector<T>>、vector<Mat>。也就意味着当你看refman或者源代码时,如果看见函数的参数类型是InputArray型时,把上诉几种类型作为参数都是可以的。

有时候InputArray输入的矩阵是个空参数,你只需要用cv::noArray()作为参数即可,或者很多代码里都用cv::Mat()作为空参。

这个类只能作为函数的形参参数使用,不要试图声明一个InputArray类型的变量

如果在你自己编写的函数中形参也想用InputArray,可以传递多类型的参数,在函数的内部可以使用_InputArray::getMat()函数将传入的参数转换为Mat的结构,方便你函数内的操作;必要的时候,可能还需要_InputArray::kind()用来区分Mat结构或者vector<>结构,但通常是不需要的。例如:

[cpp] view plain copy
  1. void myAffineTransform(InputArray _src, OutputArray _dst, InputArray _m)
  2. {
  3. Mat src = _src.getMat(), m = _m.getMat();
  4. CV_Assert( src.type() == CV_32FC2 && m.type() == CV_32F && m.size() == Size(3, 2) );
  5. _dst.create(src.size(), src.type());
  6. Mat dst = _dst.getMat();
  7. for( int i = 0; i < src.rows; i++ )
  8. for( int j = 0; j < src.cols; j++ )
  9. {
  10. Point2f pt = src.at<Point2f>(i, j);
  11. dst.at<Point2f>(i, j) = Point2f(m.at<float>(0, 0) * pt.x +  m.at<float>(0, 1) *   pt.y + m.at<float>(0, 2);
  12. }
  13. }

至于有的源代码里使用InputArrayOfArrays作为形参,不用慌张,其实它和InputArray是一样一样一样的。

OutputArray是InputArray的派生类。使用时需要注意的问题和InputArray一样。和InputArray不同的是,需要注意在使用_OutputArray::getMat()之前一定要调用_OutputArray::create()为矩阵分配空间。可以用_OutputArray::needed()来检测输出的矩阵是否需要被计算。有时候传进去的参不是空就不需要计算

还有就是OutputArrayOfArrays、InputOutputArray、InputOutputArrayOfArrays都是OutputArray的别名而已

OpenCV学习笔记(五十七)——在同一窗口显示多幅图片

好久没更新blog里,看到OpenCV官网做的越来越好,心里也是很高兴的,真有些冲动将来加入到这个组织里做些事。估计2.4.3要在国庆左右跟大家见面,让我们多期待一下吧。

闲话少说,今天不介绍复杂的算法了,来个简单的,大家写文章做图经常用Matlab,在Matlab里经常在一个窗口里打开多幅图片。遗憾的是OpenCV没有集成这样的功能,但这难不倒大家,让我试试用ROI来解决这个问题。

没啥好讲的,上代码好了:

[cpp] view plain copy
  1. void imshowMany(const std::string& _winName, const vector<Mat>& _imgs)
  2. {
  3. int nImg = (int)_imgs.size();
  4. Mat dispImg;
  5. int size;
  6. int x, y;
  7. // w - Maximum number of images in a row
  8. // h - Maximum number of images in a column
  9. int w, h;
  10. // scale - How much we have to resize the image
  11. float scale;
  12. int max;
  13. if (nImg <= 0)
  14. {
  15. printf("Number of arguments too small....\n");
  16. return;
  17. }
  18. else if (nImg > 12)
  19. {
  20. printf("Number of arguments too large....\n");
  21. return;
  22. }
  23. else if (nImg == 1)
  24. {
  25. w = h = 1;
  26. size = 300;
  27. }
  28. else if (nImg == 2)
  29. {
  30. w = 2; h = 1;
  31. size = 300;
  32. }
  33. else if (nImg == 3 || nImg == 4)
  34. {
  35. w = 2; h = 2;
  36. size = 300;
  37. }
  38. else if (nImg == 5 || nImg == 6)
  39. {
  40. w = 3; h = 2;
  41. size = 200;
  42. }
  43. else if (nImg == 7 || nImg == 8)
  44. {
  45. w = 4; h = 2;
  46. size = 200;
  47. }
  48. else
  49. {
  50. w = 4; h = 3;
  51. size = 150;
  52. }
  53. dispImg.create(Size(100 + size*w, 60 + size*h), CV_8UC3);
  54. for (int i= 0, m=20, n=20; i<nImg; i++, m+=(20+size))
  55. {
  56. x = _imgs[i].cols;
  57. y = _imgs[i].rows;
  58. max = (x > y)? x: y;
  59. scale = (float) ( (float) max / size );
  60. if (i%w==0 && m!=20)
  61. {
  62. m = 20;
  63. n += 20+size;
  64. }
  65. Mat imgROI = dispImg(Rect(m, n, (int)(x/scale), (int)(y/scale)));
  66. resize(_imgs[i], imgROI, Size((int)(x/scale), (int)(y/scale)));
  67. }
  68. namedWindow(_winName);
  69. imshow(_winName, dispImg);
  70. }

附上效果图一张:

工程的下载链接为http://download.csdn.net/detail/yang_xian521/4531610

OpenCV学习笔记(五十八)——读《Master OpenCV》初感

好久没更新这个系列了。去年12月初的时候就知道出了一本OpenCV的新书《Master OpenCV with Practical Computer Vision Projects》,一直没来得及看,春节前也不想做什么任务,就把这书读一读吧。大概看了一下,和OpenCV的其他书对比了一下,感觉如下:

《Learning OpenCV》是一本经典的老书了,是一个入门教材,读完可以知道OpenCV能做些什么,但里面的具体代码个人觉得还是有点out,但好处就是中文资料很全,网上可以找到很多参考资料。

《OpenCV Cookbook》是我以前推荐过的一本书,是基于2.2版本写的。我的感觉是一本上手教材,书的目的是让大家知道应该如何去调用OpenCV的函数,如何用OpenCV的类去实现简单的视觉任务。需要一定的C++基础。

《Master OpenCV》感觉更像是一个上层建筑,是基于2.4版本写的。是教会大家如何用OpenCV去实现复杂的任务,去完成OpenCV自带函数没有提供的功能。(因为大家经常会因为“OpenCV里面有xxx的函数么?”的否定答案而苦恼,这本书就是告诉大家OpenCV只是个工具,如何去驾驭这个工具进行二次开发是要动脑的)

这本《Master OpenCV》书第一章没有很复杂的东西。

第一章就是介绍了一个边缘检测、肤色检测、一个填充算法,并把这个功能移植到android平台,边缘检测和填充算法都是OpenCV自带的函数功能。这里随便说说读完第一章的几点收获:

1、具体任务要具体分析。这里因为要做到嵌入式平台中,算法的复杂度被放在了首位,所以双边滤波做了简化、填充算法也只是在原图的缩小1/2的图上进行的计算。肤色检测也没有先用经典的人脸检测算法,而是用了一种土鳖的方案,都是为了在嵌入式平台上能运行的高效。这种处理问题的方法值得借鉴学习

2、面向对象编程的思想。这章里也提到了显示FPS,只是人家是在一个类中实现,再对比自己之前写的OpenCV学习笔记(三十八)——显示当前FPS,高下自分。实在是自惭形愧啊~~。

3、貌似把自己的c++工程移植到android平台并不需要改写自己的代码,只要做个JNI function作为接口就可以调用c++的程序了,感觉有点像Matlab中的mex。android下的OpenCV开发基本不懂,这里就不乱讲了。

这几天抓紧把这书读完,把后几章的阅读笔记也写出来分享一下。希望大家多多指正交流

OpenCV学习笔记(五十九)——marker检测识别"Master

第二章原本是讲如何将基于标定的增强现实在ios平台实现,包括以下4个方面:

1、在ios平台建立opencv工程

2、Marker检测识别

3、摄像机标定及Marker姿态估计

4、在Marker基础上渲染一个3维虚拟物体

这里面第一部分是IOS平台的开发,我不是太关注,略去;第四部分是基于OpenGL的3维虚拟物体建立,也是基于IOS平台,因为第三章里还要用到OpenGL,这里留着第三章再解剖。所以这里主要分析第二部分和第三部分。这一篇介绍第二部分。感觉这个东西有点像二维码识别。不知道2维码是怎么做的哦

MarkerDetection类任务processFrame:图1

转为灰度图、2值化(固定阈值法threshold:受光照等影响明显;自适应阈值法adaptiveThreshold:更好)(我这里用OpenCV243里的adaptiveThreshold函数未能实现自适应滤波的效果,效果像边缘检测的算法,很困惑。。最后用threshold函数代替,这个问题未能解决,希望高手指点,ps:网上高手多啊,这个问题已经解决了),检测后的结果如图threshold(图1左上)

findMarkerContours函数进行轮廓检测findContours(用多边形的顶点最好,去掉小于阈值的点(对小的轮廓不感兴趣),把每个轮廓的点按照逆时针排序,并去掉距离太近的轮廓),结果如图contours(图1中上)

接下来findMarkerCandidates函数对轮廓进行筛选,先用approxPolyDP得到轮廓近似的多边形。进行筛选,为凸多边形且顶点为4的才有可能是marker,并检测这个4边形的边长,最小边长如果小于10pixel,也不认为是一个marker。然后把得到的可能的marker的轮廓点按照逆时针排序。并且检测是否检测到重复的marker,如果检测到重复的marker,去掉周长更短的那个。这步之后效果如下markerCandidate(图1左下)

detectMarkers函数有3个任务,去除投影变换的影响(getPerspectiveTransform得到投影矩阵,warpPerspective得到正面的视角的图像),得到marker正面的视图。

然后对这个marker的正面图进行解码,threshold对marker使用THRESH_OTSU进行2值化。效果图:

接下来对这个marker进行识别marker.decode。检测编码marker(对marker解码,marker编码为7*7的栅格,中心5*5为ID,周围一圈为黑色边界,检测的时候先检测周围一圈是否为黑色边界,然后再对中心5*5解码(注意,只有5*5具有旋转不变形才能得到唯一的码),是5bit*5word,每个word中的5bit,2位为id(2位4位),3位为校验码(用来保证旋转),所以5word一共有2^10=1024个不同id,而且第一位要置反,目的是要防止一个word全黑,不易检测。举例,我这里使用的marker的5个word的id分别为10、01、11、11、11。那么如何从刚刚得到的marker图提取出7*7的2值栅格呢,这里用个Mat(Rect)取marker中的小方块,用countNonZero来判断这个方块为0or1。因为marker有4个方向,哪个方向才是我对应的marker的id的,这里用id和我验证用的id的hamming距离来做依据,汉明距最小的即marker的方向。

确认为一个marker后再得到轮廓的细致的corner,使用cornerSubPix,这时才进行细化,是因为这个函数相对耗时,如果之前就对各corner细化,由于候选目标很多,会加重计算负担。)效果图marker(图1右下)。

最后我试了其他的marker编码,都能正确解码出id信息,效果图如下:第一幅图的id为0011010101,第二幅图为第一图的旋转,id相同,第三图id为0011000110,第四图不是一个marker,故没有检测出来。

代码的下载地址:http://download.csdn.net/detail/yang_xian521/5040634

在下一篇里,将介绍如何用这个marker的轮廓位置,和轮廓(红色)的方向(黄点)来在marker上建立一个3维的虚拟物体。

OpenCV"chp.2 OpenCV学习笔记(六十一)——建立支持OpenGL的OpenCV工程“Master OpenCV”chp.3

从OpenCV2.4beta版本,OpenGL就可以有接口到highgui的模块中了。结合Master OpenCV第三章的阅读,这里说说如何在OpenCV的显示中嵌入OpenGL的虚拟物体。

要注意的一点:如果想使OpenCV支持OpenGL,不能使用预编译好的library,要用cmake rebuild工程,注意ENABLE_OPENGL = YES,(在2.4.2版本中,默认ENABLE_OPENGL = NO),标签的改变在CMake的高级版本都是图形界面的,只需把WITH_OPENGL的对号勾选即可。

这里实战过程中我还遇到了一个问题,用这个CMake得到的vs工程(添加了WITH_OPENGL)无法编译通过,郁闷了好久。因为opengl在vs中是支持的,不需要安装,最后找到了这个bug,需要把\modules\core\src\opengl_interop.cpp文件中使用<gl\gl.h>前面添加#include <windows.h>,(其实#include <gl.h>前都需要添加#include <windows.h>)这样才能编译通过,这里我只重新编译opencv_core243d.lib 和opencv_highgui243d.lib

已经得到了支持OpenGL的OpenCV lib,接下来就是如何用OpenCV建立OpenGL窗口,基本的调用方式很像OpenCV中鼠标的使用,都是通过回调函数实现,核心代码如下:

[cpp] view plain copy
  1. // callback function
  2. void onDraw(void* param)
  3. {
  4. // Draw something using OpenGL here
  5. }
  6. int main(void)
  7. {
  8. string openGLWindowName = "OpenGL Test";
  9. namedWindow(openGLWindowName, WINDOW_OPENGL);
  10. resizeWindow(openGLWindowName, 640, 480);
  11. setOpenGlContext(openGLWindowName);
  12. setOpenGlDrawCallback(openGLWindowName, onDraw, NULL);
  13. updateWindow(openGLWindowName); // when needed
  14. return 0;
  15. }

以前我们调用 namedWindow最后一个参数通常会用默认或者使用WINDOW_AUTOSIZE,这回用 WINDOW_OPENGL,然后调用 setOpenGLContext建立窗口关联,为了在这个窗口上画虚拟物体,需要使用回调函数,建立方法就是 setOpenGLDrawCallback,注意这个函数第一个参数是窗口名称,第二个参数是回调函数名,第三个参数是回调函数的参数,因为我这里回调函数onDraw是无参函数,所以这里为NULL。跟MFC重绘需要调用Invalidate或者uadate类似,在需要重绘的时候还要调用 updateWindow。

把我做的一个最基础的OpenGL演示上传:http://download.csdn.net/detail/yang_xian521/5023063(附上我rebulid的支持OpenGL的lib),效果图如下:

OpenCV学习笔记(六十二)——《OpenCV Computer Version with Python》阅读摘要

现在python火啊,每次OpenCV自带的ml模块都让我直呼坑爹,索性准备用python来做OpenCV后期的机器学习算法的处理。于是赶紧拿起这本书读读。

适合OpenCV和python都有一定基础的。。。。由于都比较熟悉这两个东西,我阅读之前比较关心的只有几个问题,具体的应用实例没有仔细看。

1.如何在python中安装opencv

2.OpenCV的Mat数据结构能否方便的转换成numpy的array结构

3.OpenCV的GUI模块在python里好用么

4.二者还能擦出什么我想不到的火花么。。。。

书中提到在windows系统中,python-32bit表现的比64bit要好,推荐安装32位的python

第一个问题在windows下很简单,OpenCV安装好之后,找到目录<build_folder>\lib\Release\cv2.pyd(from a Visual Studio build) 这个文件,然后copy到C:\Python2.7\Lib\site-packages。搞定了,就这么简单。毕竟脚本语言,简直无情,\sources\samples下有很多python的例子,跑几个试试就知道是否安装好了。import cv2这句就可以导入cv2模块了

第二个问题也不用担心了,因为python不用声明变量的类型,实验了一下,发现得到的矩阵的数据类型就是array,稳了,直接拿来用。

第三个问题也超简单,图像显示读写的模块、摄像头模块、鼠标键盘的响应模块都可以,跟c++的版本使用起来也差不多。

第四个问题我简单粗看了一遍书,没发现什么亮点,只是书中提到一个pygame可以用来做hgui效果还行,支持画画和编辑文本,不过好像对CV也没啥帮助,所以就没研究了。

补充几个我学习的时候遇见的问题:

opencv里的Rect数据结构在python里是没有对应类型的,这个要注意调用的时候需要注意。比如rectangle函数输入的就是矩形两个点的坐标,不是Rect。

还有就是opencv里的很多宏在python里需要加上cv2.cv前缀就可以生效了。

from: http://blog.csdn.net/yang_xian521/article/category/910716

OpenCV学习笔记(五十六)——InputArray和OutputArray的那些事core OpenCV学习笔记(五十七)——在同一窗口显示多幅图片 OpenCV学习笔记(五十八)——读《Mast相关推荐

  1. InputArray和OutputArray的那些事

    看过OpenCV源代码的朋友,肯定都知道很多函数的接口都是InputArray或者OutputArray型的,这个接口类还是很强大的,今个就来说说它们的那些事. InputArray这个接口类可以是M ...

  2. 聊聊高并发(三十六)Java内存模型那些事(四)理解Happens-before规则

    在前几篇将Java内存模型的那些事基本上把这个域底层的概念都解释清楚了,聊聊高并发(三十五)Java内存模型那些事(三)理解内存屏障 这篇分析了在X86平台下,volatile,synchronize ...

  3. flash动画设计期末作业_「2019年下学期」第二十五二十六节:期末作品三-吉祥物设计...

    初心 伟大的艺术品不必追随潮流,他本身就能引领潮流. 课前准备 软件安装 [2019(上)]<三维建模与动画设计> [2019年下学期]第一节:选修介绍及选修人数确定 [2019年下学期] ...

  4. OpenCV C++案例实战十六《制作哈哈镜图像》

    OpenCV C++案例实战十六<制作哈哈镜图像> 前言 一.凸透镜 1.功能源码 2.效果显示 二.凹透镜 1.功能源码 2.效果显示 三.源码 总结 前言 本文将使用OpenCV C+ ...

  5. 第十六届全国大学生智能汽车竞赛华北赛区开幕式在我院隆重举行

    简 介: 第十六届全国大学生智能车竞赛华北赛区在北京科技大学天津学院召开. 关键词: 智能车竞赛,第十六届,华北赛区,北京科技大学天津学院   7月16日上午,第十六届全国大学生智能汽车竞赛华北赛区在 ...

  6. 第十六届全国大学生智能车竞赛比赛获奖证书格式说明以及下载链接

    简 介: 本文给出了 第十六届全国大学生智能车竞赛 获奖证书的格式说明以及制作方法.证书的格式也参照了 第十五届智能车竞赛电子证书格式说明 .同时,获奖证书下载链接在后面给出. 关键词: 全国大学生智 ...

  7. 第十六届智能汽车竞赛AI视觉组分赛区数据集发布

    第十六届智能汽车竞赛AI视觉组 分赛区数据集发布 §01 图片规格   各参赛同学你们好,为保障第十六届智能汽车竞赛AI视觉组的顺利备赛,组委会及赞助单位NXP一致认为可以将分赛区的数据集提前公布,经 ...

  8. 第十六届全国大学智能汽车竞赛竞速比赛规则

    ➤第十六届竞赛竞速比赛规则导读   参加过往届比赛的队员可以通过下面内容了解第十六届竞赛规则主要变化.如果第一次参加比赛,建议对于本文进行全文阅读. 竞速比赛共分为为八个组别.详细情况参加文档第一节中 ...

  9. 第十六届计算机表演赛,第十六届全国中小学学生计算机表演赛邢台赛区评选结果...

    <第十六届全国中小学学生计算机表演赛邢台赛区评选结果>由会员分享,可在线阅读,更多相关<第十六届全国中小学学生计算机表演赛邢台赛区评选结果(4页珍藏版)>请在技术文库上搜索. ...

最新文章

  1. usb深度检查 清理_巴南区清理化粪池工程队价格合理2020
  2. win10 安装selenium和使用
  3. SonarQube6.2源码解析(二)
  4. ViewPager+Fragment 组合的预加载和懒加载
  5. 35 岁 学python 必要_程序员:Python学不学?完全没必要纠结
  6. python cookbook 笔记三
  7. SpringSecurity自动登录详解
  8. oracle desc卡,Oracle的一个bug,desc的bug,很夸张,这么基础的功能居然有bug
  9. 探索webpack热更新对代码打包结果的影响(二)
  10. C# 异步定时器,可以重载; System.Timers.Timer
  11. 【POJ1064】Cable master(二分搜索+浮点判断处理)
  12. 全球经典《深入解析Windows 操作系统,第4 版》4月19日全国发货!
  13. 【免公众号】新版盲盒交友程序源码盲盒交友系统一元交友
  14. 软件开发人员的简历项目经验怎么写?
  15. 【新知实验室】体验腾讯云音视频
  16. 名校申博有多难?印度小哥申请CMU一路被拒,最终拿到马普研究所offer
  17. 计算机系统底层架构思路
  18. C语言:while与do while循环语句
  19. InternalEror :Dst tensor is not initialized
  20. Google Play邮件提示: 您必须声明您的广告 AD_ID 权限

热门文章

  1. Spring Cloud【Finchley】-16 Zuul的路由配置
  2. Java-Java5.0注解解读
  3. Spring-整合多个配置文件
  4. WebView完全解读
  5. Java学习笔记(二)--Java开发环境
  6. mysql 散列存储_什么是数据库散列存储? - 蚂蚁吞大象的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  7. linux内核引入模块机制好处,linux内核模块的版本检查机制
  8. 微服务如何解决分布式事务
  9. redis之mq实现发布订阅模式
  10. android图片跳转动画效果,Android实现Activity界面切换添加动画特效的方法