Code Quality
Dieses Beispiel zeigt, wie Sie die Qualität von verschiedenen 1D- und 2D-Codes nach ISO/IEC Standards bewerten können. Dabei wird:
- Mit den Funktionen F_VN_GradeBarcodeExp, F_VN_GradeDataMatrixCodeExp oder F_VN_GradeQRCodeExp jeweils ein Code pro Bild bewertet.
- Die Ausführungszeit der Funktion über einen Watchdog überwacht.
- Verschiedene (optionale) Visualisierungen für eine schnelle oder detaillierte Analyse erzeugt.
Erläuterung
Code-Grading ist ein Verfahren zur Bewertung der Druckqualität von 1D- und 2D-Codes nach internationalen Standards. Das Verfahren dient dazu sicherzustellen, dass Codes zuverlässig von verschiedenen Lesegeräten unter unterschiedlichen Bedingungen decodiert werden können. Die Qualitätsbewertung erfolgt nach spezifischen ISO-Normen: für 1D-Strichcodes nach ISO/IEC 15416:2016 und für 2D-Codes nach ISO/IEC 15415:2011. Die Bewertung wird auf einer Skala von 0 bis 4 durchgeführt, wobei 0 eine sehr schlechte und 4 eine sehr gute Codequalität bedeutet.
Für normkonforme und vergleichbare Grading-Ergebnisse müssen die in den ISO-Standards definierten Bedingungen eingehalten werden. Dazu gehören spezifizierte Anforderungen an Beleuchtung, Blende, Auflösung und Messabstand. Dennoch können die Grading-Funktionen auch außerhalb der exakten Normbedingungen zur Qualitätsprüfung eingesetzt werden. In diesem Fall muss sichergestellt werden, dass die Eingangsbilder scharf und gleichmäßig ausgeleuchtet sind, der Code mittig und vollständig im Bild liegt und möglichst ohne perspektivische Verzerrung abgebildet wird. Die Ergebnisse sind dann zwar nicht normkonform vergleichbar, erlauben aber dennoch eine Beurteilung der Code-Qualität, z.B. in der Produktion zur Überprüfung einer geforderten Mindestqualität.
Die Grading-Funktionen suchen nach einem einzelnen Code innerhalb eines definierten Bildbereichs und bewerten die Qualität anhand der Kriterien, die im entsprechenden Standard definiert sind. Dabei liefern sie zusätzlich die Kontur sowie den Drehwinkel des gefundenen Codes zurück.
Den Funktionen muss ein 1-kanaliges 8-Bit-Grauwertbild übergeben werden. Zudem ist es erforderlich, dass sich der Code mittig im übergebenen Bildbereich befindet. Liegt der Code nicht im Zentrum des Bildes, muss die Position vorab durch andere Funktionen ermittelt und durch das Setzen einer Region of Interest (ROI) entsprechend angepasst werden.
Bei den Funktionen für 2D-Codes definiert der Parameter fModuleWidth die erwartete Mindestmodulbreite in Pixeln. Dieser Wert sollte möglichst exakt der realen Größe im Bild entsprechen. Dabei ist eine absolute Mindestgröße von 3 Pixeln erforderlich. Für optimale Ergebnisse wird ein Bereich von 5 bis 8 Pixeln empfohlen. Signifikante Abweichungen von der tatsächlichen Modulbreite können die Erkennungsrate verschlechtern und die Ausführungszeit der Funktion deutlich erhöhen.
Grading
In diesem Sample wird der Code-Typ anhand der gefundenen Schlüsselwörter wie „Code128”, „EAN13”, „DM” oder „QR” im Dateinamen erkannt. Anschließend wird die entsprechende Grading-Funktion aufgerufen. Es werden Expert-Varianten der Grading-Funktionen F_VN_GradeBarcodeExp, F_VN_GradeDataMatrixCodeExp und F_VN_GradeQRCodeExp verwendet. Diese bieten zusätzliche Detailinformationen und Visualisierungen, wie zu Scanlinien, Modul-Bewertungen und Code-Konturen. Die Parameter ipResultVisualization, ipScanLineInfo und ipMarginGrades sind optional und können auf 0 gesetzt werden, was die Verarbeitungszeit der Funktion verkürzt. Die Ausführung der Funktionen erfolgt unter Watchdog-Überwachung, um Zykluszeitüberschreitungen zu verhindern.
hrWD := F_VN_StartRelWatchdog(tStop, S_OK);
// Grade code based on code type
CASE eCodeType OF
BARCODE:
// Grade 1D barcode
hrGrade := F_VN_GradeBarcodeExp(
ipSrcImage := ipImageIn,
ipDecodedData := ipDecodedData,
stCodeGrades := stCodeGrades1D,
eBarcodeType := eBarcodeType,
eSearchDirection := eSearchDirection,
ipResultVisualization := ipResultVisualization,
ipScanLineInfo := ipScanLineInfo,
ipContour := ipContour,
hrPrev := hr,
fAngleDeg => fRotationAngleDeg);
// Get overall result grade
fGradeOverallResult := stCodeGrades1D.fOverall;
DATAMATRIX:
// Set module with according to image resoulution
IF INT_TO_BOOL(Find(sFileName, '1')) OR INT_TO_BOOL(Find(sFileName, '2')) THEN
fModuleWidth := 4;
ELSE
fModuleWidth := 9;
END_IF
// Grade 2D data matrix code
hrGrade := F_VN_GradeDataMatrixCodeExp(
ipSrcImage := ipImageIn,
ipDecodedData := ipDecodedData,
stCodeGrades := stCodeGradesDM,
fModuleWidth := fModuleWidth,
ipResultVisualization := ipResultVisualization,
ipMarginGrades := ipMarginGrades,
ipContour := ipContour,
hrPrev := hr,
fAngleDeg => fRotationAngleDeg);
// Get overall result grade
fGradeOverallResult := USINT_TO_REAL(stCodeGradesDM.nOverall);
QRCODE:
// Set module with according to image resoulution
fModuleWidth := 4;
// Grade 2D QR code
hrGrade := F_VN_GradeQRCodeExp(
ipSrcImage := ipImageIn,
ipDecodedData := ipDecodedData,
stCodeGrades := stCodeGradesQR,
fModuleWidth := fModuleWidth,
ipResultVisualization := ipResultVisualization,
ipMarginGrades := ipMarginGrades,
ipContour := ipContour,
hrPrev := hr,
fAngleDeg => fRotationAngleDeg);
// Get overall result grade
fGradeOverallResult := USINT_TO_REAL(stCodeGradesQR.nOverall);
ELSE
// Unknown code type, skip grading
hrGrade := Tc2_System.E_HRESULTAdsErr.NOTFOUND;
END_CASE
hrWD := F_VN_StopWatchdog(hrWD, tRest => tRest);Auswertung und Visualisierung
Nach einem erfolgreichen Funktionsaufruf kann das Ergebnis des Gradings ausgewertet werden. Über die Parameter ipDecodedData und ipContour können wie beim Code-Reading die Codes ausgelesen und die gefundene Code-Kontur dargestellt werden. fAngleDeg gibt optional die Drehung des Codes im Bild an.
IF SUCCEEDED(hrGrade) THEN
// Export decoded data to string
hr := F_VN_ExportContainer_String(ipDecodedData, sCodeResult, 255, hr);
// Create code result image with contour and rotation angle
hr := F_VN_ConvertColorSpace(ipImageIn, ipImageCodeResult, TCVN_CST_GRAY_TO_RGB, hr);
hr := F_VN_DrawContours(ipContour, 0, ipImageCodeResult, aColorGreen, 2, hr);
sText := CONCAT('Rotation angle: ', REAL_TO_STRING(fRotationAngleDeg));
hr := F_VN_PutTextExp(sText, ipImageCodeResult, 5, 10, TCVN_FT_HERSHEY_SIMPLEX, 0.4, aColorBlue, 1, TCVN_LT_8_CONNECTED, FALSE, hr);
// Further processing …
END_IF
Die Grading-Ergebnisse werden in den Strukturen stCodeGrades1D, stCodeGradesDM bzw. stCodeGradesQR gespeichert und erhalten das Gesamtergebnis sowie alle Einzelbewertungen.
Für die Visualisierung der Ergebnisse sind in dem Sample verschiedene Hilfsfunktionen unter POU/Visualization enthalten. Standardmäßig wird mit der Hilfsfunktion F_VisualizeGradingResult das Ergebnisbild ipImageGradeResult erzeugt, das die Gesamtbewertung über dem von der Grading-Funktion erzeugten Bild ipResultVisualization darstellt:

