从图像中的列表中读取像素位置的灰度值 (python)

Read gray value of pixel positions from list in image (python)

我有一个灰度值图像(8 位)和一个包含一些像素位置的列表“l”。首先我想读取列表中存储的每个位置的灰度值,然后将这个像素与黑色像素交换。

到目前为止我的代码:

img = cv2.imread(...)
list = [(11, 5), (3, 16), (0, 25), (2, 40)]


new_list_np = np.array(list)

img_np = np.array(img)

list_w_greyvalue = []

for i in new_list_np:
    list_w_greyvalue.append(img[new_list_np[i, 0], new_list_np[i, 1]])

for j in new_list_np:
    img_np = img[new_list_np[j, 0], new_list_np[j, 1]] = 0

最后一部分,黑色像素的绘制有效,但是当我想输出带有灰度值的列表时,我总是得到一个带有元组的列表,我无法真正理解其中的值。 其实应该是每个像素一个值,代表灰度值,为什么我得到一个元组?

还有什么让我感到困惑: 我用来通过(工作)循环计数的变量 j 也采用元组的形式(对于我的图像:[ 692 1023] )。但这也应该只是一个数,是加起来的吧?

已经感谢您的帮助(我是编码的初学者)

您的代码存在许多问题。首先,list 是 Python 中内置类型的名称。通过使用它作为变量的名称,您将覆盖该类型的构造函数。这是一件坏事。给它起一个更好、更具描述性的名称,例如:

>>> pixels_of_interest = [(11, 5), (3, 16), (0, 25), (2, 40)]

其次,您可以使用高级索引一次读取图像的所有值:

>>> gray_values = img_np[tuple(zip(*pixels_of_interest))]

要查看这里发生了什么:

>>> tuple(zip(*pixels_of_interest))
((11, 3, 0, 2), (5, 16, 25, 40))

zip(*pixels_of_interest) 基本上将所有 x 和 y 坐标分组为两个单独的元组。然后,通过使用这些元组作为索引,您可以访问图像数组中每个像素的值。

最后,既然您有了灰度值,就可以使用相同的坐标列表将图像数组的值设置为零:

>>> img_np[tuple(zip(*pixels_of_interest))] = 0

总计:

pixels_of_interest = [(11, 5), (3, 16), (0, 25), (2, 40)]
indices_to_read = tuple(zip(*pixels_of_interest))  # make advanced index tuple
gray_values = img_np[indices_to_read]  # read gray values
img_np[indices_to_read] = 0  # overwrite with black pixel

其他一些问题

另一个问题是:

img_np = img[new_list_np[j, 0], new_list_np[j, 1]] = 0

您正在将 img_np 分配给 img[new_list_np[j, 0], new_list_np[j, 1]] 的值,然后尝试将 that 分配给值 0。这显然是修改数组值的错误方法。一般而言,您只需要 some_array[row_index, column_index] = some_value。此外,imgcv2.imgread() 对象,我不确定该对象是什么类型,但您几乎可以肯定是要使用 img_np。顺便说一句,同样的事情发生在你的两个 for 循环中。 (这就是为什么它有助于为您的变量提供更好的名称,例如 cv2_img_dataimg_array 用于 cv2.imgread 的结果并将其转换为 numpy 数组。)

高级索引的好处是您可以一次对多个坐标进行相同的重新分配,而不必遍历坐标列表。

此外,您在迭代时看到元组的原因是因为您正在迭代从元组创建的二维数组:

>>> array_from_pixels = np.array(pixels_of_interest)
>>> for i in tuple_array:
...     print(i)
[11  5]
[ 3 16]
[ 0 25]
[ 2 40]