Elegir los límites HSV superior e inferior correctos para la detección de color con `cv::inRange` (OpenCV)
Tengo una imagen de una lata de café con tapa naranja en la posición de la cual quiero encontrar. Aquí es .
La utilidad gcolor2 muestra que HSV en el centro de la tapa es (22, 59, 100). La pregunta es ¿cómo elegir entonces los límites del color? Probé min = (18, 40, 90) y max = (27, 255, 255), pero obtuve resultados inesperados.
Aquí está el código 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()
Problema 1: diferentes aplicaciones utilizan diferentes escalas para HSV. Por ejemplo, utiliza gimp H = 0-360, S = 0-100 and V = 0-100
. Pero OpenCV usa H: 0-179, S: 0-255, V: 0-255
. Aquí obtuve un valor de tono de 22 en gimp. Así que tomé la mitad, 11, y definí el rango para eso. es decir (5,50,50) - (15,255,255)
.
Problema 2: Y además, OpenCV usa el formato BGR, no RGB. Entonces cambie su código que convierte RGB a HSV de la siguiente manera:
cv.CvtColor(frame, frameHSV, cv.CV_BGR2HSV)
Ahora ejecútelo. Obtuve un resultado de la siguiente manera:
Espero que eso sea lo que querías. Hay algunas detecciones falsas, pero son pequeñas, por lo que puedes elegir el contorno más grande que es tu párpado.
EDITAR:
Como dijo Karl Philip en su comentario, sería bueno agregar un código nuevo. Pero hay cambio de una sola línea. Por lo tanto, me gustaría agregar el mismo código implementado en el nuevo cv2
módulo, para que los usuarios puedan comparar la facilidad y flexibilidad del nuevo cv2
módulo.
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)
Da el mismo resultado que el anterior. Pero el código es mucho más simple.
Ok, encontrar color en HSV
el espacio es una pregunta antigua pero común. Hice una hsv-colormap
búsqueda rápida de un color especial. Aquí lo tienes:
El eje x representa Hue
en [0,180), el eje y1 representa Saturation
en [0,255], el eje y2 representa S = 255
, mientras se mantiene V = 255
.
Para encontrar un color, generalmente simplemente busque el rango de H
y S
y establezca v en el rango (20, 255).
Para encontrar el color naranja, buscamos en el mapa y encontramos el mejor rango: H :[10, 25], S: [100, 255], and V: [20, 255]
. Entonces la máscara escv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )
Luego usamos el rango encontrado para buscar el color naranja, este es el resultado:
El método es simple pero común de usar:
#!/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()
Respuestas similares:
Cómo definir un valor umbral para detectar solo objetos de color verde en una imagen: Opencv
Elegir valores HSV correctos para el umbral de OpenCV con InRangeS
Aquí hay un script de umbral de color HSV simple para determinar los rangos de color inferior/superior usando barras de seguimiento para cualquier imagen en el disco. Simplemente cambie la ruta de la imagen en cv2.imread()
. Ejemplo para aislar naranja:
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()
Rangos de umbral de color inferior/superior de HSV
(hMin = 0 , sMin = 164, vMin = 0), (hMax = 179 , sMax = 255, vMax = 255)
Una vez que haya determinado sus gamas de colores lower
y upper
las de HSV, puede segmentar los colores deseados de esta manera:
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()