113 votes

Choisir les limites HSV supérieures et inférieures correctes pour la détection des couleurs avec `cv::inRange` (OpenCV)

J'ai une image d'une boîte à café avec un couvercle orange dont je veux trouver la position. Voici l'image image .

L'utilitaire gcolor2 montre que le HSV au centre de la paupière est (22, 59, 100). La question est de savoir comment choisir les limites de la couleur alors ? J'ai essayé min = (18, 40, 90) et max = (27, 255, 255), mais j'ai obtenu des résultats inattendus. result

Voici le code Python :

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()

175voto

Abid Rahman K Points 18045

Problème 1 : Différentes applications utilisent différentes échelles pour le HSV. Par exemple, Gimp utilise H = 0-360, S = 0-100 and V = 0-100 . Mais OpenCV utilise H: 0-179, S: 0-255, V: 0-255 . Ici, j'ai obtenu une valeur de teinte de 22 dans Gimp. Alors j'en ai pris la moitié, 11, et j'ai défini la gamme pour cela. c'est à dire (5,50,50) - (15,255,255) .

Problème 2 : Et aussi, OpenCV utilise le format BGR, pas RGB. Donc changez votre code qui convertit RGB en HSV comme suit :

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

Maintenant, exécute-le. J'ai obtenu une sortie comme suit :

enter image description here

J'espère que c'est ce que vous vouliez. Il y a quelques fausses détections, mais elles sont petites, donc vous pouvez choisir le plus grand contour qui correspond à votre paupière.

EDITAR:

Comme Karl Philip dit dans son commentaire, il serait bon d'ajouter un nouveau code. Mais il n'y a de changement que d'une seule ligne. Donc, je voudrais ajouter le même code implémenté dans la nouvelle version du programme. cv2 afin que les utilisateurs puissent comparer la facilité et la flexibilité des nouvelles technologies. cv2 module.

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)

Il donne le même résultat que ci-dessus. Mais le code est beaucoup plus simple.

101voto

Silencer Points 6351

Ok, trouve la couleur dans HSV L'espace est une question ancienne mais courante. J'ai fait un hsv-colormap pour rechercher rapidement une couleur spéciale. C'est ici :

enter image description here

L'axe des x représente Hue dans [0,180], l'axe des y1 représente Saturation dans [0,255], l'axe des ordonnées2 représente S = 255 tout en gardant V = 255 .

Pour trouver une couleur, il suffit généralement de chercher la gamme de H y S et définir v dans l'intervalle(20, 255).

Pour trouver la couleur orange, on regarde la carte, et on trouve la meilleure portée : H :[10, 25], S: [100, 255], and V: [20, 255] . Le masque est donc cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )

Ensuite, nous utilisons la gamme trouvée pour rechercher la couleur orange, voici le résultat :

enter image description here


La méthode est simple mais courante :

#!/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()

Réponses similaires :

  1. Comment définir une valeur seuil pour détecter uniquement les objets de couleur verte dans une image :Opencv

  2. Choix des valeurs HSV correctes pour le seuillage OpenCV avec InRangeS

76voto

nathancy Points 6407

Voici un simple script de seuils de couleur HSV pour déterminer les plages de couleur inférieure/supérieure à l'aide de barres de commande pour n'importe quelle image sur le disque. Il suffit de modifier le chemin de l'image dans cv2.imread() . Exemple pour isoler l'orange :

enter image description here

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()

Plages de seuils inférieurs/supérieurs de couleur HSV

(hMin = 0 , sMin = 164, vMin = 0), (hMax = 179 , sMax = 255, vMax = 255)

Une fois que vous avez déterminé votre lower y upper Les gammes de couleurs HSV, vous pouvez segmenter vos couleurs désirées comme ceci :

import numpy as np
import cv2

image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 164, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)

cv2.imshow('result', result)
cv2.waitKey()

32voto

Aruldd Points 11

J'ai créé ce programme simple pour obtenir les codes HSV en temps réel.

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()

10voto

Hari Anugrah Points 62

J'ai créé un outil simple (plus approprié) utilisant opencv-python à cette fin. J'ai pensé que cela pourrait être utile pour quelqu'un qui aurait trébuché ici comme je l'ai fait plus tôt cette année.

enter image description here

Comme l'outil lui-même est écrit en utilisant python cv2, il serait garanti d'utiliser la même plage. Il y a aussi un curseur pour erode y dilate car les projets de vision par ordinateur ont généralement besoin de ces deux caractéristiques

Vous pouvez cloner l'outil à partir d'ici https://github.com/hariangr/HsvRangeTool

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X