是否可以将TDD与图像处理算法结合使用?

Alc*_*sta 28 c++ testing unit-testing image-processing

最近,我曾在一个项目中使用过TDD(测试驱动开发).该项目是一个用Java开发的Web应用程序,虽然单元测试Web应用程序可能并不简单,但可以使用模拟(我们使用了Mockito框架).

现在我将开始一个项目,我将使用C++处理图像处理(主要是图像分割),我不确定使用TDD是否是一个好主意.问题是很难判断分割的结果是否正确,同样的问题也适用于许多其他图像处理算法.

所以,我想知道的是,如果有人在这里成功使用TDD和图像分割算法(不一定是分割算法).

Ste*_*owe 10

至少你可以使用测试进行回归测试.例如,假设您有5个特定分段算法的测试图像.您通过代码运行5个图像并手动验证结果.如果正确,结果将存储在磁盘上的某个位置,并且将来执行这些测试会将生成的结果与存储的结果进行比较.

这样,如果你做了一个突破性的改变,你会抓住它,但更重要的是你只需要经历一次(正确的)手动测试周期.

  • @ [nikie]:如果你改变你的算法以便它产生不同的结果,那么测试**应该**打破.您/想要/回归测试是脆弱的,就像煤矿中的金丝雀一样. (3认同)
  • 但这就是我的观点:回归测试对于明确定义的问题(例如图形算法)有意义。一旦完成了它应该做的事情,它的行为就不会改变,因此您要进行回归测试。但是对于许多图像处理问题,您永远无法达到“正确性”的水平。*没有适用于所有情况的细分算法。因此,您可能需要调整您的算法(这意味着不同的结果),以便有一天对其进行优化。因此,除非您选择停止开发,否则回归测试将以您的方式进行。然后您也不需要回归测试 (2认同)
  • @ [nikie]:我想我明白您的意思,输出可能太脆弱,以至于测试即使是最简单的改进也无法幸免。因此,如果可能,请测试不那么脆弱的东西。例如,如果您的细分算法旨在识别图像中的某些东西,例如线条集,肿瘤或面部,则请对此进行测试,而不要测试汇总输出的像素级值,因为算法改进可能会有所不同。后者将测试算法中使用的数学,而不是算法的应用(算法实现的“功能”) (2认同)

jil*_*wit 9

每当我做任何与计算机视觉相关的开发时,TDD几乎都是标准做法.您有图像和想要测量的东西.第一步是手工标记图像的(大)子集.这为您提供了测试数据.然后,过程(完全正确)将您的测试集分成两部分,即"开发集"和"验证集".在应用于开发集时,您需要重复开发循环,直到算法足够准确.然后验证验证集上的结果(这样你就不会在开发集的某些奇怪方面过度训练.这是最纯粹的测试驱动开发.

请注意,在开发像这样的大量算法相关软件时,您正在测试两种不同的东西.

  1. 您将在软件中获得的常规错误.这些可以使用"普通"TDD技术进行测试
  2. 算法的性能,您需要上面列出的系统.

根据(1),程序可以是无bug的,但不完全符合(2).例如,一个非常简单的图像分割算法说:"图像的左半部分是一个部分,右半部分是另一个部分.这个程序可以很容易地根据(1)制作无错误.这是完全另一个问题.它满足了你的性能需求.不要混淆这两个方面,不要让一个人干扰另一方面.

更具体地说,我建议你首先开发算法,错误的疣和所有,然后使用TDD与算法(不是代码!)和软件的其他要求作为单独的TDDevelopment过程的规范.在重度开发中对一些相当复杂的算法深入进行小型临时辅助函数的单元测试是浪费时间和精力.


Nik*_*iki 5

我认为你能做的最好的事情就是测试你的算法所包含的简单的,数学上定义明确的构建块,比如线性滤波器,形态学运算,FFT,小波变换等.这些通常很难以有效地实现所有边界情况所以验证它们确实有意义.

对于像图像分割这样的实际算法,TDD没有多大意义恕我直言.我甚至认为单元测试在这里没有意义.当然,你可以编写测试,但这些测试总是非常脆弱.典型的图像处理算法需要一些必须根据所需结果进行调整的参数(一个不能自动化的过程,并且在算法运行之前无法完成).分割算法的结果也没有很好地定义,但是你的单元测试只能测试一些明确定义的属性.算法可以具有该属性而无需执行您想要的操作,反之亦然,因此您的测试结果不是非常有用.此外,要测试分割算法的结果,您需要编写大量相当难的代码,而在视觉上验证结果非常简单,无论如何您都必须这样做.

我认为在某种程度上它与单元测试用户界面类似:测试实际明确定义的功能(例如,当用户单击此按钮时,某些项目被添加到此列表中,此标签显示该文本...)相对容易并且可以节省大量的工作和调试.但是世界上没有任何测试可以告诉你你的UI是否可用,可理解或漂亮,因为这些东西没有明确定义.


Amr*_*mro 5

图像处理中的TDD仅适用于确定性问题,例如:

  • 图像算术
  • 直方图生成
  • 等等..

但是,TDD不适合诸如以下特征提取算法:

  • 边缘检测
  • 分割
  • 拐角检测

...因为没有算法可以完美解决所有图像的此类问题。


Mic*_*cka 5

我们对同样的“问题”进行了一些讨论,您在这些答案下方的评论中提到了许多评论。

我们到了最后,计算机视觉/图像处理中的 TDD(关于分割、检测或诸如此类的全局目标)可能是:

  1. 获取应该处理的图像/序列并为该图像创建一个测试:所需的输出和一个衡量结果可能与“基本事实”相差多远的指标。

  2. 为不同的设置(不同的照明、不同的对象或类似的东西)获取另一个图像/序列,其中您的算法失败并为此编写测试。

  3. 以解决所有先前测试的方式改进您的算法。

  4. 回到2。

不知道这是否适用,创建测试将比在传统 TDD 中复杂得多,因为可能很难定义基本事实和算法输出之间允许的差异。

可能最好只使用一些 QualityDrivenDevelopment,您的更改不应该使事情比以前“更糟”(您再次必须为此找到一个指标)。

显然,您仍然可以对这些算法的确定性部分使用传统的单元测试,但这不是“TDD-in-signal-processing”的真正问题


mar*_*lly 4

您在问题中描述的图像处理测试的级别比您使用 TDD 编写的大多数测试要高得多。

在真正的测试驱动开发过程中,在向软件添加任何新功能之前,您将首先编写失败的测试,然后编写使测试通过、冲洗并重复的代码。

这个过程会产生一个大型的单元测试库,有时测试的LOC数量比功能代码还要多!

由于您的分析算法具有结构化行为,因此它们非常适合 TDD 方法。

但我认为您真正要问的问题是“我如何针对模糊图像处理软件执行一套集成测试?” 您可能认为我在吹毛求疵,但单元测试和集成测试之间的区别确实触及了测试驱动开发的核心含义。TDD 流程的好处主要来自单元测试的丰富支持结构。

对于您的情况,我会将集成测试套件与针对 Web 应用程序的自动化性能指标进行比较。我们希望积累执行时间的历史记录,但我们可能不希望因单个执行性能不佳而导致构建显式失败(这可能受到网络拥塞、磁盘 I/O 等的影响)。您可以围绕测试套件的性能设置一些宽松的容差,并让持续集成服务器推出每日报告,为您提供算法性能的高级概述。