Auswahl der richtigen oberen und unteren HSV-Grenzen für die Farberkennung mit`cv :: inRange` (OpenCV)


79

Ich habe ein Bild von einer Kaffeedose mit einer orangefarbenen Deckelposition, die ich finden möchte. Hier ist esBild .

Das Dienstprogramm gcolor2 zeigt HSV in der Mitte des Deckels als (22, 59, 100) an. Die Frage ist, wie man dann die Grenzen der Farbe wählt. Ich habe versucht, min = (18, 40, 90) und max = (27, 255, 255), aber unerwartetErgebnis

Hier ist der Python-Code:

import cv

in_image = 'kaffee.png'
out_image = 'kaffee_out.png'
out_image_thr = 'kaffee_thr.png'

ORANGE_MIN = cv.Scalar(18, 40, 90)
ORANGE_MAX = cv.Scalar(27, 255, 255)
COLOR_MIN = ORANGE_MIN
COLOR_MAX = ORANGE_MAX

def test1():
    frame = cv.LoadImage(in_image)
    frameHSV = cv.CreateImage(cv.GetSize(frame), 8, 3)
    cv.CvtColor(frame, frameHSV, cv.CV_RGB2HSV)
    frame_threshed = cv.CreateImage(cv.GetSize(frameHSV), 8, 1)
    cv.InRangeS(frameHSV, COLOR_MIN, COLOR_MAX, frame_threshed)
    cv.SaveImage(out_image_thr, frame_threshed)

if __name__ == '__main__':
    test1()

Ich habe die Werte (22, 59, 100) als HSV überprüft und sie scheinen nicht mit einer Farbe übereinzustimmen, die der des Deckels ähnelt. Aber als BGR machen sie Sinn. Wie haben Sie diese Werte abgerufen?
Karlphillip

Hier ist ein Screenshot mit gcolor2 imageshack.us/photo/my-images/23/rgb2hsv.png . Ich habe dann die Farbnummer # FFA069 auf yafla.com/yaflaColor/ColorRGBHSL.aspx?RGB=&Colors= ,,,,,,,, und die Konvertierung ist dieselbe.
Student FourK

4
Dies ist wahrscheinlich auf verschiedene HSV-Bereiche in OpenCV zurückzuführen, nämlich H: 0 - 180, S: 0 - 255, V: 0 - 255.
Student FourK

Antworten:


145

Problem 1: Unterschiedliche Anwendungen verwenden unterschiedliche Maßstäbe für den HSV. Zum Beispiel Gimp verwendet H = 0-360, S = 0-100 and V = 0-100. Aber OpenCV verwendet H: 0-179, S: 0-255, V: 0-255. Hier habe ich einen Farbtonwert von 22 in Gimp. Also nahm ich die Hälfte davon, 11, und definierte den Bereich dafür. dh (5,50,50) - (15,255,255).

Problem 2: Außerdem verwendet OpenCV das BGR-Format, nicht RGB. Ändern Sie also Ihren Code, der RGB in HSV konvertiert, wie folgt:

cv.CvtColor(frame, frameHSV, cv.CV_BGR2HSV)

Führen Sie es jetzt aus. Ich habe eine Ausgabe wie folgt erhalten:

Geben Sie hier die Bildbeschreibung ein

Hoffe das ist was du wolltest. Es gibt einige falsche Erkennungen, aber sie sind klein, sodass Sie die größte Kontur wählen können, die Ihr Deckel ist.

BEARBEITEN:

Wie Karl Philip in seinem Kommentar sagte, wäre es gut, neuen Code hinzuzufügen. Es ändert sich jedoch nur eine einzige Zeile. Daher möchte ich denselben Code hinzufügen, der in einem neuen cv2Modul implementiert ist , damit Benutzer die Einfachheit und Flexibilität eines neuen cv2Moduls vergleichen können.

import cv2
import numpy as np

img = cv2.imread('sof.jpg')

