Check Color Range

In diesem Beispiel werden mit Hilfe der Funktion F_VN_CheckColorRange rote, grüne und blaue Objekte im Bild gesucht und entsprechend ihrer Farbe beschriftet. Dabei wird die Funktion wahlweise auf RGB- oder HSV-Bilder angewendet. Es ist auch möglich, die Funktion auf Bilder anderer Farbräume wie zum Beispiel Lab, BGR oder YCrCb anzuwenden, die Bildkonvertierung und Schwellwert-Parametrierung ist dann entsprechend anzupassen.

Erläuterung

Der Code ermöglicht die Auswahl des Farbraums für die Farbbereichssegmentierung. Über die Variable eColorSpace kann zwischen beiden Varianten, RGB und HSV, umgeschaltet werden. Je nach gewähltem Farbraum werden unterschiedliche Schwellwertarrays (aColorRefLowRGB/aColorRefUpRGB für RGB oder aColorRefLowHSV/aColorRefUpHSV für HSV) verwendet. Die Variablen enthalten die jeweilig definierten unteren und oberen Grenzwerte für die drei zu detektierenden Farben (Rot, Grün, Blau). Die Referenzen refColorLow und refColorUp verweisen auf die jeweiligen aktiven Arrays.

Das Eingangsbild liegt im Bayer RG Format vor und wird mit der Funktion F_VN_ConvertColorSpace in ein RGB-Bild konvertiert. Im RGB-Modus wird das konvertierte Bild direkt verwendet, während im HSV-Modus eine zusätzliche Farbraumkonvertierung von RGB nach HSV mit der Transformation TCVN_CST_RGB_TO_HSV_FULL durchgeführt wird. Die Variante HSV_FULL wird gewählt, damit der Hue-Kanal den vollen 8-Bit-Wertebereich (0-255) nutzt, statt wie bei HSV auf 0-179 begrenzt zu sein, was eine feinere Parametrierung ermöglicht. Der HSV-Farbraum liefert oft robustere Ergebnisse bei ungleichen Lichtverhältnissen, da die Farbwerte (Hue) von der Farbsättigung (Saturation) und Helligkeit (Value) getrennt sind. Im additiven RGB-Farbraum führt eine Änderung der Helligkeit in der Regel zu Wertänderungen in allen 3 Kanälen, was eine Festlegung von Schwellwerten zur Unterscheidung erschwert.

Schließlich kann die Funktion F_VN_CheckColorRange mit den jeweiligen oberen und unteren Schwellwerten angewendet werden.

Variablen

eColorSpace             :   (RGB, HSV); // Selected color space

hr                      :   HRESULT;

// Images
ipImageIn               :   ITcVnImage;
ipImageInDisp           :   ITcVnDisplayableImage;

ipImageColorSpace       :   ITcVnImage;
ipImageColorSpaceDisp   :   ITcVnDisplayableImage;

ipImageWorkCol          :   ITcVnImage;
ipImageWorkColDisp      :   ARRAY [0..2] OF ITcVnDisplayableImage;

ipImageRes              :   ITcVnImage;
ipImageResDisp          :   ITcVnDisplayableImage;

// Colors
iColor                  :   INT;
aColorTxt               :   ARRAY[0..2] OF STRING := [ 'RED', 'GREEN', 'BLUE' ];
aColor                  :   ARRAY[0..2] OF TcVnVector4_LREAL := [ [150, 0, 0], [0, 255, 0], [0, 0, 255] ];
refColorBoundsLow       :   REFERENCE TO ARRAY[0..2] OF TcVnVector4_LREAL;
refColorBoundsUp        :   REFERENCE TO ARRAY[0..2] OF TcVnVector4_LREAL;

// Bounds values for RGB
aColorBoundsLowRGB      :   ARRAY[0..2] OF TcVnVector4_LREAL := [ [150, 50, 20], [35, 90, 60], [20, 40, 130] ];
aColorBoundsUpRGB       :   ARRAY[0..2] OF TcVnVector4_LREAL := [ [255, 120, 100], [100, 200, 140], [60, 160, 255] ];

// Bounds values for HSV
aColorBoundsLowHSV      :   ARRAY[0..2] OF TcVnVector4_LREAL := [ [251, 180, 205], [103, 150, 100], [130, 180, 130] ];
aColorBoundsUpHSV       :   ARRAY[0..2] OF TcVnVector4_LREAL := [ [6, 220, 255], [113, 190, 190], [149, 230, 210] ];

// Contours
ipContourList           :   ITcVnContainer;
ipIterator              :   ITcVnForwardIterator;
ipContour               :   ITcVnContainer;
fArea                   :   LREAL;
aCenter                 :   TcVnPoint2_LREAL;

