73

Detectar múltiples colores con OpenCV y Python

¡Hola! En este minitutorial voy a resolver una duda que mucha gente me ha comentado: cómo detectar múltiples colores en una imagen con OpenCV y Python.

¿Cómo se hace? Se aplica detección de color a la imagen creando una máscara para cada color que uno quiera detectar: una máscara para los verdes, otra para los azules, otra para los rojos, amarillos… y  se juntan con la función cv2.add().

Los que no sepáis cómo detectar colores con OpenCV, deberíais seguir primero mi Tutorial de Detección de Colores con OpenCV y Python.

¿Hecho? Pues bien, poned un poco de música y empezamos.


 

1- Imagen estática

Para empezar  vamos a detectar los tres colores rojo, verde y azul del logo de OpenCV y los uniremos en una sola máscara.

Guardad la imagen bajo el nombre opencv_logo.png . En el mismo directorio dónde se haya bajado la imagen, cread un nuevo fichero de python. ¡A programar se ha dicho!

Lo primero es lo de siempre: importar las librerías de OpenCV y Numpy, abrir la imagen y convertirla a espacio de color HSV.

import cv2
import numpy as np

imagen = cv2.imread('opencv_logo.png')
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)

 

Después, hay que crear un rango para cada color. Primero los azules y verdes:

#Rango de colores detectados:
#Verdes:
verde_bajos = np.array([49,50,50])
verde_altos = np.array([107, 255, 255])
#Azules:
azul_bajos = np.array([100,65,75], dtype=np.uint8)
azul_altos = np.array([130, 255, 255], dtype=np.uint8)

 

El rango de rojos es un poco más puñetero… si miráis la rueda de color hsv, veréis que el HUE de los rojos está entre 0 – 20, y 240 – 255 (más o menos).

Habrá que crear dos rangos diferentes para los rojos: uno que tenga el Hue entre 0 y 20 y el otro entre 240 y 255.

#Rojos:
rojo_bajos1 = np.array([0,65,75], dtype=np.uint8)
rojo_altos1 = np.array([12, 255, 255], dtype=np.uint8)
rojo_bajos2 = np.array([240,65,75], dtype=np.uint8)
rojo_altos2 = np.array([256, 255, 255], dtype=np.uint8)

 

Se crean las máscaras de la forma normal con la función inRange():

#Crear las mascaras
mascara_verde = cv2.inRange(hsv, verde_bajos, verde_altos)
mascara_rojo1 = cv2.inRange(hsv, rojo_bajos1, rojo_altos1)
mascara_rojo2 = cv2.inRange(hsv, rojo_bajos2, rojo_altos2)
mascara_azul = cv2.inRange(hsv, azul_bajos, azul_altos)

 

Ahora viene lo nuevo: se juntan las máscaras en una sola máscara final que llamaremos ‘mask’. La función cv2.add sólo puede recibir dos argumentos, por lo que habrá que aplicarla varias veces.

#Juntar todas las mascaras
mask = cv2.add(mascara_rojo1, mascara_rojo2)
mask = cv2.add(mask, mascara_verde)
mask = cv2.add(mask, mascara_azul)

 

Para terminar mostramos la imagen inicial, la máscara y salimos al pulsar ESCAPE.

#Mostrar la mascara final y la imagen
cv2.imshow('Finale', mask)
cv2.imshow('Imagen', imagen)

#Salir con ESC
while(1):
    tecla = cv2.waitKey(5) & 0xFF
    if tecla == 27:
        break

cv2.destroyAllWindows()

 

Al final tendréis algo como esto:

# Algoritmo de deteccion de colores multiples
# Por Glar3
# www.robologs.net
#
# Busca los píxeles rojos, verdes y azules de una imagen

import cv2
import numpy as np

imagen = cv2.imread('opencv_logo.png')
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)

