【发布时间】:2017-05-22 03:18:59
【问题描述】:
我正在编写一个基于 C++ OpenCV 的计算机视觉程序。该程序的基本思想可以描述如下:
从相机读取图像。
对图像做一些魔法。
显示转换后的图像。
程序核心逻辑的实现(第2步)落入顺序调用OpenCV函数进行图像处理。大约有 50 个函数调用。创建了一些临时图像对象来存储中间结果,但除此之外,不会创建其他实体。第 2 步中的函数只使用一次。
我对组织这种类型的代码感到困惑(感觉更像是脚本)。我曾经为图像处理的每个逻辑步骤创建几个类。比如说,在这里我可以创建ImagePreprocessor、ImageProcessor和ImagePostprocessor等3个类,并将上述50个OpenCV调用和临时图像在它们之间进行相应的拆分。但感觉不像是合理的 OOP 设计。这些类只不过是存储函数调用的一种方式。
main() 函数仍然只会为每个类创建一个对象,然后调用它们的方法:
image_preprocessor.do_magic(img);
image_processor.do_magic(img);
image_postprocessor.do_magic(img);
在我的印象中,这与一个一个调用 50 个 OpenCV 函数基本相同。
我开始怀疑这种类型的代码是否需要 OOP 设计。毕竟我可以简单地提供一个函数do_magic(),或者三个函数preprocess()、process()和postprocess()。但是,这种方法也不是一个好的做法:它仍然只是一堆函数调用,被分成不同的函数。
我想知道,是否有一些常见的做法来组织这种类似脚本的代码?如果这段代码是大型 OOP 系统的一部分,会是什么方式?
【问题讨论】:
-
好的,我给出了部分答案,因为完整的解决方案需要大量的工作。对于视频/图像阅读器,创建一个抽象类。无论您是处理视频还是图像,处理都是一次完成一帧,因此创建一个抽象类(接口)ImageProcessor。没有 Pre 和 Post。例如,retinex 处理用作后期处理,但某些应用程序可以将其用作预处理。 Retinex 处理类将实现 ImageProcessor。
-
接下来,如何制作管道。创建一个包含类 PipeLineElement 的 LinkedList 的类管道。每个元素都将保存其 ImageProcessor 和 Next PipeLineElement 对象。 pipelineElement 会将一个数据包(所有数据)传递给 ImageProcessor 并接收更新的数据包。更新的数据包将被传递到管道的下一个元素。请注意,此管道是串行管道,即您不能在同一最后一个数据包中处理两个元素,但您可以进一步推广链表。
-
每个元素现在可以并行处理。第一个元素将处理第 n 个元素,第二个元素将处理第 n-1 个元素,并且很快,但随之而来的更多问题,例如管道瓶颈和由于每个元素中较少的多线程导致的额外延迟将导致严重的实时延迟。去过那里并从经验中讲述:D。总的来说,祝你好运,这个设计非常好,但需要非常高的专业知识。另一方面,每个库都可以像处理链表一样轻松地从管道中添加和删除。
-
此外,您可以在内部处理一个 ImageProcessor 实现,而无需对整个管道进行任何更改。最后,不要使用 Mat 作为唯一需要传递的数据。使用像 PipeLinePacket 这样的类来存储应该传递的所有信息。这也将允许您将在早期 ImageProcessor 中完成的任何处理存储在管道中,并允许以后的 ImageProcessor 使用它。
-
告售者!! :P,看起来我几乎给出了完整的解决方案。稍后将其添加为答案。
标签: oop design-patterns architecture code-organization