gpt4 book ai didi

python - 如何有效地将三 channel 图像的每个像素映射到一个 channel ?

转载 作者:行者123 更新时间:2023-12-01 09:32:14 24 4
gpt4 key购买 nike

我正在编写一个 python 程序来预处理图像,以用作语义分割任务的标签。原始图像具有三个 channel ,其中代表每个像素的三个值的向量代表该像素的类标签。例如,[0,0,0] 的像素可能是类别 1,[0,0,255] 可能是类别 2,依此类推。

我需要将这些图像转换为单 channel 图像,像素值从0开始并连续增加以代表每个类别。本质上,我需要将旧图像中的 [0,0,0] 转换为新图像中的 0,将 [0,0,255] 转换为 1,对于所有类,依此类推。

这些图像的分辨率相当高,宽度和高度均超过 2000 像素。我需要对数百张图像执行此操作。我当前的方法涉及迭代每个像素并用相应的标量值替换 3 维值。

filename="file.png"
label_list = [[0,0,0], [0,0,255]] # for example. there are more classes like this
image = imread(filename)
new_image = np.empty((image.shape[0], image.shape[1]))
for i in range(image.shape[0]):
for j in range(image.shape[1]):
for k, label in enumerate(label_list):
if np.array_equal(image[i][j], label):
new_image[i][j] = k
break
imsave("newname.png", new_image)

问题是上面的程序效率非常低,每个图像运行需要几分钟。这对于处理我的所有图像来说太多了,因此我需要改进它。

首先,我认为可以通过将 label_list 转换为 numpy 数组和 using np.where 来删除最内层循环。 。但是,我不确定如何使用 np.where 在二维数组中查找一维数组,以及它是否会改进任何内容。

来自this thread ,我尝试定义一个函数并将其直接应用到图像上。但是,我需要将每个 3 维标签映射到标量。字典不能包含列表作为键。是否有更好的方法来做到这一点,它会有帮助吗?

是否有一种方法可以(大幅)提高效率,或者是否有更好的方法来完成上述程序的功能?

谢谢。

最佳答案

方法#1

这是一种使用 viewsnp.searchsorted 的方法 -

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
a = np.ascontiguousarray(a)
b = np.ascontiguousarray(b)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel(), b.view(void_dt).ravel()

# Trace back a 2D array back to given labels
def labelrows(a2D, label_list):
# Reduce array and labels to 1D
a1D,b1D = view1D(a2D, label_list)

# Use searchsorted to trace back label indices
sidx = b1D.argsort()
return sidx[np.searchsorted(b1D, a1D, sorter=sidx)]

因此,要将其用于 3D 图像数组,我们需要 reshape 形状,将高度和宽度合并为一维,并保持颜色 channel 不变,并使用标签函数。

方法#2

针对具有 [0,255] 范围的图像元素进行调整,我们可以利用矩阵乘法进行降维,从而进一步提高性能,如下所示 -

def labelpixels(img3D, label_list):
# scale array
s = 256**np.arange(img.shape[-1])

# Reduce image and labels to 1D
img1D = img.reshape(-1,img.shape[-1]).dot(s)
label1D = np.dot(label_list, s)

# Use searchsorted to trace back label indices
sidx = label1D.argsort()
return sidx[np.searchsorted(label1D, img1D, sorter=sidx)]

关于如何扩展图像案例并验证的示例运行 -

In [194]: label_list = [[0,255,255], [0,0,0], [0,0,255], [255, 0, 255]]

In [195]: idx = [2,0,3,1,0,3,1,2] # We need to retrieve this back

In [196]: img = np.asarray(label_list)[idx].reshape(2,4,3)

In [197]: img
Out[197]:
array([[[ 0, 0, 255],
[ 0, 255, 255],
[255, 0, 255],
[ 0, 0, 0]],

[[ 0, 255, 255],
[255, 0, 255],
[ 0, 0, 0],
[ 0, 0, 255]]])

In [198]: labelrows(img.reshape(-1,img.shape[-1]), label_list)
Out[198]: array([2, 0, 3, 1, 0, 3, 1, 2])

In [217]: labelpixels(img, label_list)
Out[217]: array([2, 0, 3, 1, 0, 3, 1, 2])

最后,输出需要重新整形回2D -

In [222]: labelpixels(img, label_list).reshape(img.shape[:-1])
Out[222]:
array([[2, 0, 3, 1],
[0, 3, 1, 2]])

关于python - 如何有效地将三 channel 图像的每个像素映射到一个 channel ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49863767/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com