Code Detection
Dieses Sample zeigt die Lokalisierung und Klassifizierung von 1D- und 2D-Codes mithilfe von neuronalen Netzen. Es demonstriert die Verwendung der Funktionen:
- F_VN_DetectCodesNeuralNetwork zur Detektion von 1D- und/oder 2D-Codes.
- F_VN_ResizeRegion_TcVnRectangle_DINT zur Anpassung der Größe der gefundenen Regionen für nachfolgende Prozessschritte.
- Die Visualisierung der gefundenen Code-Regionen und -Typen.
Erläuterung
Die Funktion F_VN_DetectCodesNeuralNetwork dient der Lokalisierung von 1D- und 2D-Codes und liefert die wahrscheinlichen Code-Regionen als Rechtecke sowie die zugehörigen Codetypen zurück. Dieser Ansatz ist besonders vorteilhaft bei unruhigen Hintergründen, variierender Beleuchtung oder vielen Codes im Bild, da eine nachfolgende Code-Reading-Funktion gezielt nur auf den erkannten Teilbereichen ausgeführt werden kann. Damit reduziert sich in der Regel der Rechenaufwand, den die Reading-Funktionen benötigen, um einen Code zu finden, da weniger Pixel geprüft werden müssen.
Im Sample kann über den Parameter eModelType zur Laufzeit zwischen verschiedenen neuronalen Netzwerkmodellen (ETcVnCodeDetectionModel) umgeschaltet werden. Da sich diese in ihrer Eingangsauflösung und ihrem Erkennungsumfang unterscheiden, lässt sich so der Kompromiss zwischen Detektionsgenauigkeit und Ausführungsgeschwindigkeit evaluieren. Allerdings kann es auch zu Verwechslungen kommen, wenn Strukturen im Bild einem Code ähneln, insbesondere im skalierten Eingangsbild.
Die Modelle gliedern sich dabei systematisch in zwei Dimensionen:
- Erkennungsumfang (Präfix):
TCVN_CDM_DETECT_1_x(1D-Codes und 2D-Codes [QR, DATAMATRIX und DOTCODE])TCVN_CDM_DETECT_2_x(nur 1D-Codes)TCVN_CDM_DETECT_3_x(nur 2D-Codes)- Eingangsauflösung (Suffix):
TCVN_CDM_DETECT_x_1 (224×224 Pixel, maximale Geschwindigkeit)TCVN_CDM_DETECT_x_2 (352×256 Pixel, ausgewogen)TCVN_CDM_DETECT_x_3 (416×352 Pixel, höchste Genauigkeit für kleine Codes)
Das Eingangsbild wird von der Funktion intern automatisch auf diese jeweilige Zielauflösung skaliert.
Zusätzlich kann über die Variable eCodeTypeSelection definiert werden, nach welchen spezifischen Code-Typen innerhalb des gewählten Modellumfangs gesucht werden soll. Um nach mehreren ausgewählten Typen gleichzeitig zu filtern, können die Enums mit einer bitweisen OR-Operation verknüpft werden (z. B. eCodeTypeSelection := TCVN_CT_QR OR TCVN_CT_DATAMATRIX).
Modellinitialisierung
Bevor die Code-Detektion durchgeführt werden kann, muss das Modell geladen werden. Dies erfolgt einmalig beim Programmstart über den Funktionsbaustein FB_VN_InitializeFunction.
Soll das Modell zur Laufzeit gewechselt werden oder wird es nicht mehr benötigt, kann mit F_VN_DeinitializeFunction das Modell deinitialisiert werden, um den Speicher wieder freizugeben.
Variablen
bInitialized : BOOL := FALSE;
eModelType : ETcVnCodeDetectionModel := TCVN_CDM_DETECT_1_1;
fbInit : FB_VN_InitializeFunction;
nInitReturnCode : UDINT;Code
// Load code detection model
IF NOT bInitialized THEN
fbInit(eFunction := TCVN_IF_CODEDETECTION, nOptions := eModelType, bStart := TRUE);
IF NOT fbInit.bBusy THEN
fbInit(bStart := FALSE);
IF NOT fbInit.bError THEN
bInitialized := TRUE;
nInitReturnCode := fbInit.nErrorId AND 16#FFF;
ELSE
nInitReturnCode := fbInit.nErrorId AND 16#FFF;
END_IF
END_IF
END_IFLokalisierung der Code-Regionen
Nach der erfolgreichen Initialisierung erfolgt die zyklische Detektion auf dem aktuellen Eingangsbild mit der Funktion F_VN_DetectCodesNeuralNetwork. Die Funktion gibt zwei Container zurück. Zum einen enthält ipCodeRegions die Koordinaten der gefundenen Regionen als Rechtecke und zum anderen enthält ipCodeTypes die dazugehörigen erkannten Code-Typen.
Variablen:
ipCodeRegions : ITcVnContainer;
ipCodeTypeResult : ITcVnContainer;
eCodeTypeSelection : ETcVnCodeType := TCVN_CT_ANY;Code:
hr := F_VN_DetectCodesNeuralNetwork(
ipSrcImage := ipImageIn,
ipCodeRegions := ipCodeRegions,
ipCodeTypes := ipCodeTypeResult,
eModelType := eModelType,
nCodeType := eCodeTypeSelection,
hrPrev := hr);Auswertung und Anpassung der Regionen
Wurde die Funktion erfolgreich ausgeführt und mindestens ein Code gefunden, wird über alle detektierten Elemente iteriert, um die individuellen Positionen und Typen abzurufen.
Da die Modelle die Regionen oft sehr exakt und eng um den Code ausgeben, wird die Funktion F_VN_ResizeRegion_TcVnRectangle_DINT auf die Ergebnisse angewendet. Diese vergrößert die Rechtecke um einen einstellbaren Faktor (fWidthRatio, fHeightRatio) sowie einen absoluten minimalen Pixel-Offset (nMinWidthOffset, nMinHeightOffset). Dies ist essenziell für eine nachfolgende Code-Reading Funktion, um sicherzustellen, dass die erforderliche Ruhezone vollständig im Bildausschnitt enthalten ist.
Abschließend wertet ein CASE-Statement den gefundenen Code-Typ aus, um wie im Sample gezeigt, typabhängig spezifische Farben und Beschriftungen für die visuelle Darstellung zuzuweisen. An dieser Stelle oder im nachfolgenden Code können mit diesen Informationen die entsprechenden Code-Reading-Funktionen hinzugefügt werden.
Variablen:
fWidthRatio : REAL := 1.15;
fHeightRatio : REAL := 1.15;
nMinWidthOffset : DINT := 10;
nMinHeightOffse : DINT := 10;
hr : HRESULT;
ipImageIn : ITcVnImage;
eCodeTypeResult : ETcVnCodeType;
stRectangle : TcVnRectangle;
nDetectedCodes : ULINT;
i : ULINT;Code:
IF hr = S_OK THEN
// Get number of detecded codes
hr := F_VN_GetNumberOfElements(ipCodeRegions, nDetectedCodes, hr);
IF nDetectedCodes > 0 THEN
FOR i := 0 TO nDetectedCodes – 1 DO
// Get code type and region from detection results
hr := F_VN_GetAt_ULINT(ipCodeTypeResult, eCodeTypeResult, i, hr);
hr := F_VN_GetAt_TcVnRectangle_DINT(ipCodeRegions, stRectangle, i, hr);
// Enlarge detection region to meet the respective code requirements for the quiet zone
hr := F_VN_ResizeRegion_TcVnRectangle_DINT(
stSrcRect := stRectangle,
stDestRect := stRectangle,
fWidthRatio := fWidthRatio,
fHeightRatio := fHeightRatio,
nMinWidthOffset := nMinWidthOffset,
nMinHeightOffset := nMinHeightOffset,
ipImage := ipImageIn,
hrPrev := hr);
// Evaluate the recognized code type and its region
CASE eCodeTypeResult OF
TCVN_CT_1D:
// ...
TCVN_CT_2D:
// ...
TCVN_CT_QR
// ...
TCVN_CT_DATAMATRIX:
// ...
TCVN_CT_DOTCODE:
// ...
END_CASE
END_FOR
ELSE
// No code detected
END_IF
ELSE
IF hr = S_FALSE THEN
// No code detected
ELSE
// Error: See HRESULT for more details
END_IF
END_IFErgebnis
Das Ergebnis der Lokalisierung wird mit farbigen Rechtecken und optionalen Typ-Labeln im Bild ipImageResultDisp angezeigt. Zusätzlich wird in der oberen linken Ecke ein Status-Text wie „Codes detected: n“ bzw. „No code detected“ oder im Fehlerfall der HRESULT-Code ausgegeben. Das gezeigte Bild wurde mit dem Modell TCVN_CDM_DETECT_1_2 ausgewertet:

