Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - NumPy - tuples as elements of an array

I'm a CS major in university working on a programming project for my Calc III course involving singular-value decomposition. The idea is basically to convert an image of m x n dimensions into an m x n matrix wherein each element is a tuple representing the color channels (r, g, b) of the pixel at point (m, n). I'm using Python because it's the only language I've really been (well-)taught so far.

From what I can tell, Python generally doesn't like tuples as elements of an array. I did a little research of my own and found a workaround, namely, pre-allocating the array as follows:

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

This worked correctly for the first part of the assignment, which was simply to convert an image to a matrix (no linear algebra involved).

The part with SVD, though, is where it gets trickier. When I call the built-in numPy svd function, using the array I built from my image (where each element is a tuple), I get the following 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.

This is the same error I was getting initially, before I did some research and found that I could pre-allocate my arrays to allow tuples as elements.

The issue now is that I am only in my first semester of (college-level) programming, and these numPy functions written by and for professional programmers are a little too black-box for me (though I'm sure they're much clearer to those with experience). So editing these functions to allow for tuples is a bit more complicated than when I did it on my own function. Where do I need to go from here? I assume I should copy the relevant numPy functions into my own program, and modify them accordingly?

Thanks in advance.

like image 358
Thomas Avatar asked Nov 20 '10 04:11

Thomas


People also ask

Can you have a NumPy array of tuples?

The asarray() method in NumPy can be used to create an array from data that already exists in the form of lists or tuples.

Can you store tuples in an array?

if you mean array , no python arrays don't support tuples. Save this answer.

How do you convert a 1D array of tuples to a 2d NumPy array?

How to convert a 1d array of tuples to a 2d numpy array? Yes it is possible to convert a 1 dimensional numpy array to a 2 dimensional numpy array, by using "np. reshape()" this function we can achiev this.


2 Answers

Instead of setting the array element type to 'O' (object) you should set it to a tuple. See the SciPy manual for some examples.

In your case, easiest is to use something like

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

Assuming your RGB values are tuples of 3 floating point numbers.

This is similar to creating a 3d array (as Steve suggested) and, in fact, the tuple elements are accessed as a[n,m][k] or z[n,m,k] where k is the element in the tuple.

Of course, the SVD is defined for 2d matrices and not 3d arrays so you cannot use linalg.svd(a). You have to decide SVD of what matrix (of the three possible ones: R G and B) you need.

If, for example, you want the SVD of the "R" matrix (assuming that is the first element of the tuple) use something like:

linalg.svd(a[:,:,1])
like image 139
nimrodm Avatar answered Sep 28 '22 11:09

nimrodm


I think you want a ph by pw by 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)

You just need to make sure getRGB returns a 3-element list instead of a tuple.

like image 27
Steve Tjoa Avatar answered Sep 28 '22 10:09

Steve Tjoa