【发布时间】:2017-08-02 17:14:09
【问题描述】:
我想用 Python 将 3 通道 RGB 图像转换为索引图像。它用于处理为语义分割训练深度网络的标签。通过索引图像,我的意思是它有一个通道,每个像素都是索引,它应该从零开始。当然,它们应该具有相同的大小。转换基于 Python dict 中的以下映射:
color2index = {
(255, 255, 255) : 0,
(0, 0, 255) : 1,
(0, 255, 255) : 2,
(0, 255, 0) : 3,
(255, 255, 0) : 4,
(255, 0, 0) : 5
}
我实现了一个简单的函数:
def im2index(im):
"""
turn a 3 channel RGB image to 1 channel index image
"""
assert len(im.shape) == 3
height, width, ch = im.shape
assert ch == 3
m_lable = np.zeros((height, width, 1), dtype=np.uint8)
for w in range(width):
for h in range(height):
b, g, r = im[h, w, :]
m_lable[h, w, :] = color2index[(r, g, b)]
return m_lable
输入im 是一个由cv2.imread() 创建的numpy 数组。但是,这段代码真的很慢。
由于 im 在 numpy 数组中,我首先尝试了 numpy 的 ufunc,如下所示:
RGB2index = np.frompyfunc(lambda x: color2index(tuple(x)))
indices = RGB2index(im)
但事实证明,ufunc 每次只需要一个元素。我无法一次给函数三个参数(RGB 值)。
那么还有其他方法可以进行优化吗? 如果存在更有效的数据结构,则映射不必如此。我注意到 Python dict 的访问不会花费太多时间,但是从 numpy 数组 到 tuple(它是可散列的)的转换确实如此。
PS: 我得到的一个想法是在 CUDA 中实现一个内核。但这会更复杂。
UPDATA1: Dan Mašek's Answer 工作正常。但首先我们必须将 RGB 图像转换为灰度图像。当两种颜色具有相同的灰度值时,可能会出现问题。
我在这里粘贴工作代码。希望它可以帮助别人。
lut = np.ones(256, dtype=np.uint8) * 255
lut[[255,29,179,150,226,76]] = np.arange(6, dtype=np.uint8)
im_out = cv2.LUT(cv2.cvtColor(im, cv2.COLOR_BGR2GRAY), lut)
【问题讨论】:
-
所以输入将只包含您列出的那 6 种不同的颜色?如果是这样,从 RBG 到灰度的转换将为您提供以下灰度值:[255,29,179,150,226,76] - 6 个不同的值。然后通过
cv2.LUT运行它,将其重新映射到 0-5。 -
更改顺序或 for 循环,即使这样也会加快您的代码速度
-
@DanMašek 谢谢!您的解决方案工作正常。在我没有意识到转换为灰度时 RGB 的权重不同之前。灰度图像的体积为0-255。这意味着最大类数是 256。不过,在大多数情况下都可以。问题可能是某些颜色可能具有相同的灰度值。
-
@smttsp 感谢您的评论。但这无济于事
-
@DanMašek 没错。这就是我要找的。我试图实现一个 numpy ufunc。但它只需要一个元素一次数组。如果OpenCV提供接口让我们自定义
convert函数就好了。
标签: python opencv numpy deep-learning