#Rango de colores detectados:
#Verdes:
verde_bajos = np.array([49,50,50])
verde_altos = np.array([107, 255, 255])
#Azules:
azul_bajos = np.array([100,65,75], dtype=np.uint8)
azul_altos = np.array([130, 255, 255], dtype=np.uint8)
#Rojos:
rojo_bajos1 = np.array([0,65,75], dtype=np.uint8)
rojo_altos1 = np.array([12, 255, 255], dtype=np.uint8)
rojo_bajos2 = np.array([240,65,75], dtype=np.uint8)
rojo_altos2 = np.array([256, 255, 255], dtype=np.uint8)



#Crear las mascaras
mascara_verde = cv2.inRange(hsv, verde_bajos, verde_altos)
mascara_rojo1 = cv2.inRange(hsv, rojo_bajos1, rojo_altos1)
mascara_rojo2 = cv2.inRange(hsv, rojo_bajos2, rojo_altos2)
mascara_azul = cv2.inRange(hsv, azul_bajos, azul_altos)

#Juntar todas las mascaras
mask = cv2.add(mascara_rojo1, mascara_rojo2)
mask = cv2.add(mask, mascara_verde)
mask = cv2.add(mask, mascara_azul)

#Mostrar la mascara final y la imagen
cv2.imshow('Finale', mask)
cv2.imshow('Imagen', imagen)

#Salir con ESC
while(1):
    tecla = cv2.waitKey(5) & 0xFF
    if tecla == 27:
        break

cv2.destroyAllWindows()


2- Vídeo en tiempo real:

Este otro programa es para detectar colores en un vídeo tomado por una webcam en tiempo real. Detectaremos objetos verdes y amarillos.

No voy a comentarlo línea por línea como el programa anterior porque la idea es la misma. Además el tutorial que he mencionado al principio explica cómo utilizar una webcam.

#Algoritmo de deteccion de colores
#Por Glar3
#www.robologs.net
#
#Detecta objetos verdes y amarillos
 
import cv2
import numpy as np
 
#Iniciar la camara
captura = cv2.VideoCapture(0)
 
while(1):
     
    #Capturamos una imagen y la convertimos de RGB -> HSV
    _, imagen = captura.read()
    hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
 
    #Rango de colores detectados:
    #Verdes:
    verde_bajos = np.array([49,50,50], dtype=np.uint8)
    verde_altos = np.array([100, 255, 210], dtype=np.uint8)
    #Amarillos:
    amarillo_bajos = np.array([16,76,72], dtype=np.uint8)
    amarillo_altos = np.array([30, 255, 210], dtype=np.uint8)
 
    #Detectar los pixeles de la imagen que esten dentro del rango de verdes
    mascara_verde = cv2.inRange(hsv, verde_bajos, verde_altos)
    
    #Detectar los pixeles de la imagen que esten dentro del rango de amarillos
    mascara_amarillo = cv2.inRange(hsv, amarillo_bajos, amarillo_altos)
 
    #Filtrar el ruido aplicando un OPEN seguido de un CLOSE
    kernel = np.ones((6,6),np.uint8)
    mascara_verde = cv2.morphologyEx(mascara_verde, cv2.MORPH_CLOSE, kernel)
    mascara_verde = cv2.morphologyEx(mascara_verde, cv2.MORPH_OPEN, kernel)
    mascara_amarillo = cv2.morphologyEx(mascara_amarillo, cv2.MORPH_CLOSE, kernel)
    mascara_amarillo = cv2.morphologyEx(mascara_amarillo, cv2.MORPH_OPEN, kernel)

    #Unir las dos mascaras con el comando cv2.add()
    mask = cv2.add(mascara_amarillo, mascara_verde)

    #Mostrar la imagen de la webcam y la mascara verde
    cv2.imshow('verde', mask)
    cv2.imshow('Camara', imagen)
    tecla = cv2.waitKey(5) & 0xFF
    if tecla == 27:
        break
 
cv2.destroyAllWindows()

 

Al igual que antes se sale con ESCAPE.

 

Bueno, espero que esto resuelva vuestras dudas sobre cómo detectar varios colores a la vez con OpenCV. Si queréis preguntarme algo más, mis circuitos visuales leerán vuestros comentarios con fruición.

¡Hasta la próxima!

Actualización 3/11/2016: Resolución de errores frecuentes con OpenCV+Python

Gl4r3

