2010-08-04 15 views
5

Ésta es la siguiente parte de la continuación:comprobar los elementos de la no-ceros que rodea

2) pregunta adicional:

Después de conseguir el promedio de los vecinos que no son cero, también quiero probar si los elementos vecinos son iguales, menores o mayores que el promedio de los no gemelos. Si es mayor o igual, entonces '1' o bien '0'.

Nota: si los vecinos están en el radio de los dos o más centros, tome el promedio del centro más pequeño para probar.

0 12  9  
    4 **9** 15  
    11 19  0 

El '9' en el medio se encuentra dentro del radio de 12, 15, y 19 centros, a fin de tomar la media mínima de dichos min [9.000, 9.000, 8.000] = 8,000

Por ejemplo , cuando el radio = 1 m o 1 elemento de distancia.

nueva_matriz_x =

 0   0   0   0   0 
    0   0  **9.0000** 9.0000  0 
    0  4.0000  9.0000 **9.0000** 0 
    0 **8.3333** **8.0000**  0   0 
    0  2.0000  4.0000  8.0000  0 
    0  4.0000  5.0000  8.0000  0 
    0   0   0   0   0 

Test_x =

 0   0   0   0   0 
    0   0  **9.0000**  1   0 
    0   0   1  **9.0000** 0 
    0 **8.3333** **8.0000**  0   0 
    0   0   0   0   0 
    0   0   0   0   0 
    0   0   0   0   0 

============================ =============================================== ===

1) Di si tengo una matriz, que se muestra como abajo,

X =

0  0  0  0  0 
0  0 12  9  0 
0  4  9 15  0 
0 11 19  0  0 
0  2  4  8  0 
0  4  5  8  0 
0  0  0  0  0 

y quiero encontrar la media de los elementos no nulos de los alrededores que es mayor de 10. El resto de los elementos siguen siendo los mismos elementos decir < 10.

así que quiero que mi solución a un aspecto similar,

nueva_matriz_x =

 0   0   0   0   0 
    0   0 9.0000 9.0000   0 
    0 4.0000 9.0000 9.0000   0 
    0 8.3333 8.0000   0   0 
    0 2.0000 4.0000 8.0000   0 
    0 4.0000 5.0000 8.0000   0 
    0   0   0   0   0 
No

: que soy NO mirando sólo los vecinos del elemento greather eso es que som e valor (es decir 10 en este caso).

Digamos que cualquier elemento que sea mayor que 10 es el 'centro' y queremos encontrar el promedio de los que no son ceros con el radio de, digamos, 1 m. donde 1 metro = 1 elemento lejos del centro.

Nota: Puede que no siempre esté a 1 metro de distancia en el radio, es decir, puede ser 2 o más. En este caso, no será superior, inferior, izquierda y derecha del centro.

**** También tenga en cuenta el límite de la matriz. Por ejemplo, cuando radio = 2 o más, algunos de la media de los vecinos no nulos son fuera del lado de la frontera. **

Por ejemplo,

Para radio = 1 m = 1 elemento de distancia, nueva_matriz_x = Media de [(i + 1, j), (i-1, j), (i, j + 1) y (i, j-1)] - arriba, abajo, derecha e izquierda del centro.

Para radio = 2 m = 2 elementos de distancia, new_x = promedio de [(i + 1, j), (i + 2, j), (i-1, j), (i-2, j), (i, j + 1), (i, j + 2), (i, j-1), (i, j-2), (i + 1, j + 1), (i + 1, j -1), (i-1, j-1) y (i-1, j + 1)].

============================================== ====================

He intentado algunas cosas antes, sin embargo, no estoy familiarizado con las funciones.

Así que por favor ayúdenme a resolver el problema.

Gracias de antemano.

Respuesta

3

Este es el algoritmo que creo que está describiendo en su pregunta. Para cada píxel:

  • Si el valor del píxel es inferior a 10, no haga nada.
  • Si el valor de píxel es mayor o igual que 10, reemplace el valor de píxel por el promedio de los vecinos más cercanos conectados a cero que no sean cero.

Si esto es correcto (ya que parece ser de las matrices de muestras que diste), entonces se podría utilizar la función de NLFILTER del Image Processing Toolbox (si tiene acceso a ella) para realizar esta operación:

fcn = @(x) [x(5) sum(x(2:2:8))/max(sum(x(2:2:8) > 0),1)]*[x(5) < 10; x(5) >= 10]; 
new_x = nlfilter(X,[3 3],fcn); 


EDIT: Si usted no tiene acceso a la Image Processing Toolbox, también se puede hacer esto utilizando la incorporada en CONV2 función, así:

kernel = [0 1 0; ...      %# Convolution kernel 
      1 0 1; ... 
      0 1 0]; 
sumX = conv2(X,kernel,'same');   %# Compute the sum of neighbors 
              %# for each pixel 
nX = conv2(double(X > 0),kernel,'same'); %# Compute the number of non-zero 
              %# neighbors for each pixel 