ORANGE_MIN = np.array([5, 50, 50],np.uint8)
ORANGE_MAX = np.array([15, 255, 255],np.uint8)

hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

frame_threshed = cv2.inRange(hsv_img, ORANGE_MIN, ORANGE_MAX)
cv2.imwrite('output2.jpg', frame_threshed)

Es ergibt sich das gleiche Ergebnis wie oben. Code ist jedoch viel einfacher.


+1 Wieder einmal ausgezeichnet. Wenn Sie den vollständigen Quellcode mit Ihren Änderungen hinzufügen könnten, wäre es fantastisch.
Karlphillip

Vielen Dank. Aber ich glaube nicht, dass es hier viel Exzellenz gibt. :) (OK, ich werde es tun)
Abid Rahman K

1
Großartig! Es funktioniert jetzt auch für mich, obwohl ich glaube, dass Ihre S- und V-Min-Max-Bereiche zu entspannt sind. Ich habe auch eine gute Deckelabdeckung mit min (5, 100, 255) und max (15, 200, 255).
Student FourK

Gut zu wissen. Ich habe S, V-Werte genommen, um das Ergebnis zu zeigen, um zu zeigen, dass diese Lösung funktioniert. Gut, dass du bessere gefunden hast. Versuchen Sie auch, auf die cv2Schnittstelle zu wechseln . Es ist einfacher und schneller. Einige gute Tutorials finden Sie hier: opencvpython.blogspot.com. Und wenn es Ihr Problem löst, akzeptieren Sie die Antwort und schließen Sie diese Sitzung.
Abid Rahman K

Dies ist der Ort, an dem jeder Fehler begeht, wenn er ein Neuling bei OpenCv ist.
Nbsrujan

56

Ok, Farbe im HSVRaum zu finden ist eine alte, aber häufige Frage. Ich habe eine hsv-colormapzu schnelle Suche nach Sonderfarben gemacht. Hier ist es:

Geben Sie hier die Bildbeschreibung ein

Die x-Achse repräsentiert Huein [0,180], die y-Achse1 repräsentiert Saturationin [0,255], die y-Achse2 repräsentiert S = 255, während behalten V = 255.

Um eine Farbe zu finden, suchen Sie normalerweise nur nach dem Bereich von Hund Sund setzen Sie v im Bereich (20, 255).

Um die orange Farbe zu finden, suchen wir nach der Karte und finden den besten Bereich : H :[10, 25], S: [100, 255], and V: [20, 255]. So ist die Maskecv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )

Dann verwenden wir den gefundenen Bereich, um nach der orange Farbe zu suchen. Dies ist das Ergebnis:

Geben Sie hier die Bildbeschreibung ein


Die Methode ist einfach, aber häufig anzuwenden:

#!/usr/bin/python3
# 2018.01.21 20:46:41 CST
import cv2

img = cv2.imread("test.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )
cv2.imshow("orange", mask);cv2.waitKey();cv2.destroyAllWindows()

Ähnliche Antworten:

  1. So definieren Sie einen Schwellenwert, um nur Objekte mit grüner Farbe in einem Bild zu erkennen: Opencv

  2. Auswahl der richtigen HSV-Werte für die OpenCV-Schwellenwertbildung mit InRangeS


zweiter Link verhält sich merkwürdig?
jtlz2

1
@ jtlz2: Sie haben einfach auf diese Antwort verlinkt . Vielleicht aus Versehen.
Martijn Pieters

Ein bisschen spät, aber ich frage mich, wie Sie den V-Wert bestimmt haben. In meiner Anwendung verwende ich Histogramme, um die H / S-Werte zu bestimmen, war mir aber nicht sicher, ob V. Wenn 0-100% dunkel / hell sind, würden wir in einem anständig beleuchteten Raum wohl nur einen Medianwert wählen?
Jacob David C. Cunningham

29

Ich habe dieses einfache Programm erstellt, um HSV-Codes in Echtzeit abzurufen

import cv2
import numpy as np


cap = cv2.VideoCapture(0)

def nothing(x):
    pass
# Creating a window for later use
cv2.namedWindow('result')

# Starting with 100's to prevent error while masking
h,s,v = 100,100,100

# Creating track bar
cv2.createTrackbar('h', 'result',0,179,nothing)
cv2.createTrackbar('s', 'result',0,255,nothing)
cv2.createTrackbar('v', 'result',0,255,nothing)

while(1):

    _, frame = cap.read()

    #converting to HSV
    hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)

    # get info from track bar and appy to result
    h = cv2.getTrackbarPos('h','result')
    s = cv2.getTrackbarPos('s','result')
    v = cv2.getTrackbarPos('v','result')

    # Normal masking algorithm
    lower_blue = np.array([h,s,v])
    upper_blue = np.array([180,255,255])

    mask = cv2.inRange(hsv,lower_blue, upper_blue)

    result = cv2.bitwise_and(frame,frame,mask = mask)

    cv2.imshow('result',result)

    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cap.release()

