Filtros de imágenes por convolución de matrices

Un filtro de imagen es un procedimiento que se aplica a una imagen para resaltar o mejorar algunas características de la misma, para lograr esto se modifica la matriz que compone la imagen aplicándole un determinado procedimiento, en este tutorial estudiaremos el procedimiento llamado convolución de matrices.

Convolución de matrices en OpenCV

OpenCV cuenta con gran variedad de función que aplican los distintos filtros más comunes, estos filtros ya los hemos visto en cursos previos, en esta ocasión utilizaremos la función cv::filter2D(...) que nos permitirá implementar nuestro propio filtro.

Lo primero debemos saber es que para crear un filtro requerimos una matriz de convolución o kernel, esta será una matriz cuadrada cuyos tamaños normalmente son: 3x3, 5x5, 7x7, etc., dependiendo del filtro que deseemos aplicar, esta matriz será usada para calcular el valor de cada pixel de la imagen resultante, a la matriz de convolución se le asigna un punto de anclaje que normalmente se ubica en el centro, este es un ejemplo de una matriz de convolución o kernel.

filtros de imágenes en OpenCV kernel

Para calcular el valor de un pixel tomamos los elementos vecinos al mismo y creamos una ventana de igual tamaño que la matriz de convolución, luego multiplicamos las matrices elemento por elemento y sumamos los resultados para obtener el pixel deseado, normalmente el que se ubica en el centro.

convolución de matrices en opencv

Otra cosa que debemos saber es que tenemos que definir como manejaremos los bordes de la matriz, por ejemplo, para calcular el valor del pixel en la posición (0, 0) la ventana de convolución sobresale de la matriz, mira la imagen:

filtrado de imagen en opencv

En OpenCV la enumeración cv::BorderTypes define las opciones que tenemos disponibles, podemos utilizar la función copyMakeBorder() para ver los distintos tipos de bordes, esta función agrega un borde del tipo indicado a una imagen, debemos indicar las dimensiones del bordes en cada una de sus lados correspondientes, para nuestro ejemplo todos son iguales.

int dim = 20;
Mat border_w, border_r;

copyMakeBorder(src, border_w, dim, dim, dim, dim, cv::BorderTypes::BORDER_WRAP);
copyMakeBorder(src, border_r, dim, dim, dim, dim, cv::BorderTypes::BORDER_REPLICATE);

opencv agregar bordes a imágenes

Existen más tipos de bordes que podemos utilizar, te queda de tarea explorar los demás.

Filtro de imágenes en OpenCV

Con esto ya tenemos los conocimientos necesarios para aplicar filtros a nuestras imágenes en OpenCV, esta biblioteca nos facilita la tarea con la función cv::filter2D() diseñada para tal propósito, si deseas trabajar directamente sobre los pixeles puedes ver el tutorial acceso a los pixeles de un Mat, si usamos la función antes mencionada solo debemos indicar como mínimo la imagen de entrada, la de salida y el kernel.

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    String imagen = "../../../opencv-3.2.0/samples/data/lena.jpg";

    Mat src = imread(imagen, CV_LOAD_IMAGE_GRAYSCALE);

    if (src.empty()) {
        cout << "No se ha podido leer la imagen: " << imagen << endl;
    }

    Mat dst;
    Mat kernel = (Mat_<char>(3, 3) << 0,  1, 0,
                                      1, -4, 1,
                                      0,  1, 0);

    cv::filter2D(src, dst, src.depth(), kernel);

    imshow("Display Image", src);
    imshow("Display Filter2D", dst);

    waitKey(0);

    return 0;
}

filtro de bordes

Mat kernel = (Mat_<char>(3, 3) << -2, -1, 0,
                                  -1,  1, 1,
                                   0,  1, 2);

cv::filter2D(src, dst, src.depth(), kernel);

filtro de repujado

Esta función usa tres parámetros adicionales, en nuestro ejemplo no los utilizamos, ellos son: anchor: define la posición de anclaje por defecto es el centro del kernel, delta: indica un valor que se sumará al filtro, por defecto es cero, por ultimo, borderType: indica el tipo de borde por defecto se usa BORDER_DEFAULT.

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Acceso a la webcam con OpenCV

JavaFx 8 Administrar ventanas

Conociendo la clase cv::Mat de OpenCV