Питон |Преобразования изображений массивов - PullRequest
0 голосов
/ 25 января 2019

У меня есть массив изображений Numpy с формой (1000, 50, 100, 3) (class 'numpy.ndarray'), который содержит 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])

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Вы можете векторизовать преобразование так, чтобы все пиксели 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 изображений, в противном случае тестирование было бы слишком медленным.

0 голосов
/ 25 января 2019

Вы смотрели в numpy.apply_along_axis?

Вы можете сделать:

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

edit: перепутал порядок аргументов

...