cv2.destroyAllWindows()

9
LOL, ich hatte denselben Code beim Drucken der endgültigen HSV-Werte geschrieben, die unter github.com/saurabheights/ImageProcessingExperimentScripts/blob/… verwendet wurden.
saurabheights

16

Hier ist ein einfaches HSV-Farb-Thresholder-Skript zum Bestimmen der unteren / oberen Farbbereiche mithilfe von Spurleisten für jedes Bild auf der Festplatte. Ändern Sie einfach den Bildpfad incv2.imread()

Geben Sie hier die Bildbeschreibung ein

import cv2
import numpy as np

def nothing(x):
    pass

# Load image
image = cv2.imread('1.jpg')

# Create a window
cv2.namedWindow('image')

# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)

# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

while(1):
    # Get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin', 'image')
    sMin = cv2.getTrackbarPos('SMin', 'image')
    vMin = cv2.getTrackbarPos('VMin', 'image')
    hMax = cv2.getTrackbarPos('HMax', 'image')
    sMax = cv2.getTrackbarPos('SMax', 'image')
    vMax = cv2.getTrackbarPos('VMax', 'image')

    # Set minimum and maximum HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Convert to HSV format and color threshold
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    result = cv2.bitwise_and(image, image, mask=mask)

    # Print if there is a change in HSV value
    if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display result image
    cv2.imshow('image', result)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

Das war sehr hilfreich. 20-mal schneller einen geeigneten HSV-Bereich gefunden. Viele Mahalos!
Vielleicht

Beeindruckend! Sehr hilfreich, wie bereits kommentiert. Danke für das Teilen!
KlopDesign

Pure Großartigkeit! Vielen Dank
Seminko

4

Der OpenCV-HSV-Bereich beträgt: H: 0 bis 179 S: 0 bis 255 V: 0 bis 255

Bei Gimp (oder anderen Fotomanipulations-Sw) liegt der Farbton zwischen 0 und 360, da opencv Farbinformationen in ein einzelnes Byte einfügt. Der maximale Zahlenwert in einem einzelnen Byte beträgt 255, daher entsprechen openCV-Farbtonwerte den Farbtonwerten von gimp geteilt durch 2 .

Beim Versuch, eine Objekterkennung basierend auf dem HSV-Farbraum durchzuführen, stellte ich fest, dass ein Bereich von 5 (OpenCV-Bereich) ausreichte, um eine bestimmte Farbe herauszufiltern. Ich würde Ihnen raten, einen HSV-Farbgaumen zu verwenden, um herauszufinden, welcher Bereich für Ihre Anwendung am besten geeignet ist.

HSV-Farbgaumen mit Farberkennung im HSV-Raum


3

Versuchen Sie die folgenden Befehle im Python-Terminal, um den HSV-Wert von Grün zu ermitteln

green = np.uint8([[[0,255,0 ]]])
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
print hsv_green
[[[ 60 255 255]]]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.