【问题标题】:Python Image Library - Convert pixels to 2D listPython 图像库 - 将像素转换为 2D 列表
【发布时间】:2012-10-09 19:33:19
【问题描述】:

我需要对从图像中读取的二维数组值执行一些操作,然后使用生成的二维数组创建图像。我正在使用 python 列表来表示二维数组。

发生了一些非常奇怪的事情;二维数组(列表列表)中的值在我标记的两个打印调用之间的某个时间点似乎变为“0”。也就是说,它们似乎可以从图像中正确读取......但后来不知何故被设置为零。

代码:

image = Image.open("test.png").convert("L")

data = [ [255] * image.size[1] ] * image.size[0]
pix = image.load()
for x in range(0, image.size[0]):
    for y in range(0, image.size[1]):
        data[x][y] = pix[x, y]
        #data[x][y] = 77
        print "1. data[x][y] = " + str(data[x][y]) + " .vs. " + str(pix[x, y]) # Prints correct values

for x in range(0, image.size[0]):
    for y in range(0, image.size[1]):
        print "2. data[x][y] = " + str(data[x][y]) + " .vs. " + str(pix[x, y]) # Always prints "0 .vs. [correct value]"

但是,如果我注释掉该行

data[x][y] = pix[x, y]

然后取消注释:

data[x][y] = 77

那么两个print语句显示data中的所有元素都是77

发生了什么事?我不是 python 专家,但我想不出任何合理的理由为什么列表值会这样改变。

我已经尝试了以下行,以防像素访问器做一些奇怪的事情:

data[x][y] = 0 + int(pix[x, y])

但仍然得到相同的结果。我也尝试过使用 RGB 图像而不是灰度图像。

我应该明确表示,我绝对不会对这两个打印调用之间的数据做任何事情。上面的代码正是我将原始程序简化为的代码(在发现我所有的“结果”图像文件都是黑色之后)。

【问题讨论】:

  • 为什么不能简单的对image.load()返回的二维结构进行操作?
  • 数据稍后会被算法修改。它还将包含复数。

标签: python list python-imaging-library


【解决方案1】:

你的问题在于这一行:

data = [ [255] * image.size[1] ] * image.size[0]

这将创建一个长度为image.size[1] 的列表,其中填充了值255。然后创建image.size[0]同一个列表 的引用,并将所有这些引用打包到另一个列表中。因此,当您更改a[1][1] 时,您也会更改a[0][1]a[2][1] 等,因为a[0]a[1]a[2]... 是对同一个列表的引用 .

这是一个简单的例子:

a = [[255]*10]*10
a[1][1] = 77
print (a)

最简单的解决方法是:

a = [[255]*10 for _ in range(10)]

因为这会创建 10 个新列表,而不是对同一列表的引用列表。

【讨论】:

  • 在python中,变量_并不特别——只是习惯性地用它来表示“语法上,我需要一个变量,但我永远不会真正使用它"
  • 我想补充一点:虽然这个答案是正确的,但提前创建一个完整的列表列表并不是一个好主意。如果事先知道数据大小,则 numpy.array 可能更可取。否则,按照@halex 在下面指出的那样动态附加到列表中。
  • @Dhara -- 如果您要立即填充数据结构,我认为提前创建数据结构没有任何问题。 (你有什么理由说这不是一个好主意?)如果项目的其他部分需要 numpy,那么 numpy 数组肯定会更好,但如果你计划其他部分,有时最好避免外部依赖使用您的代码(但绝对值得考虑)。
  • 因为您对列表进行了两次迭代——一次创建它,然后再次添加每个数据项。我想简单地附加到一个空列表更有效(而且绝对是 IMO 更优雅)。如果你想避免外部依赖,我知道内置的数组模块也可以很方便。
【解决方案2】:

您最好将data 更改为data = [] 并附加每一行。

data = []
pix = image.load()
for y in xrange(image.size[1]):
    data.append([pix[x, y] for x in xrange(image.size[0])])

【讨论】:

  • 图像数组是否支持像 numpy 数组一样的切片?如果是这样,你可以这样做data.append(list(pix[:,y]))
猜你喜欢
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 2013-03-03
  • 1970-01-01
相关资源
最近更新 更多