Das Ausgabebild ipResultVisualization der Grading-Funktionen zeigt die Bewertung der Bereiche farbcodiert an: Grün (≥ 3,0), Blau (≥ 2,0), Orange (≥ 1,0) und Rot (< 1,0). Bei 1D-Codes werden die einzelnen Scanlinien eingefärbt, bei 2D-Codes die einzelnen Module. Dadurch lassen sich Problemstellen wie Defekte, schlechte Modulation oder unzureichender Kontrast räumlich auf dem Code lokalisieren.
Über den Parameter bEnableDetailedResultImage kann zu einer detaillierteren Ansicht umgeschaltet werden. Dabei wird mit der Hilfsfunktion F_VisualizeDetailedGradingResults ein Bild erzeugt, das links die numerischen Einzelwertungen aller Grading-Parameter und rechts das Bild ipResultVisualization zeigt:

Für eine tiefergehende Analyse können zusätzlich die von der Grading-Funktion erzeugten Container ipScanLineInfo und ipMarginGrades ausgewertet werden.
Im gezeigten Beispiel wird bei 1D-Codes mit der Hilfsfunktion F_VisualizeScanLineIntensityProfile ein Intensitätsprofil einer ausgewählte Suchlinie entlang der Scanrichtung erstellt und in ipImageCustomVisualization dargestellt:

Das Intensitätsprofil stellt die erste Suchlinie des zuvor gezeigten Barcodes dar. Damit lässt sich gut die Abwertung der Defects Grade auf 2,2 erklären. Das Intensitätsprofil zeigt starkes Rauschen in den weißen Bereichen durch einen unruhigen Hintergrund. Die Rauschintensität ist im Vergleich zum Symbolkontrast so groß, dass dies zu einer deutlichen Abwertung im Grading führt und somit die Gesamtbewertung herabsetzt.
Für 2D-Codes werden mit der Hilfsfunktion F_VisualizeMarginGrades in ipImageCustomVisualization alle Module des Codes visualisiert, die eine Grade kleiner als 3 aufweisen:
