Agrupación espectral, segmentación de imágenes y vectores propios

Basándome en el libro Computer Vision a Modern Approach página 425, intenté usar vectores propios para la segmentación de imágenes.

http://dl.dropbox.com/u/1570604/tmp/comp-vis-modern-segment.pdf

El autor menciona que las afinidades de píxeles de imagen se pueden capturar en la matriz A. Entonces podemos maximizar w w TA t producto donde w’s son pesos. Después de algún álgebra, se obtiene Aw = \ lambda w, encontrar w es como encontrar vectores propios. Luego, encontrar el mejor grupo es encontrar el valor propio con el vector propio más grande, los valores dentro de ese vector propio son valores de pertenencia al grupo. Yo escribi este codigo

import matplotlib.pyplot as plt import numpy as np Img = plt.imread("twoObj.jpg") (n,dummy) = Img.shape Img2 = Img.flatten() (nn,) = Img2.shape A = np.zeros((nn,nn)) for i in range(nn): for j in range(nn): N=Img2[i]-Img2[j]; A[i,j]=np.exp(-(N**2)) V,D = np.linalg.eig(A) V = np.real(V) a = np.real(D[1]) threshold = 1e-10 # filter a = np.reshape(a, (n,n)) Img[a<threshold] = 255 plt.imshow(Img) plt.show() 

La imagen

introduzca la descripción de la imagen aquí

El mejor resultado que pude obtener de esto es abajo. Tengo la sensación de que los resultados pueden ser mejores.

Los valores propios se ordenan de mayor a menor en Numpy, probé el primero, que no funcionó, luego probé el segundo para obtener los resultados que se muestran a continuación. El valor de umbral fue elegido por prueba y error. ¿Alguna idea sobre cómo este algoritmo puede ser mejorado?

introduzca la descripción de la imagen aquí

Acabo de probar el algoritmo en Mathematica, funciona bien en tu imagen, por lo que debe haber un error sutil en tu código.

Esta parte:

 V,D = np.linalg.eig(A) V = np.real(V) res = n_max(V,1) # take largest idx = res[0][1][0] a = np.real(D[idx]) # look at corresp eigv 

Parece extraño: todos los paquetes de álgebra lineal que conozco devuelven los valores propios / vectores propios ordenados, por lo que simplemente tomarías el primer vector propio de la lista. Ese es el que corresponde al valor propio más alto. Intente trazar la lista de valores propios para confirmar eso.

Además, ¿de dónde sacaste el umbral fijo? ¿Has intentado normalizar la imagen para mostrarla?

Para lo que vale, los resultados que obtengo para los primeros 3 vectores propios son:

Eigenvector1Eigenvector2Eigenvector3

Este es el código de Mathematica que uso:

 pixels = Flatten[image]; weights = Table[N[Exp[-(pixels[[i]] - pixels[[j]])^2]], {i, 1, 900}, {j, 1, 900}]; eigenVectors = Eigenvectors[weights]; ImageAdjust[Image[Partition[eigenVectors[[1]], 30]]]