Brillante, luminosa y cegadora a veces, Glare es tan artista como técnica. Le encanta dar rienda suelta a sus módulos de imaginación y desdibujar los ya de por si delgados límites que separan el mundo de la electrónica y el arte. Su mayor creación hasta la fecha es un instrumento capaz de convertir los colores y la luz en música. Cuándo sus circuitos no están trabajando en una nueva obra electrónica, le gusta dedicar sus ciclos a la lectura o a documentar sus invenciones para beneficio de los humanos. Sus artilugios favoritos son aquellos que combinan una funcionalidad práctica con un diseño elegante y artístico.

73
Deja un comentario

avatar
30 Hilos iniciados
43 Respuestas a hilos
0 Followers
 
Most reacted comment
Hottest comment thread
30 Nº autores comentarios
ErickGl4r3KevinJoel Leninsilvia Autores de comentarios recientes
más nuevos primero más antiguos primero
Erick
Humano
Erick

Hola Gl4r3.
Una consulta. ¿Como podría distinguir los colores rojo y azul?
Por ejemplo:
Si tengo en una parte del vídeo el color rojo y en otra parte de ese mismo vídeo el color azul. ¿Como podría distinguir esos colores?.
Es que quiero distinguir esos colores, e ir llenando en un arreglo de 3*3 de (0 ó 1) según en que parte del vídeo se encuentra.

Kevin
Humano
Kevin

Amigo disculpe me sale error
Traceback (most recent call last):
File “C:/Users/WIN8/Desktop/ASASA.py”, line 5, in
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
error: OpenCV(3.4.1) C:\build\master_winpack-bindings-win32-vc14-static\opencv\modules\imgproc\src\color.cpp:11214: error: (-215) (scn == 3 || scn == 4) && (depth == 0 || depth == 5) in function cv::cvtColor

Joel Lenin
Humano
Joel Lenin

Hola Gl4r3, gracias por tu tutorial está excelente, mi consulta es sobre un proyecto que vengo analizando de como reconocer unas plagas y al aplicar la codificación HSV y luego una mascara aun me aparece mucho ruido de fondo que confunde el objeto que quiero extraer, como puedo eliminarlo si poseen la misma iluminacion por el sol hojas y el tono de la plaga?

silvia
Humano
silvia

Hola, muchas gracias por toda tu aportación.
Mi problema es que tengo una imagen de un jardin y quiero dectertar lo que unicamente es cesped, entonces cuando hay arboles, y claro tambien son verdes ¿ como hago para detectar solo lo que es cesped?
Gracias,
Saludos

Rigel
Humano
Rigel

¡Hola que tal!, primeramente muchas gracias por todo este contenido, ¡es muy bueno! Ando en proceso de un proyecto, el cual quisiera que detecte los colores del cubo rubik, que en la imagen aparecieran recuadros tales que al poner el cubo rubik entre esos recuadros, se capture el color capturado por cada recuadro exactamente y al final presente el juego de colores de ese conjunto de recuadros, es decir, la cara completa del cubo rubik.
Algo como esto: https://www.youtube.com/watch?v=Vnwv_xW-Fls
Muchas gracias

SemiDiosXD
Humano
SemiDiosXD

hola , gran tutorial pero tengo una duda, no entiendo como se escogen los colores para luego añadirlos al programa osea hsv solo tiene para 3 valores para agregar por ejemplo np.array([110,50,50])
np.array([130,255,255])
como se ponen los colores en hsv para esas dos lineas

daniel
Humano
daniel

Saludos, mi consulta es por que manejaste los rangos en el modelo HSV o cual fue tu criterio para cambiar del modelo RGB. Gracias

Piero Bryan
Humano
Piero Bryan

Hola, quisiera saber si puedo detectar el color blanco, ya que probé una vez con ciertos valores y no me lo detecto, o que valores son los que pondría ?

Enzo Peña
Humano
Enzo Peña

Hola , mi duda es la siguiente : Quisiera condicionar que cada color haga algo como activar una función o un Led así decirlo .¿como lo podría hacer?

Benjamín
Humano
Benjamín