Code

// Attention: With other images another color space transformation could be necessary
hr := F_VN_ConvertColorSpace(ipImageIn, ipImageRes, TCVN_CST_Bayer_RG_TO_RGB, hr);

// Select the color space for segmentation
CASE eColorSpace OF
    RGB:
        hr := F_VN_CopyImage(ipImageRes, ipImageColorSpace, hr);
        refColorBoundsLow REF= aColorBoundsLowRGB;
        refColorBoundsUp REF= aColorBoundsUpRGB;
        
    HSV:
        hr := F_VN_ConvertColorSpace(ipImageRes, ipImageColorSpace, TCVN_CST_RGB_TO_HSV_FULL, hr);
        refColorBoundsLow REF= aColorBoundsLowHSV;
        refColorBoundsUp REF= aColorBoundsUpHSV;
END_CASE

FOR iColor := 0 TO 2 DO
    
    // Apply a "Color-Threshold" on the image
    hr := F_VN_CheckColorRange(ipImageColorSpace, ipImageWorkCol, refColorBoundsLow[iColor], refColorBoundsUp[iColor], hr);
    
    // Find all objects / contours in the black and white image
    hr := F_VN_FindContours(ipImageWorkCol, ipContourList, hr);    
    hr := F_VN_GetForwardIterator(ipContourList, ipIterator, hr);

    // Filter the objects by size and draw the contours
    WHILE SUCCEEDED(hr) AND_THEN ipIterator.CheckIfEnd() <> S_OK DO

        hr := F_VN_GetContainer(ipIterator, ipContour, hr);
        hr := F_VN_IncrementIterator(ipIterator, hr);
        
        // Filter contours by size
        hr := F_VN_ContourArea(ipContour, fArea, hr);

        IF fArea > 5000 THEN
            // Draw Results into an Image
            hr := F_VN_DrawContours(ipContour, -1, ipImageRes, aColor[iColor], 3, hr);
            hr := F_VN_ContourCenterOfMass(ipContour, aCenter, hr);
            hr := F_VN_PutText(aColorTxt[iColor], ipImageRes, LREAL_TO_UDINT(aCenter[0])-30, LREAL_TO_UDINT(aCenter[1])+10, TCVN_FT_HERSHEY_PLAIN, 2, aColor[iColor], hr);
        END_IF
    END_WHILE
        
    // Display effect of the CheckColorRange-Function
    hr := F_VN_TransformIntoDisplayableImage(ipImageWorkCol, ipImageWorkColDisp[iColor], hr);
END_FOR

Ergebnis

In ipImageColorSpaceDisp wird der gewählte Farbraum im ADS Image Watch dargestellt. Dies ermöglicht die Analyse der exakten Pixelwerte zur Optimierung der Schwellwertparametrierung. Das HSV-Bild wird dabei in Falschfarben dargestellt, da die H-, S- und V-Kanäle als RGB interpretiert werden.

Check Color Range 1:

Die Binärbilder ipImageWorkColDisp[0..2] zeigen die Segmentierungsergebnisse für jede Farbe. Wird als Farbraum RGB ausgewählt, sind häufig Artefakte an den Objektkanten sichtbar. Das liegt daran, dass alle drei Farbkanäle mit der Helligkeit gekoppelt sind. Dadurch können Beleuchtungsgradienten und Glanzlichter an Objektkanten die Farbwerte so stark verändern, dass sie ungewünscht innerhalb oder außerhalb des Segmentierungsbereichs fallen. Der HSV-Farbraum liefert in der Regel sauberere Segmentierungen, da die Schwellwerte von der Helligkeit (Value) und der Sättigung (Saturation) getrennt von den Farbinformationen (Hue) eingestellt werden können.

Bei der Farbbereichsprüfung von Rottönen im HSV-Farbraum kann F_VN_CheckColorRange das sogenannte „Wraparound-Problem“ des Hue-Kanals korrekt verarbeiten, da der Rot-Bereich sich ca. +-20° um 0° erstreckt. Wenn der untere Grenzwert für den Farbton größer als der obere Grenzwert definiert wird (z. B. 251 bis 6), erkennt die Funktion dies automatisch als kreisförmigen Bereich über den Nullpunkt hinweg. Dies erspart die manuelle Aufteilung in zwei separate Farbbereiche sowie Funktionsaufrufe und ermöglicht die Erkennung des gesamten Farbbereiches in einem einzigen Schritt.

Check Color Range 2:

Das Ergebnisbild ipImageResDisp zeigt die detektierten Objekte mit farbigen Konturen und Beschriftungen entsprechend ihrer erkannten Farbe.

Check Color Range 3:

Ähnliche Beispiele