Zu Debugging-Zwecken generiert das Sample zusätzlich das Bild ipImageModelInputDisp. Es zeigt das Eingangsbild so, wie es von der Funktion intern auf die gewählte Modellauflösung herunterskaliert wird. Dadurch bekommen Sie einen direkten visuellen Eindruck davon, welche Details und Seitenverhältnisse das neuronale Netzwerk tatsächlich als Input verarbeitet.
Standardmäßig verwendet das Sample das Modell TCVN_CDM_DETECT_1_1 (224×224 Pixel). Bei sehr kleinen Codes oder Eingangsbildern mit ungünstigen Seitenverhältnissen kann die interne Herunterskalierung auf diese Modellgröße dazu führen, dass kleine Strukturen verloren gehen. Dadurch kann es vorkommen, dass Codes nicht detektiert oder falsch klassifiziert werden. Beispielsweise können QR-Codes und DataMatrix-Codes für das Netz bei starker Verkleinerung visuell kaum noch unterschieden werden, was in manchen Fällen zu Fehlklassifikationen führt.
Zur Optimierung der Detektions- und Klassifizierungsgenauigkeit bieten sich in diesen Fällen zwei Lösungsansätze an, die auch kombinierbar sind:
- Höhere Modellauflösung: Der Wechsel des Parameters
eModelTypeauf ein Modell mit größerem Input (z. B.TCVN_CDM_DETECT_1_2oderTCVN_CDM_DETECT_1_3) stellt dem neuronalen Netz mehr Details zur Verfügung. Die korrekte Klassifizierung der Typen wird dadurch deutlich robuster, erhöht jedoch die Ausführungszeit. - Verwendung einer ROI: Das Setzen einer ROI auf dem Eingangsbild vor der Detektion verkleinert den Bildausschnitt. Dadurch kann einerseits das Seitenverhältnis näher an das Format des Modell-Inputs herangebracht werden, andererseits erhöht sich die effektive Pixelauflösung für das Modell. Idealerweise wird eine ROI entsprechend des vom Modell verwendeten Seitenverhältnisses gesetzt. Dadurch werden Verzerrungen oder Stauchungen der Codes vermieden oder zumindest minimiert. Oft lässt sich so die Erkennung verbessern, ohne dass ein rechenintensiveres Modell verwendet werden muss.