【问题标题】:Python | Numpy array images transformations蟒蛇 | Numpy 数组图像转换
【发布时间】:2019-06-19 05:52:16
【问题描述】:

我有一个形状为(1000, 50, 100, 3) (class 'numpy.ndarray') 的 Numpy 图像数组,其中包含 1000 个图像 RGB(高度 = 50,宽度 = 100,通道 = 3)。我想首先将RGB 值转换为YUV 值并重新调整它们以获得yuv 值。下面给出了逐像素转换器的原型实现。

我的问题:有没有一种简单的方法可以进行这种转换?

def yuv(_pixel):
    R, G, B = _pixel[0], _pixel[1], _pixel[2]
    Y = 0.299 *  R + 0.587 * G + 0.114 * B
    y = Y / 127.5 - 1
    u = (0.493 * (B - Y)) / 127.5 - 1
    v = (0.887 * (R - Y)) / 127.5 - 1
    return np.array([y, u, v])

【问题讨论】:

  • 您的功能不起作用。 Y的定义在哪里?是y吗? @markuscosinus 好吧。问题在于循环遍历每个像素的过程效率极低。
  • 我的解决方案有效吗?如果是,您可以接受并投票。这也会给你一些分数。 :)

标签: python numpy rgb yuv


【解决方案1】:

你看过numpy.apply_along_axis吗?

你可以这样做:

images_yuv = np.apply_along_axis( yuv, -1, images_rgb)

编辑:混淆了参数的顺序

【讨论】:

  • 这不起作用。即使您将images_rgbyuv 交换以正确传递参数,结果似乎也不好。
  • 将参数的顺序更改为 images_yuv = np.apply_along_axis(yuv, -1, imgs) 并将样本大小减少到 100 张图像(奇怪的是,对于 64GB 内存的 apply_along_axis 来说,1000 张图像似乎太多了),np.apply_along_axis 正在工作很好,即使它真的很慢。因此,如果性能不重要,这似乎也是一个很好的解决方案。
  • @Scotty1- 实际上我混合了参数的顺序,可能你需要批量切割。如果可以就地应用该函数会很好,因为它可以保持形状,但看起来没有提供该功能的 numpy 内置函数。
【解决方案2】:

您可以对转换进行矢量化处理,以便同时转换所有 R、G 和 B 像素:

def yuv_vec(images):
    R, G, B = images[:, :, :, 0], images[:, :, :, 1], images[:, :, :, 2]
    y = (0.299 *  R + 0.587 * G + 0.114 * B) / 127.5 - 1
    u = (0.493 * (B - y)) / 127.5 - 1
    v = (0.887 * (R - y)) / 127.5 - 1
    yuv_img = np.empty(images.shape)
    yuv_img[:, :, :, 0] = y
    yuv_img[:, :, :, 1] = u
    yuv_img[:, :, :, 2] = v
    return yuv_img

为了计时性能,我将展示问题中所示 yuv 函数的简短嵌套循环实现:

def yuv(_pixel):
    R, G, B = _pixel[0], _pixel[1], _pixel[2]
    y = (0.299 *  R + 0.587 * G + 0.114 * B) / 127.5 - 1
    u = (0.493 * (B - Y)) / 127.5 - 1
    v = (0.887 * (R - Y)) / 127.5 - 1
    return np.array([y, u, v])

def yuvloop(imgs):
    yuvimg = np.empty(imgs.shape)
    for n in range(imgs.shape[0]):
        for i in range(imgs.shape[1]):
            for j in range(imgs.shape[2]):
                yuvimg[n, i, j] = yuv(imgs[n, i, j])
    return yuvimg

一些速度比较:

imgs = np.random.randint(0, 256, size=(100, 50, 100, 3))
%timeit yuvloop(imgs)
# Out: 8.79 s ± 265 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
% timeit np.apply_along_axis(yuv, -1, imgs)
# Out: 9.92 s ± 360 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit yuv_vec(imgs)
# Out: 34.4 ms ± 385 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

所以这比在像素上循环快 256 倍。使用np.apply_along_axis 似乎更慢。三者的结果都是一样的。
我将测试样本的大小减少到 100 张图像,否则测试会太慢。

【讨论】:

  • A nit: np.random.randint(0, 256, size=(100,50,100,3)) 以正确的形状生成数据,为您节省大量 reshape 的成本。
  • 哦,很高兴知道!谢谢!我马上就实现了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多