没有合适的资源?快使用搜索试试~ 我知道了~
现代C中的泛型编程用于图像处理
https://theses.hal.science/tel-03922670Michaël Roynard0HAL编号:tel-039226700提交日期:2023年1月4日0HAL是一个多学科开放获取的存储和传播科学研究文档的平台,无论这些文档是否已发表。这些文档可以来自法国或国外的教育和研究机构,或者来自公共或私人研究中心。0HAL(L’archive ouvertepluridisciplinaire)是一个多学科开放获取的存储和传播科学研究文档的平台,这些文档可以是已发表或未发表的,来自法国或国外的教育和研究机构,公共或私人研究中心。0现代C++中的泛型编程用于图像处理0引用此版本:0Michaël Roynard. 现代C++中的泛型编程用于图像处理. 信号与图像处理. Sorbonne Université, 2022. 英文.�NNT : 2022SORUS287�. �tel-03922670�230致谢0在EPITA的LRDE进行博士学位期间的几年是丰富而充实的经历。我要感谢所有在这个博士论文旅程中支持我的人。我要真诚地感谢Benjamin Perret和Pascale LeGall同意审查我的论文。此外,我还要感谢Hugues Talbot同意担任我的评委会主席,以及LaurentNajman、Camille Kurtz和Joël Falcou同意成为我的评委会成员。我要衷心感谢我的导师ThierryGéraud。你从一开始就招募了我并对我充满信任。尽管这个旅程曲折而充满变故,但你的建议和评论始终准确无误,对我在最佳状态下答辩我的论文非常有帮助。我还要感谢我的论文主管EdwinCarlinet,在整个旅程中给予我宝贵的帮助。谢谢你在我最需要的时候推动我前进,并陪伴我走到最后。我特别要感谢ClaireLecocq,感谢她的支持和建议,使我能够清楚地找到通向这个旅程终点的道路。我要花时间感谢Daniela,她一直陪伴着我度过整个博士学位期间。你在我刚开始时帮助我融入,并始终帮助我,特别是在每个博士学位阶段的行政任务上。特别感谢我们亲爱的系统管理员Clément。你总是准确无误、乐于助人,并迅速使我的计算机恢复正常工作!谢谢你的系统管理员笑话!它们真的能提高情绪。此外,我还要感谢图像团队的所有成员Jonathan、Joseph、Guillaume、Élodie、Nicolas和Olivier,感谢他们愉快的心情和在整个论文中的帮助。当然,我还要感谢Spot团队(自动机)的成员,特别是Alexander、Sven、Jim、Adrien、Philipp和Didier。与你们一起工作(现在仍然如此)是一种真正的享受。我要热情地感谢博士团队,他们总是在那里分享忧虑、给予建议、喝一杯啤酒,这些都是博士生生存所必需的。衷心感谢Ludovic和Duy,你们现在已经走上了自己的道路。祝你们一切顺利。衷心感谢Baptiste、Caroline、Minh、Charles、Zhou、Yizi、Antoine、Anissa和Florian的支持,特别是在休息时间的笑话和政治辩论。下次我们再一起喝一杯啤酒时,让我们重新改变世界!最后,我要感谢我亲爱的家人,在这个旅程的开始到结束,你们始终给予我坚定的支持。你们一直相信我。谢谢你们。没有你们,我将无法完成。450摘要0C++是一种多范式语言,使有经验的程序员能够建立高效的图像处理算法。这种语言的优势来自于几个方面。C++是高级的,可以开发强大的抽象和混合不同的编程风格以便于开发。同时,C++是低级的,可以充分利用硬件提供最佳性能。它也非常便携和高度兼容,允许从高级、快速原型语言(如Python或Matlab)调用算法。C++真正闪耀的一个最基本的方面是泛型编程。泛型编程使得在不损失性能的情况下,可以在不同类型的对象(图像)上开发和重用软件模块。然而,协调泛型性、效率和简单性并不是一件简单的事情。现代C++(2011年后)引入了新的功能,使语言更简单、更强大。在这篇论文中,我们首先探讨了C++20的一个特定方面:概念,以建立一个具体的与图像相关的类型和算法的分类。其次,我们探索了C++20的另一个新增功能:范围(和视图),并将这种设计应用于图像处理算法和图像类型,以解决诸如定制/调整图像处理算法的困难程度等问题。最后,我们探索了关于如何在静态(编译时)泛型C++代码和动态(运行时)Python代码之间建立桥梁的可能性。我们提供了自己的混合解决方案,并对其性能进行了基准测试,并讨论了未来可以使用JIT技术做些什么。考虑到这三个方面,我们将解决如何协调泛型编程、效率和易用性的问题。0C++是一种多范式编程语言,使有经验的开发人员能够开发图像处理算法。该语言的优势基于多个方面。C++是高级的,这意味着可以开发强大的抽象,结合多种编程风格来简化开发。同时,C++仍然是低级的,可以充分利用硬件提供最大的性能。它也是可移植和高度兼容的,可以与其他高级语言(如Python或Matlab)进行快速原型开发。C++最突出的一个基本方面是泛型编程。泛型编程使得开发和重用不同类型(类型)的软件模块(如图像对象)成为可能,而不会损失性能。然而,要协调泛型、性能和易用性方面并不是一件简单的事情。现代的C++(2011年后)引入了一些新功能,使其更简单、更强大。在本论文中,我们首先探讨了C++20的一个特定方面:概念,目的是构建与图像处理相关的类型分类。其次,我们探索了C++20中添加的另一个功能:范围(和视图)。我们将这种设计应用于图像处理算法和图像类型,以解决相关问题,特别是与定制图像处理算法的困难相关的问题。最后,我们探索了如何在静态的泛型C++代码(编译时)和动态的Python代码(运行时)之间建立桥梁的可能性。我们提供了一种混合解决方案,并对其性能进行了测量。我们还讨论了未来可以探索的方向,特别是涉及JIT技术的方向。鉴于这三个方面,我们希望解决泛型、性能和易用性方面的问题。670长摘要0引言0如今,计算机视觉和图像处理(IP)已经无处不在地融入人们的日常生活中。每当我们经过一个闭路电视摄像头,每当我们去医院做核磁共振检查,每当我们开车经过一个测速摄像头,每当我们使用电脑、智能手机或平板电脑时,它都存在其中。我们无法再避免它。使用这项技术的系统有时很简单,有时更复杂。此外,这项技术的使用目的也很多,如空间观测、医学成像、提高生活质量、监视、控制、自主系统等。因此,图像处理的研究范围很广,尽管已经有大量的先前工作做出了贡献,但仍有很多可以探索的地方。0让我们以一个现代智能手机应用程序为例,该应用程序提供面部识别功能,以识别出照片中的人物。为了提供准确的结果,该应用程序需要通过多个步骤进行许多不同的处理。此外,还有许多需要处理的变量。我们可以列举(非详尽)天气、光照、分辨率、方向、人数、人的位置、人与物体/动物的区分等。所有这些元素都需要仔细处理,以最终识别出照片中的人物。应用程序没有告诉您的是,在幕后的图像处理流水线的复杂性,大部分情况下,无法在设备上完整执行(智能手机、平板电脑等)。事实上,图像处理在计算资源方面是昂贵的,如果整个流水线在设备上执行,将无法满足用户的时间要求。此外,对于最后一部分“识别照片上的人物”,应用程序需要将经过预处理的照片输入事先通过深度学习技术训练的神经网络,以给出准确的响应。存在能够将神经网络嵌入到手机中的技术,如MobileNets[135],但在操作能力方面仍然有限。它可以检测照片中的人,但无法提供关于这个人是谁的答案。这就是为什么准确的神经网络系统通常在云技术中进行抽象,只能通过互联网使用。当用户上传他的照片时,他无法想象将使用多少技术和计算资源来找到照片中的人物。0我们现在明白,为了构建与照片或视频交互的应用程序,我们需要能够在多种设备上(智能手机、平板电脑等)进行准确、快速和可扩展的图像处理。为了实现这个目标,图像处理从业者需要两种工具。第一种是原型设计环境,一个工具箱,允许从业者开发、测试和改进应用程序逻辑。第二种是生产环境,部署由从业者开发的可行版本的应用程序。两个环境可能有不同的需求。一方面,原型设计环境通常需要快速的反馈循环进行测试,以及先进算法和现有软件的可用性。这样,从业者可以轻松地在其之上构建,并且足够快,以便在测试许多原型时不需要等待很长时间来获得结果。另一方面,生产环境必须稳定、弹性、快速和可扩展。80当我们现在看行业标准时,我们注意到Python编程语言是原型设计的主要选择。然而,Python可能不适合在生产中推出一个可行的原型,并在之后进行最小的更改。我们发现,从这种方式进行时,从算法效率和更好的硬件使用方面,从业者无法利用许多优化机会,这是不理想的。当设计应用程序时,拥有可以适应尽可能多用例的基本低级构建块将更加高效。我们区分两种用例。第一种是从业者面临的类型或算法的多样性。第二种是从业者可能希望运行其程序的硬件的多样性。目标是拥有可以智能地利用许多优化机会的构建块,无论是输入数据类型/算法还是目标硬件。然后,从业者将获得重要的性能改进,而无需专门调整其应用程序。因此,引入了通用性的概念。它旨在提供一个共同的基础,关于当传递给复杂应用程序所需的基本算法时,图像应该如何行为。这样,理论上,只需要编写一次算法,就可以与任何给定类型的图像一起使用。0最后,通常人们知道通用性、效率和易用性之间存在一个三方规则。该规则指出,只有牺牲第三个方面,才能同时拥有前两个方面。如果想要通用和高效,那么朴素的解决方案将非常复杂,有很多参数。如果想要通用和易于使用的解决方案,那么默认情况下它将不太高效。最后,如果想要易于使用和高效的解决方案,那么它将不太通用。为了说明这个规则,我们可以在现有库中找到例子。一个在C++中非常通用和高效的库是Boost[169],它也以难以使用而闻名。诸如Boost.Graph、Boost.Fusion或Boost.Spirit之类的组件很难使用。此外,一个既通用又易于使用的库是由NielsLohmann编写的Json解析器[172],它力求处理每种用例,同时保持非常易于集成和在用户代码中使用(通过提供DSL领域特定语言,将C++构造解析为JSON的语法非常接近本地C++代码)。然而,这是有代价的,解析器比针对速度进行优化的Json解析器(如simdjson[171])要慢。最后,还有很多用户友好且高效的代码示例,但不具备通用性。我们可以举出易于使用且高效(大量手写的SIMD/GPU代码)的Scikit-image [120]和OpenCV[29],但由于设计选择的原因,它们不具备通用性。0在这篇论文中,我们选择通过继续在Pylene[140]上的工作来研究图像处理库。但仅仅在库级别上工作将限制我们的工作的可用性,从而限制其影响力。这就是为什么我们希望通过提供一个可以在Python等动态语言中使用的软件包来接触到原型用户,而不会牺牲效率。特别是,我们希望能够在Jupyter笔记本中使用。对我们来说,达到能够渗透到教育领域的可用性是一个非常重要的目标,而这是Python的优势。在这个库中,我们展示了如何在保持易于使用的同时实现通用性和效率。在这样做的过程中,我们努力突破之前提到的规则。这个库的范围仅限于数学形态学[111,83]和提供非常多功能的图像类型。我们利用现代C++语言及其与通用性和性能相关的许多新特性,突破了图像处理领域的这一规则。最后,我们试图通过在这两个世界之间建立桥梁,将静态世界的低级工具和概念带到高级和动态原型世界中,以实现更好的传播和使用便利。0以这种理念为指导,本文旨在介绍我们在C++语言应用于图像处理领域的论文工作。它的组织如下:90泛型编程(通用性)我们对通用性的概念进行了最新的综述。我们解释了它的起源,它是如何发展的(特别是在C++语言中),它解决了哪些问题,它又带来了哪些问题。我们解释了为什么图像处理和通用性能够很好地结合在一起。最后,我们介绍了允许通用性存在于动态世界(如Python等解释性语言)的现有工具。0图像处理的分类:图像类型和算法我们提出了我们在图像处理领域的第一个贡献,即对不同图像家族以及不同算法家族进行分类的全面工作。我们解释了概念的概念,并说明它如何应用于图像处理领域。此外,我们解释了如何从现有代码中提取概念,如何利用它使代码更高效和可读。最后,我们以一系列与图像处理领域相关的概念的形式提供我们的观点。0我们提出了第二个贡献,即将View的概念(来自C++语言,关于范围的工作[143])推广到图像。这使得创建轻量级、廉价复制的图像成为可能。它还通过在代码中直接链接操作,以一种直观的方式简化了图像处理流水线的设计。范围是新设计的基石,以便在算法中更容易使用图像,并进一步扩展其通用行为。最后,我们讨论了惰性求值的概念以及视图对性能的影响。0静态世界与动态世界之间的桥梁我们提出了我们的第三个贡献,即一种将编译语言(如C++)的通用功能授予动态语言(如Python)的方法,以便简化原型阶段和生产阶段之间的差距。事实上,能够将C++的通用代码(其通用性在编译时解决,我们称之为“静态世界”)与依赖于预编译软件包二进制文件的Python的动态代码(我们称之为“动态世界”)有效地通信,这确实并不明显。我们也不能要求用户每次想要从Python使用我们的库时都提供和使用编译器。我们讨论了可以考虑的现有解决方案以及它们的优缺点。最后,我们讨论了如何设计一个混合解决方案来建立静态世界和动态世界之间的桥梁。0泛型编程(泛型性)0在自然语言中,当某物能够同时适用于多个目的并且效率还不错时,我们说它是通用的。例如,计算机是一种通用工具,可以用来编写文档、访问电子邮件、浏览互联网、玩视频游戏、观看电影、阅读电子书等。在编程中,当一个工具能够适用于多个目的时,我们称之为通用工具。例如,gcc编译器可以编译多种编程语言(C、C++、Objective-C、Objective-C++、Fortran、Ada、D、Go和BRIG(HSAIL)),并且可以针对多种体系结构(IA-32(x86)、x86-64、ARM、SPARC等)进行目标编译。因此,我们可以说gcc是一个通用编译器。此时重要的是要注意,即使一个工具被认为是通用的,它也有其能够做和不能做的范围。例如,尽管编译器支持多种语言和体系结构,但它无法打电话或冲咖啡。因此,重要的是要注意通用性是一个限定某物的方面。我们研究与库和编程语言相关的通用方面。本论文有意忽略了与目标体系结构相关的通用方面。实际上,能够编写和/或生成能够在大量不同硬件上运行的代码是非常重要的。100体系结构是一个独立的研究领域,不是本论文的主要焦点。它也被称为异构计算。相反,我们将重点关注与库级别和编程语言级别的泛型性相关的方面。0库中的泛型性是指它能够处理多少用例的基数。库总是提供自己的数据结构,以表示和赋予用户要处理的数据以意义,并提供处理这些数据并提供不同类型结果的算法。当(i)库的数据结构允许用户无限制地表达自己,并且(ii)其算法库足够大以执行用户对其数据的任何操作时,该库将被标记为通用[15]。实际上,这样的库并不存在,总会有限制。研究这些限制以及推动它们的原因是理解如何在未来通过开发新的硬件和/或软件支持来克服它们的关键。0编程语言中的泛型性是指语言能够在大量数据结构上执行相同的代码[31],无论是原生的(char、int等)还是用户自定义的。如今,编程语言能够做到这一点是至关重要的。事实上,在信息技术无处不在的世界中,软件开发人员编写的代码量是惊人的。随之而来的是大量的错误和安全漏洞。通过使用一种本地支持更多功能的编程语言,可以以更少的代码实现更多的功能,从而降低开发和维护成本。编程语言提供了许多实现泛型性的方式,这取决于语言的内在特性:编译型还是解释型,本地支持还是模拟支持等。在深入探讨泛型性对库和编程语言的影响之前,让我们先介绍一些术语以便理解。首先是类型的概念。类型(或数据类型)是数据的属性,它告诉编译器或解释器程序员打算如何使用数据。大多数编程语言支持基本数据类型(也称为原始类型),如整数、浮点数、布尔值和字符(ASCII、Unicode等)。这个数据属性定义了可以对数据执行的操作、数据的含义以及数据在内存中的大小(然后可以将数据存储在堆、栈等中)。数据类型提供了一组值,表达式(例如变量、函数等)可以从中获取这些值。在编程语言中,我们可以区分动态类型和静态类型。静态类型语言是那些变量声明为特定类型的语言。这个变量在声明的范围内不能保存来自另一种类型的数据。静态类型的编程语言有Ada、C、C++、Java、Rust、Go、Scala。动态类型语言是那些变量可以重新分配为不同类型的值的语言。变量的类型随后动态更改以适应其保存的新值。动态类型的编程语言有PHP、Python、JavaScript、Perl。能够始终知道变量保存的类型(静态类型语言)的结果是双重的。对于开发人员来说,更容易推理代码并发现错误。对于编译器来说,可以生成针对该数据类型的优化二进制代码(矢量化等)。能够在运行时改变变量可以保存的类型的结果主要是为了提供原型设计的目的。在调整Jupyter笔记本时,不限制每个变量只能使用单一类型,可以更快地迭代原型。在图像处理中,图像Im在包含点的域D上通过关系@x P D,y“Im p xq来定义,其中y是点x处图像Im的值。当将此定义转换为编程语言时,这总是转化为一个复杂的数据结构。该数据结构必须了解包含图像数据的数据缓冲区以及图像的大小和维度的信息。此外,为增加难度,110在编写源代码时,并不总是知道精确定义数据结构所需的信息。实际上,一个非常简单的用例是从文件中读取图像以将其加载到内存中。文件可以包含不同数据类型的图像,程序仍应正常工作。解决此问题有多种方法,我们正在解决它们。将通用性的概念应用于图像处理,我们可以推断出我们需要两个重要方面才能实现通用性。首先,我们需要将数据结构及其拓扑和底层数据与算法解耦。实际上,我们希望我们的算法支持尽可能多的数据结构。其次,许多算法共享相同的计算形状,可以一起因式分解。0图像 2D 图形 网格0输入:0输出:0相同的代码在所有这些输入上运行。0图1:分水岭算法应用于三种不同的图像类型[118]。0通用性可以有两种不同的含义,这取决于你问的人。例如,有些人会认为通用性是一个高级方面,当一个工具处理他的所有用例时,会称之为“足够通用”。其他人会认为通用性是一个与机器(代码)相关的低级方面,能够构建很多不同的工具。“足够通用”以制作很多不同工具。两者都没有错。然而,为了理解起见,我们将为每种情况使用不同的词语。一个足够通用以处理很多用例的工具将被称为“通用”。最后,对于一个旨在能够构建很多不同工具的工具(即提供能够处理任何用例的编程框架),我们将使用“通用”。在这篇论文中,通用性将涉及代码,意味着能够处理任何用例的编程框架。图1 [92]说明了相同的通用分水岭实现应用于2D图像、图形和网格。我们介绍了通用编程的起源,它可以追溯到1988年,以及它如何被整合到Ada编程语言中,然后是C++编程语言。此后,它进一步发展,引入了概念的概念,这样就可以完全利用通用编程而不需要使用晦涩的调整和工具。0我们探索了从库内部实现通用性概念的可能性。实际上,有三种技术使用户能够编写一次高级算法,然后在每种类型上运行。它们是代码复制方法、泛化方法和包含和参数化多态方法[72]。120最后,我们介绍了C++模板的固有限制,即它们仍然处于静态世界(编译时)。通用性(在C++模板的意义上)在最终交付给用户的二进制文件中不存在。最终用户在其动态世界(运行时)无法使用通用(C++代码)工具。我们讨论了可能的不同方法来弥合静态(编译时)和动态(运行时)世界之间的差距。然后,我们将广泛使用通用性来介绍本论文的第一个贡献:与图像处理相关的概念分类学。0图像处理的分类学:图像类型和算法0在这篇论文中,我们继续研究如何将C++语言中的所有这些新的通用功能应用于图像处理领域。这使我们能够在我们偏爱的领域上以实际方式测试它们,同时记住我们在这方面的过去工作,无论是成功还是失败。然而,从代码中产生概念是一种逐渐发展的方式。因此,第一项工作将是对所有现有图像算法进行清点,以及对我们能够想到的所有图像处理算法(包括基本和更复杂的算法)进行清点。这样,我们将注意到从相似的图像类型或相似的算法中出现的行为模式。然后,我们将能够从清点中提取行为模式,以产生一个完整的分类学,形成与图像处理相关的概念框架。我们提出概念不是根据数据结构设计的,而是根据算法设计的。实际上,一个概念是从一段代码(算法)中提取一致的行为模式,并对其进行命名以赋予其意义。通过一个简单但具体的例子,我们以教学的方式介绍了如何从图像处理算法(伽马校正)中提取概念。0图像类型0图像LUT0填充版本10可写图像0填充版本20(a)不同版本的填充算法0图像类型0可写图像0填充版本20内存中的连续缓冲区?0专用算法0(b)版本内的特化0图2:算法版本集合(a)及其在版本内的特化(b)。0然后我们解释了理论上图像类型之间的关系。我们介绍了不同图像类型的集合以及算法在这些集合中的存在方式,这引入了算法版本的概念。对于支持的每个图像类型集合,算法将具有不同的版本。我们将其与算法的特化(在图2中)区分开来,后者是利用机会(与属性相关)进行优化并提高性能的能力。然后我们描述了算法画布的概念,它是图像处理算法分类法的结果。实际上,有三个主要的算法族:逐像素算法(二值阈值),局部算法(膨胀)和全局算法(Chamfer距离变换)。我们主要关注局部算法以及如何通过相同的代码画布编写它们。实际上,例如,膨胀和腐蚀之间唯一的区别是运算符(max vs.min)。然后我们讨论如何利用这些画布来可能解决异构计算问题。14+∗ima1alpha∗ima21 − alpha0const uint8_t * iptr = ima1 + y * stride1; uint8_t * optr = ima2 + y *stride2; for (int x = 0; x < width; ++x) optr[x] = iptr[x] * alpha +optr[x] * (1- alpha); } }0这段代码有几个缺陷。它对输入图像做出了强烈的假设:数据缓冲区的连续性和形状(2D)。假设我们的用户现在想要将算法限制在图像内的特定区域。维护者现在必须提供一个重载的算法,其中包含一个额外的输入参数,对应于感兴趣区域。假设用户现在想要支持操作3D图像。维护者现在必须提供两个额外的重载,其中包含一个额外的步幅参数(一个用于基本算法,一个用于感兴趣区域限制算法)。现在假设用户只想操作红色通道。现在维护者必须支持并添加算法的每个通道和/或颜色类型的额外重载。对于维护者想要提供给用户的每种定制点,复杂性都会增加很多。当然,通过巧妙地使用计算工程技术(代码因子化等)可以防止代码重复,但复杂性仍然会泄漏到API中。因此,另一种解决方案是使用户能够在算法上游透明地执行这些限制,以便下游算法易于编写、理解和维护。为了实现这一点,我们需要将图像的抽象级别提高一层,以便我们可以在图像级别上工作。然后,alpha混合算法将被编写如图4所示。0ima0← 0.2 ×0ima10+ 0.8 ×0ima20图4:以图像级别编写的Alpha混合算法。0通过引入视图到图像处理中,可以以这种方式表达算法。现在,图像是一个视图,用户在将其提供给算法之前可以根据需要对其进行限制/投影/操作。甚至整个alpha混合算法也可以完全以视图的形式重写,如图5所示。0auto alphablend =0[](auto ima1,auto ima2,float alpha) {0返回alpha * ima1 +(1-alpha)* ima2; };0图5:Alpha混合,使用视图,表达式树的通用实现。0能够在将图像馈送到算法之前对其进行强大的操作,完全消除了在维护和记录所有相关可选参数的同时,具有相同算法的多个重载的初始问题。实际上,为了对基本输入图像执行alpha混合变换,用户只需执行以下操作:0auto ima1,ima2 = /* ... */; auto ima_blended =alphablend(ima1,ima2,0.2);160auto operator +(Image A,Image B){0返回transform(A,B,std :: plus <>()); } auto togray = [](Image A){返回transform(A,[](auto x) {返回(x.r + x.g + x.b)/ 3.f; };)}; autosubquantize16to8b = [](Image A) {返回transform(A,[](float x){返回uint8_t(x / 256 +.5f); }); };0auto input = imread(...); auto MyComplexImage =subquantize16to8b(togray(A));0图8:使用高阶原始视图创建自定义视图操作符。0此外,视图是延迟计算的。因为操作记录在图像视图中,所以这种新的图像类型允许基本图像类型与算法混合使用。在图8中,视图的创建本身不涉及任何计算,而是将计算延迟到调用表达式v(p)时。由于视图可以组合,因此评估可以延迟得很远。图像适配器是模板表达式[20,40],因为它们记录用于生成图像的表达式作为模板参数。视图实际上表示一个表达式树(图5)。此外,视图是高效的。采用传统设计,管道的每个操作都是“独立的”。每个操作都需要为输出图像分配内存,并且每个操作都要求完全遍历图像。这种设计简单、灵活、可组合,但不是内存高效或计算高效。采用延迟评估方法,图像只遍历一次(应用膨胀时),这有两个好处。首先,没有中间图像,这非常节省内存。其次,由于更好地使用了内存缓存,遍历图像更快,并执行了最佳的选择性遍历。实际上,在我们的示例(图6)中,从膨胀算法处理RGB16像素直接将其转换为灰度,然后将其子量化为8位,并最终使其可用于膨胀算法。它的作用就像我们正在编写一个将所有这些操作组合在一起的最佳运算符。这种方法与某些HPC规范中提供的内核融合操作有些相关[150],但视图融合仅由C++编译器优化[139]。选择性方面介入的是在处理管道的某一点选择感兴趣区域时。实际上,只有在处理管道的最后一步才进行此选择,但整个管道的所有操作都仅在感兴趣区域上执行。最后,视图提高了生产力。所有逐点图像处理算法都可以(也应该)通过使用一行视图进行直观重写。transform视图是实现该点的关键。这意味着在原型化算法时,从业者可以使用一种新的抽象级别。减少了实现功能所需的时间,因此也减少了反馈循环时间。这自然地为从业者带来了生产力的提升。0静态世界和动态世界之间的桥梁0在编程世界中,有三个主要的编程语言家族[38]。有(i)编译型编程语言,如C、C++、Rust或Go,(ii)解释型编程语言,如Python、PHP、Lisp或Javascript,以及(iii)混合型编程语言,如Java或C#。后者有一个快速编译过程,将源代码编译成中间字节码。然后,这个字节码通过主机(运行器)上的解释器进行解释。我们设计了许多解决静态和动态世界之间各种问题的解决方案。我们提出了我们的混合解决方案,可以使我们的C++模板库(静态)能够从Python(动态)中使用。我们讨论了几种实现的方法。170C++/Python绑定0NumPy.ndarray Python图像多通道信息0C++ py::buffer C++类型擦除ndimage_buffer0类型转换0C++具体类型ndimage0图9:从Python到C++的桥梁,通过Pybind11和一个类型擦除的C++类。0介绍了这个特性,它们的优点和缺点。此外,我们引入了一个新的抽象层,即值集,它是在实现图像处理算法时用于操作底层图像值的标准方法。这个新的抽象层使用户能够从Python端注入代码到已编译的C++例程中。然而,层层叠加抽象层,甚至调用Python代码都会带来性能损耗。这就是为什么我们进行了基准测试来概述我们解决方案的成本。这个基准测试比较了我们的拉伸算法的四个版本,其实现和使用方法在手稿中详细说明。结果显示在表1中。0分派类型 计算时间 ∆计算时间0具有本地C++值类型的本地值集(基线)0.0093秒 0 具有本地C++值类型的虚拟分派值集0.1213秒 ^13具有C++类型擦除值的虚拟分派值集1.0738秒 ^115 注入的Python值集与本地C++值类型21.5444秒^23160表1:我们拉伸算法的所有版本的基准测试。0这个基准测试显示,每次在基线之上添加一个抽象层,用户必须预计他的代码性能会减慢10倍。此外,调用Python代码比基线慢得多(2300倍!)。这表明,对于执行时间较长的代码,重新编译模板化的C++库并添加一个已知类型要比从Python中注入类型更有意义。能够注入Python代码可以方便原型设计,并提高用户编写代码的速度。然而,基准测试显示,一旦原型需要扩展到生产环境,这种方法就不可行了。0续:基于JIT的解决方案,优点和缺点。我们的混合解决方案确实有优势,但注入自己的类型从Python端的速度非常慢是一个巨大的缺点。还有另一种解决方案,这篇论文没有机会深入研究。这个解决方案基于一种已知的技术:即时编译(JIT)编译,它以前在图10中已经说明过(它本身基于生成式编程的概念[30])。像AsmJit[91]这样的库能够通过在C++代码中进行调用直接生成机器码。事实上,这是一种已经被解释型语言(如Java或PHP)使用的技术,用于为解释器认为“热点”的源代码部分即时生成本机和优化的机器码。当将这种策略应用于我们的问题时,这意味着用户必须能够通过在使用时注入所需的类型来从模板化的通用C++代码中编译本机机器码。这种操作将严重地增加用户的负担,而且众所周知,编译C++代码特别复杂且耗时。此外,一旦编译了C++代码,库需要能够自动生成Python绑定,并在接口中处理NumPy.ndarray类型。有几种解决方案可以达到这个目标。180在运行时0字节码编译0.py,Python源代码0解释器0热代码检测0结果0字节码编译器0.pyc,机器本地代码0图10:解释型语言:运行时0第一种解决方案基本上是使用系统调用来编译C++代码,一旦模板类型已知并在源代码中明确实例化。这种解决方案需要谨慎的代码生成设计,用户实际上必须在计算机上拥有编译器。此外,用户必须解决所有库依赖关系,例如IO等的freeimage。这个解决方案在VCSN库[108]中被设计出来。实际上,每当用户在Jupyter笔记本中声明一个新的自动机时,相应的源代码会在后台进行编译,然后缓存。当最终执行环境(操作系统、已安装的软件)事先不为人所知时,这是一个非常危险的解决方案。现在,这个问题可能较小,但仍需要维护库和容器解决方案来使用它(Docker)。0第二种解决方案是使用Cython[88]。它是一个转译基础设施,可以直接将Python源代码转换为C语言源代码,以便可以通过标准C编译器进行编译,只需链接Python/CAPI。这消除了编写谨慎的代码生成例程、系统调用到C++编译器以及解决所有依赖项的负担。该基础设施为用户处理一切。Cython甚至支持C++模板代码[176],这对我们的用例是必需的。0第三种解决方案是依赖于最近的项目,这些项目都依赖于LLVM基础设施。我们可以特别注意AutoWIG[141]、Cppyy [130]、Xeus-cling [173]和Pythran[123]。AutoWIG具有基于LLVM/Clang的内部代码,用于解析C++代码以生成并编译使用Mako模板引擎的SwigPython绑定。AutoWIG与Cython结合使用,例如,允许用户生成与自定义Python结构相关的C代码。然后,只需调用AutoWIG,它将解析C代码并将其注入到C++库中,以为用户生成适当的绑定。至于Cppyy,它基于LLVM/Cling,一个C++解释器,可以直接从Python字符串中解释C++代码。这使得很容易注入自定义类型,无论是在Python代码中(使用Cython转译)还是在C++代码中(由Cling直接解释)。然后,基础设施从模板化的C++库为注入的类型生成适当的绑定。Xeus-cling是一个即插即用的Jupyter内核,允许直接从笔记本中使用C++代码。这完全绕过了首先需要Python绑定的需求,并允许用户从笔记本中使用库,就像使用Python库一样。最后,Pythran是一个针对Python语言的子集的预编译器,重点是科学计算。它接受带有少量接口描述的Python模块,并将其转换为具有相同接口但希望更快的本机Python模块。Pythran利用多核和SIMD指令,将其Python语言子集转换为针对特定优化类型的大量模板化C++代码。然而,所有这些基础设施在二进制大小方面都带来了巨大的成本。事实上,C++编译器并不小,将其与图像处理库一起打包可能会严重影响最终的二进制文件。没有19ConclusionThe work presented in this thesis by the author followed a very clear narrative arc. The emphasiswas first shown on presenting what is the notion of generic programming (genericity), its storyand how anyone can relate in his day-to-day life, especially when applied to image processing.Genericity is a 4-decades years old notion that has evolved and found usage in very modern areasof our society. Indeed, image processing is widely used to build modern applications used allaround the world. However, it was demonstrated how difficult it can be to implement solutionsrelying on genericity. Indeed, there is a rule of three tying genericity, performance and ease ofuse stated in introduction. In this thesis, we try to demonstrate how to break this rule in threesteps.The first step, illustrated in Taxonomy for Image Processing, was to make an inventoryof image types and families as well as different image processing algorithms. The aim wasto produce a comprehensive taxonomy of types (pixel, image, structuring elements, . . . ) andalgorithms related to image processing in order to be able to write concepts (in the sense ofC++ concepts). This first step delimits the p
下载后可阅读完整内容,剩余1页未读,立即下载
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://profile-avatar.csdnimg.cn/default.jpg!1)
cpongm
- 粉丝: 4
- 资源: 2万+
上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助
![](https://csdnimg.cn/release/wenkucmsfe/public/img/voice.245cc511.png)
会员权益专享
最新资源
- 利用迪杰斯特拉算法的全国交通咨询系统设计与实现
- 全国交通咨询系统C++实现源码解析
- DFT与FFT应用:信号频谱分析实验
- MATLAB图论算法实现:最小费用最大流
- MATLAB常用命令完全指南
- 共创智慧灯杆数据运营公司——抢占5G市场
- 中山农情统计分析系统项目实施与管理策略
- XX省中小学智慧校园建设实施方案
- 中山农情统计分析系统项目实施方案
- MATLAB函数详解:从Text到Size的实用指南
- 考虑速度与加速度限制的工业机器人轨迹规划与实时补偿算法
- Matlab进行统计回归分析:从单因素到双因素方差分析
- 智慧灯杆数据运营公司策划书:抢占5G市场,打造智慧城市新载体
- Photoshop基础与色彩知识:信息时代的PS认证考试全攻略
- Photoshop技能测试:核心概念与操作
- Photoshop试题与答案详解
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
![](https://img-home.csdnimg.cn/images/20220527035711.png)
![](https://img-home.csdnimg.cn/images/20220527035711.png)
![](https://img-home.csdnimg.cn/images/20220527035111.png)
安全验证
文档复制为VIP权益,开通VIP直接复制
![](https://csdnimg.cn/release/wenkucmsfe/public/img/green-success.6a4acb44.png)