对于Ruby编程语言使用OpenCV和FFI的机器视觉的延伸.docx
- 文档编号:26852178
- 上传时间:2023-06-23
- 格式:DOCX
- 页数:15
- 大小:166.07KB
对于Ruby编程语言使用OpenCV和FFI的机器视觉的延伸.docx
《对于Ruby编程语言使用OpenCV和FFI的机器视觉的延伸.docx》由会员分享,可在线阅读,更多相关《对于Ruby编程语言使用OpenCV和FFI的机器视觉的延伸.docx(15页珍藏版)》请在冰豆网上搜索。
对于Ruby编程语言使用OpenCV和FFI的机器视觉的延伸
对于Ruby编程语言使用OpenCV和FFI的机器视觉的延伸
亚伦马尔堡,迈克尔·P·海斯和安德鲁·班布里奇-史密斯
电气与计算机工程系
坎特伯雷大学
新西兰基督城
电子邮件:
aaron.marburg@canterbury.ac.nz
摘要:
本文介绍了OpenCV-FFI软件包,它从OpenCV计算机视觉库公开数据类型和功能给Ruby编程语言。
OpenCV-FFI使用外部函数接口(FFI)产生一个RubyAPI,它反映了OpenCV的CAPI;复杂的其他层随后建立在核心API。
示例代码和基准测试结果显示使用OpenCV-FFI的内部Ruby脚本代码的OpenCV的有效性,以及示范不谨慎使用Ruby迭代的隐患。
最后,还有一个的相对优势和劣势的讨论关于FFI为基础的方法对比一个用Ruby-c写的定制的扩展库或一个自动包装器生成软件包的使用。
I.介绍
通过在数量和可用性的快速增长带动对可视化数据源,机器视觉已成为一个地区的密集和集中研究在两个学术和商业环境。
这导致了一个多样的和不断扩大的应用范围,其中包括自助停车和导航车[1],可以人脸识别的相机[2],以及从异构图像集的场景的全三维重建[3]。
机器视觉的研究是被一个强烈的需要试验标记。
即使有一个明确的问题,该方法将产生最好的结果往往不能确定先验。
此外,许多机器视觉算法需要交换机配置,培训,或在一个给定的数据集调整任意参数以达到最好的结果。
典型的机器视觉工程在初期阶段由强烈的灵活性需要标记,只有在以后的发展阶段被计算效率的驱动器取代。
然后,对机器视觉研究人员面临的挑战就是选择的工具和方法,这种方法提供了快速原型开发的敏捷性和探索新的算法,同时也维护运行时的效率和性能。
最近几年动态(脚本)语言受欢迎程度在上升,部分原因是他们的开发效率大大减少代码生成和测试之间的循环[4],部分是因为电脑系统已经变得足够强大,这样的语言可在大多数实际情况下性能变得微不足道。
不幸的是,在高性能计算领域这种性能开销(是否真实或者只是感知)已经阻碍了采用脚本语言。
在某些情况下,脚本语言的好处已经被带到一个特定的高性能计算环境通过领域特定语言的发展[5]。
最近,在各种数学和科学领域Python已经成为最好的通用脚本语言支持高性能计算,包括机器视觉[6],[7],信号处理[8],生物信息学[9],[10]。
本文介绍了它使用的外部函数接口(FFI)引入来自OpenCV的计算机视觉库核心结构为Ruby环境的Ruby编程语言的库。
这允许直接操作OpenCV的原语使用OpenCV函数内的Ruby。
它还允许层增加的功能和复杂性的发展在Ruby基于这些原始对象。
正如所述,一些护理可以实现高效绩,同时还收获Ruby环境对于非实时元素软件的好处。
从
II.RUBY编程语言
Ruby编程语言是松本行弘"Matz"(MatsumotoYukihiro)设计和开发的,第一次出现实在1995年,现在编纂在ISO/IEC31070标准[11]。
Ruby语言有不同的实现,虽然在这里讨论的重点是由松本维护的官方Ruby实现。
Ruby是一种动态的面向对象的语言。
将块作为首选机制实现词法闭包,循环和迭代。
允许动态创建和操纵的成员变量和函数。
允许动态成员变量和函数的创建及操纵。
近年来,Ruby加入了Perl、PHP、Python作为一个主要的开源脚本语言[12]。
不断扩大的用户群带来了大量的高级功能的Ruby的生态系统,尤其是在网络和在线内容表示的区域。
然而,在其他领域,比如科学计算,Ruby已经落后于同行。
要解决本工程,就需要一个完整的功能齐全的Ruby机器视觉库。
A.在Ruby中访问共享库
规范化方法C代码引入Ruby是通过Ruby-CAPI,在C中它能提供工具来定义和操作Ruby类,对象,方法。
一旦编译,由Ruby-C建立的库可以加载到Ruby环境中其中基于C和基于Ruby的类的定义是没有区别的。
集成第三方共享库时,标准做法是编写一个Ruby-C扩展它定义了RubyAPI在C代码,封装相关的库函数,并提供翻译功能将库数据结构映射到Ruby对象。
这个过程被Ruby强大的元编程功能给简化了,Ruby的任何功能不能直接访问库。
另外,SWIG界面生成工具的最新版本支持Ruby代码生成[13]。
这可能提供了一个强有力的替代这里描述的方法,尽管由于复杂自然OpenCVc++接口(即,大量模板等)的任何自动解析器可能无法解开的API。
值得注意的是,OpenCV开发社区的选择来实现定制的解析器生成的Python包装器API的应被视为一个迹象的相对复杂性。
Ⅲ.相关工作
这里介绍的工作必须直接与扬魏德金的HornetsEyeRuby库进行比较[14]。
HornetsEye是建立在一套定制的多维数组表示(标量,复杂,RGB数组),定义在Ruby中,虽然与一个潜在的二进制表示。
加速算术运算通过即时(JIT)创建Ruby-C扩展生成、编译和加载生成。
魏德金的工作包括扩展库的多样性,将HornetsEye矩阵表示转换成用于与其他第三方库(例如,OpenCV的,FFTW3等)和其他输入和输出系统(例如,V4L,X11)。
HornetsEye已被成功地用于计算机视觉研究[15]。
这里描述的项目和HornetsEye的核心优势是每个提出了特定的矩阵表示为常见的交换媒介。
OpenCV-FFI使用OpenCV的CvMat结构,而HornetsEye用自己的内部MultiArray。
这两个项目提供了一套全面的快速基本操作为操作核心的数据类型。
使用CvMat这里确保直接兼容OpenCV提供的高级功能的范围。
通过引入一个新的数据类型,HornetsEye需要强制函数来访问OpenCV的功能虽然库都需要翻译与其他库函数来进行互操作(例如,FFTW3)。
在Ruby中这两个系统还必须应对表示可用备用数组,特别是内置数组和矩阵类型,和田中先生的NArray多维数组包[16]。
有提出OpenCV-FFI方法的主要优势是它将任何RubyOpenCV开发社区的发展。
从某种意义上说,一个OpenCV-FFI应用程序是一个OpenCV的应用程序。
尤其是如果Ruby代码随后被转化为C代码效率(一旦发展已经放缓)。
因为C代码使用OpenCV构造本身,它可以很容易地贡献回OpenCV项目供non-Ruby开发人员使用。
有用Ruby编写的特定于应用程序的机器视觉分析软件包,例[17],同时有一个休眠项目开发一个RubyAPI使用Ruby-C对于OpenCV。
还有许多Ruby库的图像处理(如不同于机器视觉),例如Ruby-VIPS接口到VIPS图像处理系统[18],或RMagick接口到ImageMagick应用程序。
目前,HornetsEye是唯一完整的通用机器视觉库为Ruby语言。
而在Ruby小径Python支持科学计算,它已经被用于复杂的自动化任务的控制[19]。
在Ruby生态系统之外,与Python语言最直接的比较是支持包括官方OpenCV分布[7]。
OpenCV开发团队使用定制代码解析器自动生成Python包装器代码(c++),然后可以编译成Python扩展。
OpenCV的过程是借助于宏代码解析器的源代码提Python库—就一个公分母科学计算库而言—在Ruby生态系统。
应该指出的是,Python有库访问外部函数接口API通过ctypes和cffi包。
这两个包的区别在于ctypes在Python中使用一组特定于域的类型和函数来定义数据类型和函数参数。
cffi支持直接解析C代码片段定义函数和数据结构。
RubyFFI扩展提供了这两种操作模式,尽管前者用于OpenCV-FFI。
Ⅳ.外部函数接口
一个外部函数接口(FFI)定义了一个编程语言的应用程序编程接口可以从另一种语言访问元素。
在这种背景下,FFI指的是便携式外部接口调用由libffi提供的函数接口。
一般而言,在一个给定平台/操作系统将定义一个“调用协定”,描述了函数参数的位置在入口函数。
编译语言语法描述函数参数在某种程度上编译器可以映射到正确的安排平台。
相比之下,解释语言通常缺乏修复函数参数的顺序和类型的能力。
libffi提供了一种机制,通过这种机制可以动态地描述函数定义,但仍然遵守底层平台调用协定。
Ruby语言的标准实现,FFI是Ruby-FFI提供的扩展。
从一个Ruby用户的角度来看,FFI库定义了一个Ruby语法连接共享库,描述数据结构,并定义库函数调用,全部在Ruby环境中。
FFI接口语法简洁,在Ruby空间中提供了库函数和函数之间的一对一映射。
表1、2和3提供了一个简单的例子Ruby-FFI语法和示例生成的数据结构和函数的使用方法。
Ruby-FFI突出的优势就是开发人员只需要知道两种语言:
C和Ruby,而不是中间系统(如Ruby-C函数/宏集是两种语言的桥梁)。
这也意味着开发人员熟悉库的编译语言API(如。
典型的分类和函数调用的使用)可以快速开始使用Ruby中的相同的功能。
相比Ruby-C扩展的传统发展,Ruby的软件调用函数通过FFI在库中有一个先决条件:
相关的动态库。
安装一个Ruby-C扩展要求相关的扩展被编译在每个安装的软件,它需要一个本地开发环境(即。
一个编译器,等等)。
Ruby-FFI提供了数据结构生成包装器在堆上像Ruby对象被访问。
特别是,自动生成访问函数提供对数据结构的读/写访问成员。
小心,这意味着数据结构可以呆在他们的本地二进制形式不翻译。
当连续地调用库函数时这可以提供一个性能优势,但如果变量是反复在本地和Ruby数据类型之间转换就会潜在很大的性能损失,特别是如果翻译发生透明没有特定的来自用户的输入。
处理本地对象库的缺点是他们管辖范围之外的Ruby的垃圾收集系统,必须谨慎处理和销毁对象。
在许多情况下,这可以通过将每个堆变量与Ruby栈对象进行关联立即改善。
销毁堆栈对象,一个析构函数功能可以释放相关堆的变量。
不幸的是,目前,FFI机制不使用c++代码。
因为c++函数Name-Mangling方法不是标准化的,没有将c++函数名转换为链接器的象征的可移植机制。
这将在第七部分进一步讨论,这对OpenCV-FFI进一步发展提出了一个严重的阻碍。
Ⅴ.OPENCV-FFI扩展
OpenCV-FFI家族的扩展包括一套分层的库:
清单1.示例代码用C.
typedefstruct{
doublea,b;
intc;
}DataType;
DataType*makeDataType(doublea,doubleb,intc);
doubleuseDataType(DataType*c);
清单2.RUBYFFI的描述代码在清单1中.这个示例使用了一些从NICEFFI工具.
classDataType< : Struct layout: a,: double, : b,: double, : c,: int end attach_function: makeDataType,[: double,: double,: int], DataType.typed_pointer attach_function: useDataType,[: pointer],: double 清单3.示例使用RUBY-FFI代码从2.RUBY解释器的回应由“->”表示. data=makeDataType(1.0,2.0,16) data.is_a? ->DataType data.a ->1.0 useDataType(data) ->3.0 核心opencv-ffi库代表一个“纯”OpenCV函数和原语通过FFI映射到Ruby。 它包含一些语法糖在FFI语法尴尬的情况下,如创建和废弃pointers-to-pointers。 这个库允许创建Ruby脚本,看起来非常类似于等价的OpenCVC程序。 这一层提供了大多数控制代码的性能,因为它保留了强类型核心OpenCV原语,不透明的翻译。 opencv-ffi-wrappers由类组成,它创建一个“ruby类”(即、面向对象)的API。 在某种程度上,这些对象反映OpenCVc++接口。 这一层也努力的做更多“type-agnostic”和包含更多的必要的数据的自动转换。 它还包含写在本地的补充的计算机视觉例程,也就是说,未编译的Ruby。 opencv-ffi-ext包含编译Ruby-C扩展和相关的Ruby代码。 这个扩展介绍了不是OpenCVCAPI的功能,例如,C包装器函数仅OpenCVc++API中。 这些函数映射在FFI的方式类似于其他OpenCV-FFI库。 图1。 用于基准测试的测试图像。 进一步的补充库的序列使用FFI-binding技术引入其他非OpenCV代码库的生态系统。 例如opencv-ffi-fast链接代码来自Ed-winRosten的快速关键点检测代码[20]。 同样,opencvffi-fftw实现对FFTW3FFT库的包装[21]。 这些包装器包含代码翻译OpenCV类型在每个库中使用本机类型。 例如,这允许一个OpenCVCvMat直接传递到FAST库通过FFI。 Ⅵ.基准测试 作为一个示范,两个算法实现并行使用OpenCV的CAPI,OpenCV-FFI的“纯”映射和OpenCV-FFI“包装器”功能。 为了每个算法,输入图像是一个8位单通道(灰度)2.1像素的测试模式(图1)。 跟踪测量系统时间的计时与代码中发现相关的清单相关联,而不包括加载输入图像的开销。 每个算法运行1000次同时第一次执行被丢弃,为了避免缓冲效果。 所有的实验都是运行在一个英特尔酷睿i7-3770k,使用OpenCV2.4.2编译和标准的“释放”优化。 第一种情况下计算输入图像的单维(x-方向)Sobel算子。 在这种情况下,OpenCV的内置cvSobel函数可用于C和纯Ruby映射。 包装器的实现在MAT调用cvSobel时是一个微不足道的成员函数。 如表所示,在Ruby调用OpenCV函数的开销可以忽略不计。 表1.SOBEL算法的相对性能。 表2.色彩映射操作的相对性能。 第二个操作模拟色彩映射操作输入图像的灰度转换为三通道RGB图像。 色彩映射操作给出的浮点值在[0: 1]范围,需要转换和扩展的8位整型图像,从其本源生成三个独立通道(R,G,B),同时在每个通道上执行计算。 然后三个浮点图片组合成一个三通道RGB图像,并且重新缩放范围[0: 255]。 如果灰度图像按[0: 1]的比例缩放为v,那么三个通道的操作就是(r=v;g=1−v;b=0.2×v;)。 而数学密集型少于索贝尔的例子,这个代码示例需要额外的复制和整体形象的转换。 Ruby提供了两个版本的计算空间。 在Ruby空间中第一个使用算术运算直接映射到OpenCV函数调用。 这个版本的损失速度是由于额外的临时变量的创建引起的。 这可以通过实现更复杂的img.convert_scale功能消除。 虽然语法紧凑的成本和API的复杂性将是可观的。 同样,最后一行包含一个临时的取消在C版本的就地扩展(由范围图像合成)。 备用版本使用Ruby公约的闭包(传递到地图操作)。 时间的结果显示,有一个重大的损失就是执行计算以“Ruby的方式”结束。 使用Ruby进行图像处理突显出一个伟大的低效。 像许多脚本语言一样,Ruby有强大的工具的操作和迭代任意对象的列表。 在Ruby中,句法关闭,一个lambda函数,提供了一个干净的方法反复地来执行一个任意迭代数组或列表的元素操纵。 事实上,它可以认为Ruby明确促进一个迭代数组的对象,“for-each”操作的首选实现一组广泛的数组操作。 同样,许多机器视觉算法是在一个图像或矩阵中通过重复操作或迭代每个像素。 不幸的是,OpenCV和Ruby概念不能有效地聚集在一起。 而机器视觉算法可以为每个低成本迭代进行优化,本质上Ruby版本是完全通用的。 解释器无法预测开发人员会将什么放进一个给定的闭包。 因此,迭代是一个开销相对较高的操作, 随着在数组中的成本积累和有大量元素存在。 这种区别是明显的代码示例9和10的相对速度。 从OpenCV-FFI需要获得最佳性能需要一个弃用的“for-each”理念体系来尽可能的支持整个数组操作。 清单4.C中的索贝尔操作。 CvMat*out=cvCreateMat(img->rows,img->cols,CV_8UC1); cvSobel(img,out,1,0,3); 清单5.C中的COLORMAP操作。 CvMat*r=cvCreateMat(img->rows,img->cols,CV_32FC1); CvMat*g=cvCreateMat(img->rows,img->cols,CV_32FC1); CvMat*b=cvCreateMat(img->rows,img->cols,CV_32FC1); cvConvertScale(img,r,1./256,0); cvSubRS(r,cvScalarAll(1.0),g,NULL); cvConvertScale(r,b,0.2,0); CvMat*rgb=cvCreateMat(img->rows,img->cols,CV_32FC3); cvMerge(b,g,r,NULL,rgb); cvConvertScale(rgb,rgb,256,0); 清单6.在纯OPENCV-FFI中的SOBEL操作。 out=cvCreateMat(img.rows,img.cols,: CV_8UC1) cvSobel(img,out,1,0,3) 清单7.在纯OPENCV-FFI中的COLORMAP操作。 r=cvCreateMat(img.rows,img.cols,: CV_32F); g=cvCreateMat(img.rows,img.cols,: CV_32F); b=cvCreateMat(img.rows,img.cols,: CV_32F); cvConvertScale(img,r,1.0/256,0); cvSubRS(r,cvScalarAll(1.0),g,nil); cvConvertScale(r,b,0.2,0); rgb=cvCreateMat(img.rows,img.cols,: CV_32FC3); cvMerge(b,g,r,nil,rgb); cvConvertScale(rgb,rgb,256,0); 清单8.在OPENCV-FFI包装器中的索贝尔操作。 classCVFFI: : Mat defsobel(args={}) dst=twin cvSobel(self.to_CvMat,dst.to_CvMat, args[: xorder]||0, args[: yorder]||0, args[: apertureSize]||3) dst end End 清单9.在OPENCV-FFI包装器中的COLORMAP操作。 r=img.convert(: CV_32F)/256 g=1.0-r b=r*0.2 [b,g,r].merge(: CV_32FC3)*256 清单10.作为一个RUBY闭包执行COLORMAP操作。 rgb=img.map(: CV_32FC3){|r,c,val| r=val/256.0 g=1.0-r b=0.2*r [b,g,r].map! {|x|x*256} } Ⅶ.进一步研究和关注 本文档中提供的工作在OpenCV2.2版下开始。 后续版本的OpenCV(目前达到2.4)显示共同努力反对CAPI支持c++。 大部分其间的版本中引入的新功能仅仅出现在c++API。 混合的C和c++API一直都在OpenCV的代码库中,同时许多功能发生C++包装C函数,反之亦然。 到目前为止OpenCV-FFI库中的描述,c++区域包装(在opencv-ffi-ext发现)已经被写入仅存在C++API中的手动back-port函数。 这些包装器回波设计模式在OpenCV代码库本身被发现。 然而,如果OpenCVCAPI阻止进一步发展,很明显,这将是一场艰苦的战斗。 有几个未来发展的方向。 第一是继续FFI-based方法,必要的实现C垫片。 这样的缺点就是需要增加投资在c++中区域转换代码,特别难堪的,因为大多数的Ruby开发集中于C表示通过opencv-ffi-wrappers表现更加面向对象的方式。 然而,如果c++区域包装被OpenCV社区接受,他们可能延长给用户的CAPI的可用性,并且用户会更喜欢它。 它也有调整OpenCV-FFI和OpenCV的发展的突出优势,使OpenCV代码库的新发展可以利用在OpenCV-FFI中,同时舍弃一个开发人员熟悉使用OpenCV的Ruby-spaceAPI。 另一种选择是使用相同的开发工作只编写c++Ruby-C包装器函数。 目前为止这将是与该项目的精神相反的。 或许,它可能是一个更实际的解决方案,特别是考虑到代码将c++对象映射到Ruby对象,这可能更简单。 这个过程可能加速了的项目如同Rice,一种对c++代码的Ruby-C包装器自动发展的工具。 长期关注可能会被C和c++代码的OpenCV混合物影响,而且,如果混合这两个有性能问题存在——尽管类似翻译在当前的策略需要对任何c++区域垫片。 另一种方法是使用不同的技术来将OpenCV桥接到Ruby。 例如,SWIG可以被研究,或者可以认为一个Ruby相当于OpenCV解析器和包装器脚本生成器。 这种方法将受益于最初的Python开发,特别是大量的面包屑宏在OpenCV源代码。 然而,这仍将带来重大的发展。 它可能被Python和Ruby社区诅咒,但也许现有的Python解析器可以被修改来生成Ruby包装器代码! 最后,可以采用一个备用机器视觉库,或者在Ruby中开发本地机器视觉库(纯Ruby或编译扩展)。 这将是最不可取的选择,因为它将需要大量的冗余的发展和导致OpenCV开发者广泛的生态系统的分歧。 引用 [1]H.Dahlkamp,“Self–supervisedmonocularroaddetectionindesert terrain,”inInProc.ofRobotics: ScienceandSystems(RSS),2006. [2]P.Phillips,P.Flynn,T.Scruggs,K.Bowyer,J.Chang,K.Hoffman, J.Marques,J.Min,andW.Worek,“Overviewofthefacerecognition grandchallenge,”inComputerVisionandPatternRecognition,2005. CVPR20
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 对于 Ruby 编程 语言 使用 OpenCV FFI 机器 视觉 延伸