Hola, cuando hago la detección me detecta solo verde y azul, y cuando pongo rojo no detecta nada, a alguien más le pasó ? Saludos

Kamelaz
Humano
Kamelaz

hola tenia una duda y queria ver si me podrias ayudar con eso, me gustaria manejar una imagen hsv pero en lugar de tener h, s y v “juntos” quisiera saber si hay alguna forma de pasar la capa “h” a otra variable y que sea una matriz aparte?

Jesus
Humano
Jesus

Hola, me encanto este tutorial pero tengo un problemita. La cámara me va muy lenta y no se como hacer para aumentar los fps.

Jack Bustinza Gamero
Humano
Jack Bustinza Gamero

¡Que versión de Python usas ?

sMIT
Humano
sMIT

NO FUNCIONA TU WAADA

daniel sepulveda
Humano
daniel sepulveda

buenos dias, tengo una pregunta es que me sale error en la linea 30: mascara_verde = cv2.inRange(hsv, verde_bajos, verde_altos). Me dice que hsv no la tengo definida:
name error: name ‘hsv’ is not defined

Armando
Humano
Armando

Hola, soy nuevo en esto, tengo una tarea en la que debo detectar esos colores, y si se detecta un color, debo encender con la ayuda de un microcontrolador un led del respectivo color, mi pregunta es: ¿Que condicion debo utilizar para tener esas condiciones? Es a tiempo real el procedimiento asi que imagino que debo aplicarlo en la variable (en tu caso imagen), pero no se si deba usar alguna condicion if u opencv tenga alguna funcion para ello, o de alguna manera leer pixeles que da el HSV, aun no comprendo muy bien este tema. Lo estoy realizando… Leer más »

Patricio
Humano
Patricio

Hola GL4R3, estoy siguiendo tus programaciones son muy buenas, tengo una duda con esta, he revisado el codigo de HSV en gimp, pero la escala que me resulta en S va de 0 a 100% y lo mismo en V de 0 a 100%, pero veo q en la programacion usted utiliza el valor de 255 quisiera saber de donde obtuvo ese valor o como lo transformo, ya que quiero detectar otros colores pero no encuentro la forma de ponerlo como usted, en verde me sale que el maximo es H=120° S=100% y V=100%, luego como usted saca 80 255… Leer más »

Obeth
Humano

Buena tarde, gracias por el tutorial. ¿Existe alguna manera de identificar que color fue el detectado, es decir, saber si se detectó el verde o el azul? pretendo mandar por serial un nombre del color y prender un led.

N4n0
Admin

Hola! Una posibilidad rápida es aplicar detección de colores con distintos arrays de máximos y míninimos para saber qué color se está detectando: primero intentas detectar verdes, después rojos, después amarillos…

Obeth
Humano

Gracias eso había echo solo que pensé que había alguna manera más limpia, también e investigado que con moments puedo sacar el centroide del objeto detectado y luego ver si ese pixel es verde o azul por ejemplo, y con eso poder diferenciar pero aún no logro aplicarlo, cuándo lo logre lo comparto, gracias N4n0.

Martin Dominguez
Humano
Martin Dominguez

Buenas, sabras como poder hacer condiciones con esto por ejemplo que me mande algun mensaje si es de color azul, o otro mensaje si es de otro color

Humano
Humano
Humano

Buenas noches, muy buenos los tutoriales todos me han funcionado bien pero no entiendo porque en este no me funciona cv2.cvtColor(…), este es el error que me sale:

OpenCV Error: Assertion failed ((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F)) in cv::cvtColor, file C:buildsmaster_PackSlaveAddon-win32-vc12-staticopencvmodulesimgprocsrccolor.cpp, line 7946
Traceback (most recent call last):
File “C:UsershpMy DocumentsLiClipse WorkspaceOPENCVcOpenCV__init__.py”, line 5, in
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
cv2.error: C:buildsmaster_PackSlaveAddon-win32-vc12-staticopencvmodulesimgprocsrccolor.cpp:7946: error: (-215) (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) in function cv::cvtColor

De antemano muchas gracias

Humano
Humano
Humano

Encontre el error jajaj la imagen no estaba en la carpeta, la proxima vez voy a leer los comentarios si alguien tiene algun error parecido.