index = (X >= 10);      %# Find logical index of pixels >= 10 
new_x = X;        %# Initialize new_x 
new_x(index) = sumX(index)./max(nX(index),1); %# Replace the pixels in index 
               %# with the average of their 
               %# non-zero neighbors 

Lo anterior maneja su radio = 1 caso. Para hacer frente a su radio = 2 caso, sólo hay que cambiar el kernel de convolución a la siguiente y vuelva a ejecutar el código anterior:

kernel = [0 0 1 0 0; ... 
      0 1 1 1 0; ... 
      1 1 0 1 1; ... 
      0 1 1 1 0; ... 
      0 0 1 0 0]; 
+0

¿Esto también funciona cuando el radio = 2 m? Para radio = 2 m = 2 elementos de distancia, new_x = promedio de [(i + 1, j), (i + 2, j), (i-1, j), (i-2, j), (i, j + 1), (i, j + 2), (i, j-1), (i, j-2), (i + 1, j + 1), (i + 1, j-1) , (i-1, j-1) y (i-1, j + 1)]. Gracias de nuevo. – Nadhris

+0

@ user327950: Sí, puede funcionar si realiza algunos cambios. Tendría que reemplazar '[3 3]' con '[5 5]', 'x (5)' con 'x (13)', y 'x (2: 2: 8)' con 'x ([3 7: 9 11 12 14 15 17:19 23]) '. – gnovice

+0

¡Ohhhh eso es genial! El problema ahora es que no tengo acceso a Image Processing Toolbox. Gracias por tu ayuda de todos modos. Realmente lo aprecio – Nadhris

1

Se podría hacer algo como esto: (probado en Octave, debería funcionar en Matlab)

octave-3.2.3:17> toohigh = (x>=10) 
toohigh = 

    0 0 0 0 0 
    0 0 1 0 0 
    0 0 0 1 0 
    0 1 1 0 0 
    0 0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 0 

octave-3.2.3:18> nbr_avg = filter2(ones(3,3)/9,x) 
nbr_avg = 

    0.00000 1.33333 2.33333 2.33333 1.00000 
    0.44444 2.77778 5.44444 5.00000 2.66667 
    1.66667 6.11111 8.77778 7.11111 2.66667 
    1.88889 5.44444 8.00000 6.11111 2.55556 
    1.88889 5.00000 6.77778 4.88889 1.77778 
    0.66667 1.66667 3.44444 2.77778 1.77778 
    0.44444 1.00000 1.88889 1.44444 0.88889 

octave-3.2.3:19> y=x; y(toohigh) = nbr_avg(toohigh) 

y = 

    0.00000 0.00000 0.00000 0.00000 0.00000 
    0.00000 0.00000 5.44444 9.00000 0.00000 
    0.00000 4.00000 9.00000 7.11111 0.00000 
    0.00000 5.44444 8.00000 0.00000 0.00000 
    0.00000 2.00000 4.00000 8.00000 0.00000 
    0.00000 4.00000 5.00000 8.00000 0.00000 
    0.00000 0.00000 0.00000 0.00000 0.00000 

La función filter2 le permite filtrar los vecinos (no sé qué función desea ...), y si utiliza una matriz de índice booleana (toohigh en este caso) para seleccionar aquellos miembros de la matriz original que son demasiado altos, puede reemplazarlos por los que desee.

Más específicamente, filter2 le permite convolucionar con una matriz arbitraria. La matriz de todos hace un filtro espacial de paso bajo.


Nota: mi matemática no coincide con la suya. No estoy muy seguro de por qué quiere promediar solo los vecinos distintos de cero (que da mayor peso a los vecinos distintos de cero cuando hay ceros), pero si desea hacer eso, puede hacer filter2(ones(3,3),x) ./ M donde M = filter2(ones(3,3),(x ~= 0)) es el recuento de vecinos distintos de cero.

+0

Gracias por la idea Jason. Sin embargo, no es exactamente lo que quiero hacer. Estoy buscando NO solo los vecinos del elemento que sean más grandes que algún valor (es decir, 10 en este caso). Digamos que cualquier elemento que sea mayor que 10 es el 'centro'. Y queremos encontrar el avearge de los no ceros con el radio de, digamos, 1 m. Donde 1 metro = 1 elemento lejos del centro. Como mencionaste, filter2 solo te permite filtrar los neigbours. ¿Qué pasa si quiero estar más lejos que solo los vecindarios, es decir, 2 o más elementos alejados del centro? Gracias de nuevo. – Nadhris

+0

simplemente use una matriz de convolución más grande (por ejemplo, 3x3) –

+0

p.s. puede usar cualquier patrón que desee: la matriz de convolución [0 0 1 0 0; 0 0 1 0 0; 1 1 0 1 1; 0 0 1 0 0; 0 0 1 0 0] tiene 1 en forma de cruz e incluye solo a los 2 vecinos más cercanos directamente al norte/sur/este/oeste. –

1

EDIT: Aquí hay una solución que no requiere Image Processing Toolbox. Sin embargo, usa conv2nan.m que es parte del NaN toolbox gratuito.

