2010-11-20 20 views
5

Soy un CS major en la universidad trabajando en un proyecto de programación para mi curso Calc III que involucra la descomposición de valores singulares. La idea es básicamente convertir una imagen de m x n dimensiones en una matriz m x n en la que cada elemento es una tupla que representa los canales de color (r, g, b) del píxel en el punto (m, n). Estoy usando Python porque es el único idioma que he sido (bien) enseñado hasta ahora.Python - NumPy - tuplas como elementos de una matriz

Por lo que puedo decir, a Python generalmente no le gustan las tuplas como elementos de una matriz. Hice un poco de investigación de mi propia y encontré una solución, es decir, antes de la asignación de la matriz de la siguiente manera:

def image_to_array(): #converts an image to an array 
    aPic = loadPicture("zorak_color.gif") 
    ph = getHeight(aPic) 
    pw = getWidth(aPic) 
    anArray = zeros((ph,pw), dtype='O') 
    for h in range(ph): 
     for w in range(pw):    
      p = getPixel(aPic, w, h) 
      anArray[h][w] = (getRGB(p)) 
    return anArray 

Esto funcionó correctamente durante la primera parte de la tarea, que era simplemente para convertir una imagen a una matriz (sin álgebra lineal involucrada).

La parte con SVD, sin embargo, es donde se vuelve más complicado. Cuando llamo a la función integrada de numpy SVD, utilizando la matriz he construido a partir de mi imagen (donde cada elemento es una tupla), me sale el siguiente error:

Traceback (most recent call last): 
    File "<pyshell#5>", line 1, in -toplevel- 
    svd(x) 
    File "C:\Python24\Lib\site-packages\numpy\linalg\linalg.py", line 724, in svd 
    a = _fastCopyAndTranspose(t, a) 
    File "C:\Python24\Lib\site-packages\numpy\linalg\linalg.py", line 107, in _fastCopyAndTranspose 
    cast_arrays = cast_arrays + (_fastCT(a.astype(type)),) 
ValueError: setting an array element with a sequence. 

Este es el mismo error que estaba inicialmente , antes de hacer algunas investigaciones y descubrí que podía asignar previamente mis matrices para permitir que las tuplas se convirtieran en elementos.

El problema ahora es que solo estoy en mi primer semestre de programación (a nivel universitario), y estas funciones numéricas escritas por y para programadores profesionales son un poco demasiado negras para mí (aunque estoy seguro de que están mucho más claros para aquellos con experiencia). Así que editar estas funciones para permitir tuplas es un poco más complicado que cuando lo hice en mi propia función. ¿A dónde debo ir desde aquí? Supongo que debería copiar las funciones numPy relevantes en mi propio programa, y ​​modificarlas en consecuencia?

Gracias de antemano.

+3

La SVD solo funciona con matrices. ¿Planeas hacer una SVD para cada uno de los canales RGB? En otras palabras, incluso si se forma una matriz m x n x 3, no se puede pasar simplemente a la función SVD porque las SVD se definen para matrices que no tienen tensores de tamaño arbitrario. –

Respuesta

2

Creo que quiere un ph por pw por 3 numpy array.

anArray = zeros((ph,pw,3)) 
for h in range(ph): 
    for w in range(pw):    
     p = getPixel(aPic, w, h) 
     anArray[h][w] = getRGB(p) 

sólo tiene que asegurarse de getRGB devuelve una lista de 3 elementos en lugar de una tupla.

+0

Claro, eso fue bastante fácil, acabo de poner list() alrededor de getRGB. Pero después de seguir sus cambios, comencé a recibir un nuevo error: Archivo "C: \ Python24 \ Lib \ site-packages \ numpy \ linalg \ linalg.py", línea 720, en svd _assertRank2 (a) Archivo " C: \ Python24 \ Lib \ site-packages \ numpy \ linalg \ linalg.py ", línea 116, en _assertRank2 raise LinAlgError, '% d-dimensional array given. La matriz debe ser \ LinAlgError: conjunto tridimensional dado. La matriz debe ser bidimensional , así que todavía necesito una forma de tener una matriz "2-d" de tuplas que funcione con numPy ... – Thomas

+0

Pensándolo bien, esto realmente no tiene sentido. No creo que puedas encontrar el SVD de una matriz 2D cuyas entradas son tuplas, y si existe algo así como SVD de una matriz 3D, definitivamente está más allá del alcance de mi clase y este proyecto. Necesito descubrir cómo hacer esto para cada canal de color y luego combinar esas tres matrices de alguna manera. Gracias por la respuesta. – Thomas

+0

* Hay * una versión 3D de SVD [DeLathauwer 2000] [Mesgarani 2004], pero sospecho que no es lo que quieres. Para una tarea como el reconocimiento facial, las personas a menudo vectorizan * imágenes completas *, luego concatenan esos vectores en una matriz grande 'X' de tamaño (h * w) -by- (imágenes num), * luego * realizan PCA en' X 'que es equivalente a la SVD de' XX^T'. Respondí una pregunta relacionada aquí: http://stackoverflow.com/questions/4171866/creating-a-dataset-from-an-image-with-python-for-face-recognition/4176400#4176400 –

7

En lugar de establecer el tipo de elemento de matriz en 'O' (objeto) debe establecerlo en una tupla. Ver the SciPy manual para algunos ejemplos.

En su caso, más fácil es usar algo como

a = zeros((ph,pw), dtype=(float,3)) 

Suponiendo que los valores de RGB son tuplas de 3 números de punto flotante.

Esto es similar a la creación de una matriz 3d (como Steve sugirió) y, de hecho, se accede a los elementos de tupla como a[n,m][k] o z[n,m,k] donde k es el elemento en la tupla.

Por supuesto, el SVD se define para las matrices 2d y no para las matrices en 3D, por lo que no puede usar linalg.svd (a). Debes decidir la SVD de qué matriz (de las tres posibles: R G y B) que necesitas.

Si, por ejemplo, desea que el SVD de la matriz "R" (suponiendo que es el primer elemento de la tupla) usar algo como:

linalg.svd(a[:,:,1]) 
Cuestiones relacionadas