2010-11-20 119 views
5

我是大学的CS专业,主要从事计算三级计划编程项目,涉及奇异值分解。该想法基本上是将m×n维的图像转换为m×n矩阵,其中每个元素是代表点(m,n)处像素的颜色通道(r,g,b)的元组。我使用的是Python,因为它是迄今为止唯一真正教授的语言。Python - NumPy - 作为数组元素的元组

从我可以告诉,Python通常不喜欢元组作为数组的元素。我做了我自己的一个小小的研究,发现了一个解决方案,即预分配数组如下:

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 

这工作正常进行分配的第一部分,这是简单地将图像转换为一矩阵(不涉及线性代数)。

尽管如此,SVD的部分却变得更加棘手。当我调用内置numpy的SVD功能,使用我从我的形象建造的阵列(其中每个元素是一个元组),我收到以下错误:

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. 

这是同样的错误我正在开始,之前我做了一些研究,发现我可以预分配我的数组,允许元组作为元素。

现在的问题是,我只在我的第一学期(大学水平)编程,这些专业程序员编写的numPy函数对我来说有点过于黑暗(尽管我确信他们对于那些有经验的人来说更加清楚)。所以编辑这些函数以允许元组比我在自己的函数上做的更复杂一些。我需要从哪里出发?我假设我应该将相关的numPy函数复制到我自己的程序中,并相应地修改它们?

在此先感谢。

+3

的SVD仅适用于矩阵。你打算为每个RGB通道做一个SVD吗?换句话说,即使你形成一个m×n×3的数组,你也不能将它传递给SVD函数,因为SVD是为矩阵而不是任意大小的张量定义的。 – 2010-11-20 07:07:39

回答

2

我想你想要一个phpw通过3 numpy数组。

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) 

你只需要确保getRGB返回一个3元素列表,而不是一个元组。

+0

当然,这很容易,我只是把list()放在getRGB周围。但在执行完更改后,我开始出现一个新错误: svd中的文件“C:\ Python24 \ Lib \ site-packages \ numpy \ linalg \ linalg.py”行720,其中包含文件“ C:\ Python24 \ Lib \ site-packages \ numpy \ linalg \ linalg.py“,第116行,在_assertRank2 引发LinAlgError'%d维数组给定。数组必须是\ LinAlgError:给出的三维数组。数组必须是二维的 所以我仍然需要一种方法来创建一个可以与numPy一起工作的“2-d”元组矩阵... – Thomas 2010-11-20 07:29:00

+0

第二个想法是,这并没有什么意义。我不认为你可以找到一个二维矩阵的SVD,这个矩阵的元素是元组,如果存在3D矩阵的SVD这样的事情,那肯定超出了我的课程和这个项目的范围。我需要弄清楚如何为每个颜色通道执行此操作,然后以某种方式组合这三个矩阵。感谢您的答复。 – Thomas 2010-11-20 07:38:54

+0

*是* SVD [DeLathauwer 2000] [Mesgarani 2004]的3D版本,但我怀疑它不是你想要的。对于诸如人脸识别之类的任务,人们通常矢量化*整个图像*,然后将这些矢量连接成大小为(h * w)的大矩阵“X”(数字图像),然后*在X上执行PCA '这相当于'XX^T'的SVD。我在这里回答了一个相关问题:http://stackoverflow.com/questions/4171866/creating-a-dataset-from-an-image-with-python-for-face-recognition/4176400#4176400 – 2010-11-20 13:49:32

7

不应将数组元素类型设置为'O'(对象),而应将其设置为元组。有关示例,请参阅the SciPy manual

在你的情况,最简单的就是使用类似

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

假设你的RGB值是3个浮点数的元组。

这与创建3D数组类似(如Steve所建议的),实际上,元组元素的访问形式为a[n,m][k]z[n,m,k],其中k是元组中的元素。

当然,SVD是为2d矩阵定义的,而不是3d数组,因此您不能使用linalg.svd(a)。你必须决定你需要什么矩阵(三种可能的矩阵:R G和B)的SVD。

如果,例如,你想要的“R”矩阵的SVD(假设是元组的第一个元素),使用这样的:

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