Este enfoque se basa en realizar dos operaciones diferentes de filtrado/convolución: una que obtiene la suma de surrounders para cada elemento, y otra que obtiene el conteo de surrounders distintos de cero. Entonces, está listo para combinarlos para obtener solo el promedio de surrounders que no sean cero. De esta manera:

% set up starting point matrix with some zeros 
X = magic(4); 
X(X < 5) = 0; 

X(X == 0) = NaN; % convert zeros to NaNs to work with conv2nan 
countmat = double(X > 0); 

cmat = [0 1 0; 
     1 0 1; 
     0 1 0]; % consider surrounding elements only 

[m1,c] = conv2nan(X,cmat); % sum of surrounding elements 
[m2,c] = conv2nan(countmat,cmat); % number of surrounding elements > 0 

x_new = m1./m2; % compute average we want 

x_new = x_new(2:end-1,2:end-1); % trim edges created by conv2 
x_new(~countmat) = 0; % restore zero elements 
x_new(X < 10) = X(X < 10) % restore < 10 elements 

Esto lo hace un poco de trabajo extra en las circunvoluciones que se llevan a cabo para todos los elementos y no sólo aquellas que son> = 10. Pero es más general que el enfoque de bucle manual.

+0

Entonces, por ejemplo, cuando había 15 en [x], [new_x] = 9. i.e. (9 + 9)/2 = 9. primero 9 es desde la parte superior de los 15 y el segundo 9 es desde la izquierda. Ignora los ceros en la parte inferior y en el lado derecho del 15. Espero que esto te ayude a comprender mejor mi problema. – Nadhris

+0

¿Puede explicar = = [m1, c] = conv2nan (a, cmat). Tengo un error que dice 'función no definida o variable' a '. He descargado la caja de herramientas de NaN. Lo siento, nunca he usado esta función antes. Gracias de nuevo. – Nadhris

+0

lo siento, error ortográfico, debe ser X, reparado! –

4

EDITAR: Nota esto requiere funciones de la Imagen Processing Toolbox, a saber: COLFILT y STREL

r = 1;      %# radius 
t = 10;      %# threshold value 
mid = round((2*r+1)^2/2); %# mid point 
nhood = getnhood(strel('diamond', r)); 
nhood(mid) = false; 
fcn = @(M)sum(M(nhood(:),:),1)./(sum(M(nhood(:),:)~=0)+all(M(nhood(:),:)==0)).*(M(mid,:)>=t)+M(mid,:).*(M(mid,:)<t); 
new_x = colfilt(x, 2*[r r]+1, 'sliding',fcn) 

Para r = 1:

new_x = 
      0   0   0   0   0 
      0   0   9   9   0 
      0   4   9   9   0 
      0  8.3333   8   0   0 
      0   2   4   8   0 
      0   4   5   8   0 
      0   0   0   0   0 

Para r = 2:

new_x = 
      0   0   0   0   0 
      0   0   11.2   9   0 
      0   4   9  10.167   0 
      0   7  7.7778   0   0 
      0   2   4   8   0 
      0   4   5   8   0 
      0   0   0   0   0 

De hecho, debería funcionar para cualquier Aviso radius >= 1

cómo el elemento de forma de diamante estructuración representa el vecindario:

nhood = 
    0  1  0 
    1  0  1 
    0  1  0 

nhood = 
    0  0  1  0  0 
    0  1  1  1  0 
    1  1  0  1  1 
    0  1  1  1  0 
    0  0  1  0  0 

and so on.. 

Explicación:

Nosotros use la función COLFILT que atraviesa la matriz usando una vecindad deslizante de NxN, y coloca cada bloque como una columna en una matriz temporal.

Procesamos cada columna de esta matriz temp (bloques) utilizando la función de fcn, y el resultado serán colocados en la ubicación correcta una vez terminado (COLFILT utiliza IM2COL y COL2IM debajo).

Comprobamos por dos casos dependiendo del valor del centro del bloque:

  1. Si está a menos de 10, devuelve ese valor sin cambios: M(mid,:)

  2. si es> = 10 , calculamos la media de los elementos distintos de cero de su vecindad sum(M(nhood(:),:),1) ./ (sum(M(nhood(:),:)~=0) + all(M(nhood(:),:)==0)). El último término de allí es necesario para evitar la división por cero

Aviso cómo el resultado de 1 & 2 anterior se combinan utilizando R1.*(M(mid,:)<t) + R2.*(M(mid,:)>=t) para emular una si otra elección /.

+0

+1: Buena solución generalizada, y buena captura de la necesidad de 'all (M == 0)' para evitar los valores 'NaN'. Sin embargo, creo que estás usando la matriz completa 'M', cuando el OP solo está preguntando por los vecinos más cercanos en' M'. – gnovice

+1

@gnovice: bien Creo que lo tengo ahora ... Estoy usando un elemento estructurador de forma de diamante para obtener el vecindario (al igual que el OP explicado) – Amro

+0

Gracias por la ayuda de Amro. Sin embargo, no pude usar su método ya que no tengo la Caja de herramientas de procesamiento de imágenes. – Nadhris

Cuestiones relacionadas