Visión artificial, filtro de color con OpenCV inRange. Está una función que permite filtrar una ventana de valores para pixeles en una imagen. Por ejemplo, está función se utilizaría en el procedimiento de crear un rastreador por color, para obtener como resultado una imagen binaria con el objeto detectado. Entonces en otras palabras, la función acepta como entrada una imagen de 1 o más dimensiones y da como resultado una imagen binaria. Para el resultado de la imagen en blanco y negro, el blanco representa a todos los pixeles que fueron validos para el rango filtrado. En este tutorial te indicaremos varios ejemplos para usar a la función y además como crear un proyecto para usar la función inRange de OpenCV con QT Creator en Ubuntu 16.04.
Sintaxis:
- void inRange(MatrizOriginal, Scalar(ValorMinCanal-0, ValorMinCanal-1, ValorMinCanal-2), Scalar(ValorMaxCanal-0, ValorMaxCanal-1,ValorMaxCanal-2), MatrizBinariaDestino);
Parámetros de entrada:
- MatrizOriginal. Es una matriz que contiene a una imagen.
- MatrizBinariaDestino es la matriz donde se guardará el resultado del filtro de ventana.
- ValorMinX representa un valor entero positivo que esta relacionado con los bits de la imagen, y que indica el valor mínimo del filtro de dos rangos para una ventana de valores.
- ValorMaxX indica el numero entero positivo que relaciona al valor máximo del filtro doble de la imagen.
Ejemplo 1 – Filtrar todos los valores de 1 canal para una imagen RGB con OpenCV inrange
Para el ejemplo 1, le pasaremos el filtro inRange de OpenCV a una imagen de 3×3 pixeles. Entonces para el filtro se configurará para que sólo se deje pasar a todos los pixeles del canal 1. Es decir, todo los pixeles VERDES. El resultado será una matriz de 1 canal de color blanco y negro con todos los pixeles blancos que cumplan con estos valores del filtro de la ventana. Por ejemplo considere el resultado con la siguiente imagen:
- inRange(ImagenRGB, Scalar(0,0,0), Scalar(0,255,0), Salida);
Ejemplo 2 – Usar la función de OpenCV inRange para dejar pasar todo
Veamos el un caso donde podemos configurar al filtro ventana de cada uno de los canales para que pase todo. El resultado sera una matriz de puntos blancos para todos los pixeles.
- inRange(ImagenRGB, Scalar(0,0,0), Scalar(255,255,255), resultado);
Ejercicio 1 para la función de OpenCV inRange
Considere la siguiente imagen, que valores binarios serán 1 o 0 si la imagen de entrada BGR tiene los siguientes valores:
Respuesta. Todos los pixeles serán 0, porque aunque puede que hay pixeles en los canales 1 y 2 que cumplan con el rango del filtro, el primer canal esta mal filtrado, al dejar pasar sólo a los pixeles que cumplan con la siguiente condición: PixelBlanco si el pixel canal 0 es > 150 y < 0. Por lo tanto esta condición excluye al resto de los filtros.
Ejercicio 2
Resultado del Ejercicio – 2
Dado que el filtro deja pasar a todos los pixeles rojos y verdes (canal 1 y canal 2 respectivamente), el filtro en realidad esta dominado por la ventana del canal 0. Y solo dejara pasar a aquellos pixeles que estén dentro de 150 a 250. Esto solo corresponde a la columna central. Dado que los canales 1 y 2 no tienen componentes verdes estos se excluyen del filtraje. Por lo tanto las operaciones del filtro de OpenCV inrange que realiza entre filtro y filtro es una tipo de operación lógica AND.
Ejercicio 3
Cuál será el resultado de la siguiente instrucción:
Resultado del ejercicio 3
Para el ultimo resultado, el único pixel que cumple con las 3 condiciones de los 3 filtros ventana para cada canal, es:
Ejemplo para crear un filtro de color con OpenCV inRange y QT Creator en Ubuntu 16.04
Ahora integraremos a una función inRange en un proyecto de QT para crear un filtro de color. Para poder continuar requieres los siguientes conocimientos previos:
Requisitos para el siguiente ejemplo:
- Crear proyecto nuevo en QT.
- Configurar QT para compilar Opencv en Ubuntu 16.04.
- Uso del QTimer en QT para generar contador.
- OpenCV clase Mat.
- OpenCV imread.
- QFileDialog para abrir un cuadro de dialogo.
- OpenCV resize.
- Función de OpenCV cvtColor.
- OpenCV GaussianBlur.
- Uso de barraHorizontal en QT.
Procedimiento para configurar el proyecto
Primero comenzaremos por crear un proyecto nuevo.
- Configurar el proyecto para poder compilar las bibliotecas de OpenCV.
- En el archivo .pro se coloca el siguiente código:
- INCLUDEPATH += /usr/local/include/opencv2
- LIBS += -L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_videoio
- CONFIG += link_pkgconfig
- PKGCONFIG += opencv
- Se agrega al proyecto las bibliotecas de mat2qimage.cpp y mat2qimage.h.
- En el archivo de MainWIndow.cpp se agregan las siguientes bibliotecas.
- #include<opencv2/core/core.hpp>
- #include<opencv2/ml/ml.hpp>
- #include<opencv/cv.h>
- #include<opencv2/imgproc/imgproc.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<opencv2/video/background_segm.hpp>
- #include<opencv2/videoio.hpp>
- #include<opencv2/imgcodecs.hpp>
- #include «mat2qimage.h» //Nota1
- #include <QFileDialog>
- #include <QTimer>
- Agregar el nombre de espacio para opencv.
- using namespace cv;
- Se agregarán las siguientes variables globales.
- Mat IMAGEN; //Para guardar la imagen que se abrirá
- Mat IMAGENchica; //Guardará la imagen pequeña
- Mat ImagenHSV; //Aquí se guarda la imagen HSV
- Mat ImagenDesenfoque; //Para la imagen con desenfoque
- Mat ImagenFiltrada; //Para la imagen binaria que resulta de inRange
- En el archivo .pro se coloca el siguiente código:
Procedimiento para crear la GUI en QT
- Se agregarán al proyecto los siguientes elementos de salida y entrada. Nota2.
2. – Se nombrarán a las 4 etiquetas principales, las 6 barras de desplazamiento y los 6 lcdNumber, de la siguiente manera:
- barraCanal0Max, barraCanal0Min, barraCanal1Max, barraCanal1Min, barraCanal2Max, barraCanal2Min,.
- labelColor, labelGauss, labelHSV, labelInrange.
- lcdCanal0Max, lcdCanal0Min, lcdCanal1Max, lcdCanal1Min, lcdCanal2Max, lcdCanal2Min.
3.- Para cada una de las barras se creará la función sliderMoved(int) en esta función se modificará el valor de los lcdNumber. Por ejemplo, para la barraCanal0Max:
- void MainWindow::on_barraCanal0Max_sliderMoved(int position){
- ui->lcdCanal0Max->display(position);
- }
Esto se tiene que hace para cada una de las 6 barras con su lcd correspondiente.
4.- Se creará la función click para el botón y se agregará el siguiente código: (Si estas viendo este tutorial en un celular, tienes que abrir el siguiente enlace:).
5.- Se creará un cronometro para que sea ejecutado cada 100ms. Entonces este proceso esta dividido en dos pasos.
- Crear, conectar e iniciar el cronometro. Por ejemplo, las siguientes líneas se colocan despues de la instrucción setupUi del archivo MainWindow.cpp.
- QTimer *cronometro = new QTimer(this);
- connect(cronometro,SIGNAL(timeout()),this,SLOT(ftimer()));
- cronometro->start(100);
- Se creará la función ftimer, tanto en el código cpp como en la cabecera .h.
- void MainWindow::ftimer(){ }
6.- En la función del timer se colocará el siguiente código.
- void MainWindow::ftimer(){
- //Paso # 1 – Procesar imagen anterior para filtro doble
- f(!ImagenHSV.empty()){
- int canal0Min = ui->barraCanal0Min->value();
- int canal0Max = ui->barraCanal0Max->value();
- int canal1Min = ui->barraCanal1Min->value();
- int canal1Max = ui->barraCanal1Max->value();
- int canal2Min = ui->barraCanal2Min->value();
- int canal2Max = ui->barraCanal2Max->value();
- nRange(IMAGENchica,Scalar(canal0Min,canal1Min,canal2Min),Scalar(canal0Max,canal1Max,canal2Max),ImagenFiltrada);
- Image qImage = Mat2QImage(ImagenFiltrada);
- QPixmap pixmap = QPixmap::fromImage(qImage);
- ui->labelInrange->clear();
- ui->labelInrange->setPixmap(pixmap);
- }
- }
Código de MainWindow.cpp
https://hetpro-store.com/TUTORIALES/EjemplosProgramas/QT-OpenCV-9-inRange.zip
Nota1. Es recomendable copiar el código desde el enlace de Github que tiene este tutorial, de otro modo puede que los caracteres no se copien correctamente.
Nota2. Se deben de modificar los valores máximos para las barras horizontales, para que sea 255. (valor máximo para los pixeles de 8 bits).
Autor: Dr. Rubén Estrada Marmolejo