¿Cómo puedo gaussiano una imagen sin necesidad de utilizar cualquiera de las funciones gaussianas incorporado?

StackOverflow https://stackoverflow.com/questions/1696113

Pregunta

Quiero desdibujar mi imagen utilizando la fórmula desenfoque gaussiano nativa. He leído artículo de Wikipedia , pero no estoy seguro de cómo implementar esto.

¿Cómo se utiliza la fórmula para decidir pesos?

No quiero utilizar cualquier construido en funciones de MATLAB como lo que tiene

¿Fue útil?

Solución

Escribir un desenfoque gaussiano ingenua en realidad es bastante fácil. Se lleva a cabo exactamente de la misma manera que cualquier otro filtro de convolución. La única diferencia entre una caja y un filtro de Gauss es la matriz que utilice.

Imagine que tiene una imagen definida de la siguiente manera:

 0  1  2  3  4  5  6  7  8  9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99

una matriz de filtro 3x3 caja se define como sigue:

0.111 0.111 0.111
0.111 0.111 0.111
0.111 0.111 0.111

Para aplicar el desenfoque gaussiano que haría lo siguiente:

Para pixel 11 que se necesita para cargar pixeles 0, 1, 2, 10, 11, 12, 20, 21, 22.

A continuación, se multiplican píxel 0 por la parte superior izquierda del filtro de desenfoque 3x3. Pixel 1 por la mitad superior, pixel 2, pixel 3 por arriba a la derecha, pixel 10 por medio izquierda y así sucesivamente.

A continuación, agregue por completo y escribir el resultado de píxeles 11. Como se puede ver Pixel 11 es ahora la media de sí mismo y los píxeles circundantes.

casos Edge hacen ser un poco más complejo. ¿Qué valores se utiliza para los valores de la orilla de la textura? Una forma puede ser redonda para envolver al otro lado. Esto se ve bien para una imagen que es de baldosas más tarde. Otra manera es empujar el píxel en los lugares circundantes.

Así que para la parte superior izquierda es posible colocar las muestras de la siguiente manera:

 0  0  1
 0  0  1
10 10 11

Espero que puedan ver cómo esto se puede extender fácilmente a grandes núcleos de filtro (es decir, 5x5 o 9x9, etc.).

La diferencia entre un filtro de Gauss y un filtro de caja es los números que van en la matriz. Un filtro gaussiano utiliza una distribución gaussiana a través de una fila y columna.

por ejemplo para un filtro definido arbitrariamente como (es decir, esto no es una gausiana, pero probablemente no muy lejos)

0.1 0.8 0.1

la primera columna sería el mismo pero multiplicado en el primer elemento de la fila anterior.

0.01 0.8 0.1
0.08 
0.01 

La segunda columna sería el mismo pero los valores sería multiplicado por el 0,8 en la fila de arriba (y así sucesivamente).

0.01 0.08 0.01
0.08 0.64 0.08
0.01 0.08 0.01

El resultado de la adición de todos los anteriores juntos debe ser igual a 1. La diferencia entre el filtro anterior y el filtro de la caja original sería que el píxel final escrito tendría una ponderación mucho más pesado hacia el píxel central (es decir, el que es en esa posición ya). La falta de definición se debe a que los píxeles circundantes no se confunden entre ese píxel, aunque no tanto. El uso de este tipo de filtro se obtiene una imagen borrosa pero que no destruye la mayor cantidad de alta frecuencia (es decir, un cambio rápido del color de píxel a píxel) de la información.

Este tipo de filtros se puede hacer un montón de cosas interesantes. Usted puede hacer un borde detectar el uso de este tipo de filtro restando los píxeles circundantes del píxel actual. Esto dejará sólo los realmente grandes cambios en el color (altas frecuencias) detrás.

Edit:. Un núcleo de filtro 5x5 es definir exactamente como arriba

por ejemplo, si su fila es 0.1 0.2 0.4 0.2 0.1 entonces si se multiplica cada valor en su por el primer elemento para formar una columna y luego multiplicar cada por el segundo elemento para formar la segunda columna y así sucesivamente que va a terminar con un filtro de

0.01 0.02 0.04 0.02 0.01
0.02 0.04 0.08 0.04 0.02
0.04 0.08 0.16 0.08 0.04
0.02 0.04 0.08 0.04 0.02
0.01 0.02 0.04 0.02 0.01

tomando algunas posiciones arbitrarias se puede ver que la posición 0, 0 es sencilla 0.1 * 0.1. Posición 0, 2 es de 0,1 * 0,4, la posición 2, 2 es 0.4 * 0.4 y la posición 1, 2 es 0.2 * 0.4.

Espero que le da una buena explicación suficiente.

Otros consejos

Esta es la pseudo-código para el código que utilicé en C # para calcular el núcleo. No me atrevo a decir que yo trato a las condiciones finales correctamente, sin embargo:

double[] kernel = new double[radius * 2 + 1];
double twoRadiusSquaredRecip = 1.0 / (2.0 * radius * radius);
double sqrtTwoPiTimesRadiusRecip = 1.0 / (sqrt(2.0 * Math.PI) * radius);
double radiusModifier = 1.0;

int r = -radius;
for (int i = 0; i < kernel.Length; i++)
{
    double x = r * radiusModifier;
    x *= x;
    kernel[i] =
    sqrtTwoPiTimesRadiusRecip * Exp(-x * sqrtTwoPiTimesRadiusRecip);
    r++;
}

double div = Sum(kernel);
for (int i = 0; i < kernel.Length; i++)
{
    kernel[i] /= div;
}

Espero que esto puede ayudar.

Para utilizar el núcleo del filtro se discutió en un artículo de Wikipedia es necesario implementar (discreta) convolución . La idea es que usted tiene una pequeña matriz de valores (el núcleo), se mueve este núcleo de píxel a píxel de la imagen (es decir, de manera que el centro de la matriz está en el pixel), multiplicar los elementos de matriz con la imagen superpuesta elementos, sumar todos los valores en el resultado y reemplazar el valor de píxel de edad con esta suma.

desenfoque gaussiano se puede separar en dos circunvoluciones 1D (una vertical y otra horizontal) en lugar de una convolución 2D, que también acelera las cosas un poco.

No me queda claro si desea limitar este a ciertas tecnologías, pero si no SVG (ScalableVectorGraphics) tiene una implementación de desenfoque gaussiano. Creo que se aplica a todas las primitivas incluyendo píxeles. SVG tiene la ventaja de ser un estándar abierto y ampliamente aplicado.

Bueno, Gauss núcleo es un núcleo separable.
Por lo tanto, todo lo que necesita es una función que soporta separable 2D como convolución - ImageConvolutionSeparableKernel() .

Una vez que lo tienes, todo lo necesario es un envoltorio para generar 1D Gauss Kernel y enviarlo a la función de como se hace en ImageConvolutionGaussianKernel() .

El código es una aplicación C recta hacia adelante de convolución 2D imagen acelerada por SIMD (SSE) y Multi Threading (OpenMP).

Todo el proyecto está dada por - convolución imagen - GitHub <. / p>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top