Filtros no lineales y Morfología matemática (Procesamiento de imágenes) (página 2)
Enviado por Pablo Turmero
La idea se puede generalizar a imágenes no binarias: Dilatación. Combinar con Máximo. Erosión. Combinar con Mínimo.
Morfología matemática. El efecto de la dilatación es extender o ampliar las regiones de la imagen con valor 1 (color blanco), mientras que la erosión las reduce. La cantidad depende del tamaño y forma del elemento estructurante y del número de veces que se aplican. Ejemplo. Imagen de entrada Elemento estructurante Dilatación 1 Dilatación 3 Erosión 1 Erosión 3
Morfología matemática. Existen otras dos operaciones frecuentes basadas en erosión y dilatación: Abrir. Aplicar erosión y después dilatación: (B?E)?E Cerrar. Aplicar dilatación y después erosión: (B?E)?E
Imagen de entrada Elemento estructurante Abrir: desaparecen los puntos sueltos o estructuras finas Cerrar: se rellenan los huecos negros de cierto tamaño
Morfología matemática. Ejemplo. Segmentación de objetos.Para segmentar un objeto del fondo usamos una simple umbralización. Funciona más o menos bien, pero aparecen algunos puntos mal clasificados. Falsos negativos Falsos positivos Usar morfología para arreglar los falsos. Imagen de entrada Umbralizada (u=130)
Morfología matemática. Cerrar 2 (B?E?E)?E?E Abrir 1 (B?E)?E Imagen umbralizada Eliminar falsos negativos Eliminar falsos positivos Erosión 2 (B?E)?E Eliminar píxeles de los bordes
Morfología matemática. El resultado es la máscara para segmentar el objeto. ¿Para qué se hacen las dos últimas erosiones?
Morfología matemática. En imágenes no binarias, el resultado de dilatación y erosión es parecido a las operaciones de máximo y mínimo. De hecho, es igual si el elemento estructurante es todo 1. Imagen entrada Erosión, 1 Dilatación, 3 Cierre, 2
Morfología matemática. Existen otras operaciones de morfología, basadas en las elementales, que son útiles en análisis de imágenes. Ejemplo 1. Borde morfológico: (B?E) – B Imagen de entrada Borde morfológico Ejemplo 2. Adelgazamiento (thinning). Aplicar una erosión, pero no eliminar el punto (no poner a 0) si se separa una región conexa en varias o si sólo queda un punto.
Filtros y transformaciones locales. Conclusiones: Las operaciones de procesamiento local son esenciales en mejora de imágenes, restauración, análisis, etc. Dos categorías básicas: Filtros lineales o convoluciones: la salida es una combinación lineal de los píxeles en una vecindad ? Suavizado, bordes, perfilado, etc. Filtros no lineales: se usan funciones no lineales ? Máximo, mínimo, operaciones de morfología, etc. Es posible combinarlas con operaciones de procesamiento global. La idea de “localidad” se puede extender a vídeo y a sonido, considerando la dimensión temporal.
Filtros en OpenCV. Filtros lineales predefinidos. Filtros lineales arbitrarios. Filtros de máximo, mínimo y mediana. Operaciones de morfología matemática. Ejemplos.
Filtros en OpenCV. Operaciones de procesamiento local: De modo práctico, podemos clasificar las operaciones de filtrado existentes en los siguientes grupos: Filtros lineales predefinidos de suavizado y detección de bordes. Filtros lineales arbitrarios, definidos por el usuario en tiempo de ejecución. Filtros de máximo, mínimo y mediana. Operaciones de morfología matemática.
Ojo con las restricciones. Algunas operaciones requieren imágenes de 1 canal o profundidad float (habrá que usar: split, merge y convertTo).
Filtros en OpenCV. Filtros lineales predefinidos: blur, GaussianBlur, Sobel, Scharr, Laplacian, Canny (este último es un filtro estándar, pero no se puede considerar como lineal). Filtros lineales arbitrarios: filter2D. Filtros de máximo, mínimo y mediana: dilate (máximo), erode (mínimo), medianBlur (mediana). Filtros de morfología matemática: erode, dilate, morphologyEx.
Filtros en OpenCV. Filtros de suavizado de una imagen: void blur (Mat src, Mat dst, Size ksize, [ Point ancla=Point(-1,-1), int tipoBorde=DEFAULT ] );
src: imagen de entrada. Puede ser de distintos tipos y número de canales. dst: imagen de salida. Debe ser del mismo tamaño y tipo que src. ksize: tamaño del suavizado (ancho por alto). ancla: punto de ancla de la convolución. El valor por defecto es en el centro de la máscara. tipoBorde: indica el modo de operar en los píxeles de los bordes (BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, etc.). Lo mejor es dejar el valor por defecto.
Filtros en OpenCV. Filtros de suavizado de una imagen: void GaussianBlur (Mat src, Mat dst, Size ksize, double sigmaX, [double sigmaY=0, int tipoBorde=DEFAULT] );
src: imagen de entrada. Puede ser de distintos tipos y número de canales. dst: imagen de salida. Debe ser del mismo tamaño y tipo que src. ksize: tamaño de la máscara suavizado (ancho por alto). Pueden ser distintas, pero deben ser positivas e impares. sigmaX, sigmaY: Indican la desviación típica de la máscara. Se puede poner 0 (para que sea según ksize). tipoBorde: indica el modo de operar en los píxeles de los bordes (BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, etc.). Lo mejor es dejar el valor por defecto.
Filtros en OpenCV. Filtros de Sobel de una imagen: void Sobel (Mat src, Mat dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int tipoBorde=DEFAULT ] );
src: imagen de origen (puede tener distintas profundidades y número de canales). dst: imagen de destino (de igual tamaño y profundidad que src). ddepth: profundidad de la imagen de salida. Puede ser -1 (igual que la de entrada) o una profundidad mayor que la entrada (CV_16S, CV_32F…). dx, dy: orden de la derivada en X y en Y. Normalmt. usaremos (1,0) o (0,1). ksize: tamaño de la máscara de convolución: -1 (filtro de Scharr), 1 (resta simple), 3, 5 ó 7. Ver también la función Scharr. scale, delta: valor que se multiplica (scale) y que se suma (delta). Ejemplo. Aplicar un efecto de bajorrelieve a una imagen img. Mat emboss; Sobel(img, emboss, -1, 1, 0, 3, 1, 128); Ejemplo. Calcular la magnitud del gradiente de la imagen img. Mat dx, dy, gradiente; Sobel(img, dx, CV_32F, 1, 0, -1); Sobel(img, dy, CV_32F, 0, 1, -1); pow(dx, 2.0, dx); pow(dy, 2.0, dy); gradiente= dx+dy; sqrt(gradiente, gradiente); Mat imgrad; gradiente.convertTo(imgrad, CV_8U);
Filtros en OpenCV. Filtros de Laplace de una imagen: void Laplacian (Mat src, Mat dst, int ddepth, [ int ksize=1, double scale=1, double delta=0, int tipoBorde=DEFAULT ] );
src: imagen de origen. dst: imagen de destino. ddepth: profundidad deseada de la imagen de salida. ksize: tamaño de la máscara de convolución, debe ser positivo e impar. scale, delta: valor que se multiplica (scale) y que se suma (delta). Calcula la laplaciana de una imagen (suma de las 2ª derivadas en X e Y). ¡¡Mucho cuidado!! La laplaciana puede tomar valores negativos: no convertir el resultado a 8U (los negativos se saturan a 0). Si se va a usar para un perfilado, el coeficiente que multiplica al resultado debe ser negativo, ya que usa máscaras “inversas” a las que hemos visto.
Ejemplo: uso de la laplaciana para calcular un perfilado de img. Mat lap, suma; Laplacian(img, lap, CV_16S); img.convertTo(img, CV_16S); suma= img – 0.4*lap; suma.convertTo(img, CV_8U);
Filtros en OpenCV. Filtro de bordes de Canny: void Canny (Mat image, Mat edges, double threshold1, double threshold2, [ int apertureSize=3, bool L2gradient=false ] );
Ojo, es un filtro de bordes más avanzado que los otros. Usa filtros de Sobel y luego un algoritmo voraz para extraer los bordes más relevantes. Requiere imágenes de 1 solo canal y 8 bits, igual que edges. threshold1, threshold2: umbrales del algoritmo. Se refieren al valor mínimo de la magnitud del gradiente para ser considerado como un borde relevante. apertureSize: tamaño de la máscara de convolución (igual que Sobel). Ejemplo. Aplicación del operador de bordes de Canny, sobre img.
Mat gris, bordes; cvtColor(img, gris, CV_BGR2GRAY); Canny(gris, bordes, 100, 60);
Filtros en OpenCV. Filtros lineales arbitrarios: son los más flexibles. Nos definimos la máscara de convolución que queramos y la aplicamos sobre las imágenes. Para los filtros que están predefinidos (suavizados, bordes, etc.) no hace falta utilizar estas funciones (que, además, serán menos eficientes). Las máscaras de convolución se definen como matrices de tipo Mat, con 1 canal y profundidad 32F. La máscara de convolución se puede inicializar al crearla de la siguiente forma: Ejemplo 1. Máscara de perfilado de la página 56. Mat kernelPerfilado= (Mat_(3, 3) << -1, -1, -1, -1, 9, -1, -1, -1, -1); Ejemplo 2. Máscara derivativa en diagonal. Mat kernelDerivada= (Mat_(3, 3) << -2, -1, 0, -1, 0, 1, 0, 1, 2);
Filtros en OpenCV. Aplicar una máscara de convolución arbitraria en OpenCV: void filter2D (Mat src, Mat dst, int ddepth, Mat kernel, [ Point ancla=Point(-1,-1), double delta=0, int borde=DEFAULT ] );
kernel es una matriz de 1 canal y 32F, indica los coeficientes de la máscara de convolución. ancla es el punto de ancla (por defecto, el centro de la máscara). delta es el valor que se suma después de aplicar la convolución.
Ejemplo. Aplicar a una imagen img el perfilado y la derivada. Mat salida1, salida2; Mat kernelPerfilado= (Mat_(3, 3) << -1, -1, -1, -1, 9, -1, -1, -1, -1); filter2D(img, salida1, CV_8U, kernelPerfilado); Mat kernelDerivada= (Mat_(3, 3) << -2, -1, 0, -1, 0, 1, 0, 1, 2); filter2D(img, salida2, CV_8U, kernelDerivada, Point(-1,-1), 128);
Filtros en OpenCV. Filtros no lineales de máximo, mínimo: no existen en OpenCV, sino que deben hacerse utilizando las operaciones morfológicas dilate (máximo) y erode (máximo). Ambas operaciones reciben como parámetro un elemento estructurante, que es una matriz de tipo Mat. Implementación de las operaciones de máximo y mínimo local:
void MinLocal (Mat entrada, Mat &salida, int ancho, int alto) { erode(entrada, salida, Mat::ones(alto, ancho, CV_8U), Point(-1,-1), 1, BORDER_REPLICATE); }
void MaxLocal (Mat entrada, Mat &salida, int ancho, int alto) { dilate(entrada, salida, Mat::ones(alto, ancho, CV_8U), Point(-1,-1), 1, BORDER_REPLICATE); }
Filtros en OpenCV. Filtro de mediana de tamaño ksize: void medianBlur (Mat src, Mat dst, int ksize); El tamaño sobre el que se aplica es siempre el mismo en horizontal y en vertical (ksize).
Filtros de morfología matemática: el manejo es parecido a las convoluciones arbitrarias. 1º: definir un elemento estructurante. 2º: aplicarlo sobre las imágenes con operaciones de erosión, dilatación, apertura o cierre. Normalmente las imágenes será de 1 canal y tipo 8U. No obstante, pueden tener otras profundidades y número de canales (se usa MAX y MIN, en lugar de OR y AND). El elemento estructurante es de tipo Mat. Si se pone la constante Mat(), entonces se usa el elemento por defecto, un rectángulo de 3×3.
Filtros en OpenCV. Aplicar erosión morfológica a una imagen: void erode (Mat src, Mat dst, Mat kernel, [ Point ancla=Point(-1,-1), int iteraciones=1, int borde=BORDER_CONSTANT, Scalar& valorBorde=morphologyDefaultBorderValue() ] ); Aplica uno o varios pasos de erosión, según el parámetro iteraciones. Si el elemento kernel es Mat() se usa un rectángulo de 3×3. La forma de tratar el borde se define en borde y valorBorde.
Aplicar dilatación morfológica a una imagen: void dilate (Mat src, Mat dst, Mat kernel, [ Point ancla=Point(-1,-1), int iteraciones=1, int borde=BORDER_CONSTANT, Scalar& valorBorde=morphologyDefaultBorderValue() ] ); Aplica uno o varios pasos de dilatación, según iteraciones. Si el elemento kernel es Mat() se usa un rectángulo de 3×3. La forma de tratar el borde se define en borde y valorBorde.
Ejemplo. Aplicar una dilatación de 5×5, con elemento en diagonal.
dilate(img, salida, Mat::eye(5,5,CV_8U));
Filtros en OpenCV. Aplicar operaciones morfológicas compuestas: void morphologyEx (Mat src, Mat dst, int op, Mat kernel,[ Point ancla=Point(-1,-1), int iterac=1, int borde=BORDER_CONSTANT, Scalar& valorBorde=morphologyDefaultBorderValue() ] );
Permite aplicar una operación morfológica compuesta por otras elementales, erosiones, dilataciones y diferencias. kernel es el elem. estructurante, iterac es el número de iteraciones. El parámetro op indica el tipo de operación: MORPH_OPEN, MORPH_CLOSE, MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT.
Ejemplo. Los dos siguientes códigos deberían dar la misma salida:
a) morphologyEx(img, res, MORPH_OPEN, Mat());
b) erode(img, img, Mat()); dilate(img, res, Mat());
Filtros en OpenCV. Ejemplo 1. Aplicar un ajuste (o estiramiento) local del histograma a la imagen img, con ancho dado. El resultado se almacena en res.
Mat mini, maxi, res; int tam= 2*ancho+1; // tamaño de vecindad local MinLocal(img, mini, tam, tam); MaxLocal(img, maxi, tam, tam); res= img-mini; maxi= maxi-mini; divide(res, maxi, res, 255.0);
Filtros en OpenCV. Ejemplo 2. Efecto de transición entre dos imágenes (que deben ser de igual tamaño), a través de un suavizado intermedio:
QString nombre1= QFileDialog::getOpenFileName(); QString nombre2= QFileDialog::getOpenFileName(); Mat img1= imread(nombre1.toStdString()); Mat img2= imread(nombre2.toStdString()); if (img1.empty() || img2.empty()) return; namedWindow("Transicion", 0); Mat int1, int2, res; for (int i= 0; i<100; i++) { blur(img1, int1, Size(i*4+1, 1)); blur(img2, int2, Size((99-i)*4+1, 1)); addWeighted(int1, 1-i/100.0, int2, i/100.0, 0, res); imshow("Transicion", res); waitKey(1); }
Página anterior | Volver al principio del trabajo | Página siguiente |