Wie teste ich einen Bildverarbeitungscode?

14

Ich arbeite in der Bildverarbeitung (hauptsächlich OCR) und frage mich, wie ich Unit-Tests in meine Entwicklung integrieren soll.

Ich benutze bereits Komponententests für "häufigere" Codearten, aber wenn ich mit Bildverarbeitungscode arbeite, bin ich mir nicht sicher, wie ich damit umgehen soll. Diese Art von Code benötigt immer eine Eingabe / Ausgabe von Bilddaten, und das Verspotten ist nicht offensichtlich. Im Moment mache ich hauptsächlich Integrationstests, aber die Ausführung dauert eine Weile. Ich möchte einige Ideen dazu haben, wie man diese Art von Code in Komponententests aufteilt, damit ich sie schneller ausführen kann.

Bearbeiten: Das Analysieren eines Zeichens kann viele Schritte umfassen, die mehrere Rotations-, Skalierungs- und Morphologieoperationen umfassen. Diese Schritte ändern sich häufig, während der Algorithmus entwickelt wird. Somit können sich die Eingabe und die erwartete Ausgabe während des Testens stark verändern. Jedes Zeichen kann 100x100 Pixel groß sein, so dass eine Hardcodierung im Code oder das Arbeiten mit generierten Daten nicht in Frage kommt.

rold2007
quelle
Können Sie ein Beispiel für eine Funktion skizzieren, bei der beim Erstellen eines Komponententests Probleme auftreten?
Doc Brown
1
Zu kurz für eine echte Antwort und nicht wirklich Unit-Testing: Wir verarbeiten Daten von Hand (wie in: Durchlaufen einer hohen Anzahl von Stichproben - bei solchen Klassifizierungsaufgaben gehe ich normalerweise über 1000 hinaus, aber das hängt von Ihrer Gesamtstichprobengröße ab ) und Vergleichen der Endergebnisse mit den handverarbeiteten Daten automatisch. Ich habe ein kleines Framework dafür eingerichtet, es wird in ein paar Wochen Open Source sein, aber das ist die Beschreibung - Sie könnten den Prozess klonen: birgitplays.wordpress.com/2012/09/15/…
Birgit P.
In Ihrem Beispiel können Sie Rotation, Skalierung usw. problemlos als kleine Testeinheiten testen. Das Drehen eines bestimmten Bildes um 45 Grad sollte sich nicht wesentlich ändern. Dies gilt auch für Skalierungen und morphologische Operationen. Etwas zu testen, bei dem sich die erwartete Ausgabe während der Implementierung entwickelt, ist jedoch schwierig. Sie könnten versuchen, ein Qualitätsmaß zu bestimmen und Qualität> = irgendeine_Qualität sagen. Um sicherzustellen, dass sich Ihre Qualität nicht verschlechtert, kann dies jedoch auch schwierig sein. Abgesehen davon können Sie nur Tests durchführen, die beweisen, dass die zugrunde liegenden Teile nicht beschädigt sind. Wie skalieren / drehen / etc.
Martiert
@martiert: Ich teste keine Rotation, Skalierung usw., da ich diese aus einer dritten Bibliothek aufrufe, von der ich glaube, dass sie gut getestet ist. Der OCR-Algorithmus besteht aus vielen dieser Operationen. Aber wie Sie sagen, ist es schwierig, etwas zu testen, bei dem sich eine Ausgabe entwickelt. Vielleicht ist es eine gute Warnung, dass wir nicht die Wahl haben, uns auf Integrationstests zu verlassen ...
rold2007
@ Birgit P .: Interessante Lösung. Wie Sie sagen, handelt es sich immer noch um Integrationstests. Ein Framework wie Ihres zu haben würde helfen, diese Tests schneller einzurichten, aber sie werden nicht schneller laufen ...
rold2007

Antworten:

12

Ich arbeite mit Videoaufzeichnungs- / Analyse- / Streaming-Software und wir hatten ein sehr ähnliches Problem. Unten war unsere Lösung, nicht sicher, wie es langfristig funktionieren wird, aber im Moment scheint es zu funktionieren.

Speichern Sie Ein- / Ausgabebilder als Ressourcen in Ihrem Unit-Test-Projekt. Lassen Sie dann den Komponententest überprüfen, ob bei Eingabe eines bestimmten Eingangs dieser bestimmte Ausgang erzeugt wird.

9/10 Mal, wenn Sie den Code überarbeiten und weitere Funktionen hinzufügen, wird sich das Verhalten Ihrer Bildverarbeitungsroutinen voraussichtlich nicht ändern. Wenn also plötzlich Unit-Tests fehlschlagen, liegt dies wahrscheinlich an einem Fehler.

Wenn Sie andererseits Änderungen am tatsächlichen Algorithmus vornehmen, führt dies auch zu einem Fehlschlagen des Komponententests. In diesem Fall müssten Sie manuell / visuell überprüfen, ob die Ergebnisse korrekt sind. Wenn sie gut aussehen, aktualisieren Sie die Bildressourcen, damit der Komponententest erneut bestanden wird.

In unserem Projekt haben wir schließlich "gefälschte" (oder, wenn Sie so wollen, verspottete) Videoquellen entwickelt, die uns Daten sowohl für die Eingabe als auch für die Ausgabe liefern können. Die Daten selbst sind jedoch keine Fälschungen. Sie wurden tatsächlich mithilfe von Hilfsdatenaufzeichnungsklassen von einem laufenden System erfasst, als wir manuelle Tests durchführten und prüften, ob alles funktionierte.

DXM
quelle
Stimmen Sie zu, es ist in Ordnung, sich bei Ihren Tests auf einige konkrete Dateien zu verlassen, wenn Sie Routinen testen, die mit Dateien arbeiten (bei Integrationstests ist dies häufiger der Fall).
Kemoda
1
Wenn Sie einige Eingaben über die gesamte Verarbeitungskette ausführen und dann die Ausgabe überprüfen, werden keine Unit-Tests, sondern Integrationstests durchgeführt.
Tdammers
@tdammers: Ich habe nie gesagt, dass ich es durch die gesamte Kette laufen lassen soll. Führen Sie eine Eingabe durch eine "Einheit", nicht durch die gesamte Kette. Und sicher, wenn die Ausgabe davon etwas anderes als Bilder ist, müssen Sie nur Eingaben als Bildressourcen speichern.
DXM
@DXM: Ich verstehe Ihre Lösung, aber ich denke, wir haben möglicherweise nicht die gleichen Einschränkungen. Meine Eingabe- / Ausgabedaten ändern sich sehr, während der Algorithmus entwickelt wird. Wie gehen Sie mit diesen regelmäßigen Veränderungen um? In der OCR kann ich eine Genauigkeit von über 99% erreichen, so dass das Testen von nur wenigen Bildern ein falsches Erfolgsgefühl
hervorruft,