Andrés Chavarría
Humano
Andrés Chavarría

Hola! Me encantan estos tutoriales, y me estan siendo muy utiles, en especial este. Ahora quiero hacer una pregunta. Como podría hacer para ademas de color, discriminar por forma?, ambos a la vez.

trackback

[…] cuándo la cámara empiece a capturar imágenes. Para que véais como hacerlo, el código del tutorial para detectar varios colores quedaría […]

Mr Robot
Humano

Antes que nada quiero felicitarte por el gran trabajo que haces al compartir tus conocimientos en cada uno de tus tutoriales.
Tengo un problemilla cuando corro el programa desde una imagen estática, me aparece el siguiente error:
Traceback (most recent call last):
File “C:/Python27/DetectaMultipleColores.py”, line 7, in
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
error: C:\builds\master_PackSlaveAddon-win32-vc12-static\opencv\modules\imgproc\src\color.cpp:7646: error: (-215) (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) in function cv::ipp_cvtColor
De antemano muchas gracias.

Mr Robot
Humano

Encontré el error…no me dí cuenta que la imagen no estaba en la carpeta donde se encuentra el script, moví el archivo de la imagen a la carpeta donde esta el script y el error se solucionó 🙂 . Aún así aprovecho para volver a agradecer por compartir tus conocimientos, saludos desde México.

albertohp
Humano
albertohp

Hola una consulta, como podria hacerse para que detecte varios objetos de color verde? probe tu codigo y solo detecta 1 objeto de color verde pero si se usan varios objetos se marea. Saludos y muchas gracias, eres un gran aporte a la comunidad amigo :).

JoseA
Humano
JoseA

Hola Gl4r3, necesito tu ayuda por farvor. A la hora de correr el programa me sale un error y no se como solucionarlo. El erro es el siguiente:
error:/home/pi/opencv-3.1.0/modules/imgproc/src/color.cpp: 8141: error: (-215)(scn ==3, scn == 4) && (depth == CV_8U, depth == CV_32f) in fuction cvtColor.
Seria de gran ayuda que me pudieras solucionar el problema. Gracias

Ricardo Vivas
Humano

Hola glare, como puedo hacer para saber cual color se detectó en mayor proporción

Ricardo Vivas
Humano

intento hacerlo de esta manera pero siempre me arroja no
if np.array_equal(mask, mascara_verde):
print “verde”
else:
print “no”

Ricardo Vivas
Humano

AAAIIIIUUUUUUDAA

JorgeG
Humano
JorgeG

Clare tu blog es fantástico!… te comento lo de que deseo y espero me puedas orientar: necesito un algoritmo en Python que emplee la librería OpenCV que dado un vídeo 4K y 360 grados de la toma de un árbol frutal haga un reconocimiento automático y el conteo de las frutas en ese árbol. Sabes si existe? Has hecho algo similar que me puedas compartir?

Aprendiz
Humano
Aprendiz

Buen tutorial por si te interesa Adrian Rosebrock creador del blog http://pyimagesearch.com/ desarrollo unos scripts en python que puedes instalar con pip (pip install imutils) entre los cuales veras incluido un pequeño script con trackbars para visualizar diferentes rangos de colores . Si te interesa opencv Adrian es especialista en procesamiento de imagenes y pone recursos muy interesantes en su blog . Yo personalmente os seguire a ambos sin dudarlo.

Anónimo
Humano
Anónimo

Gracias!!!! glare, una consulta para el vídeo en tiempo real, se puede usar el primer código, unir mas mascaras y así tener mas colores?

N4n0
Admin

Que pasa, Glare? Hoy no pones música clásica en el tutorial!

N4n0
Admin

Te han reprogramado?? D:

Luis Americo
Humano

Agradecido por el tutorial aprendi bastante sobre todo con respecto al rango de colores. Tengo la duda estuve buscando en gimp y inkscape el rango, sin embargo los valores que aparecen en tu programa son diferentes. Es decir No logro ubicarlo, tu programa al pelo. Sería interesante ver como en inkscape se logra esto. Gracias