Передача трехмерного изображения с определенной цветовой картой в двухмерное изображение с определенными значениями int

1

Для этого трехмерного изображения у него есть 6 классов, которые:

Impervious surfaces (RGB: 255, 255, 255)
Building (RGB: 0, 0, 255)
Low vegetation (RGB: 0, 255, 255)
Tree (RGB: 0, 255, 0)
Car (RGB: 255, 255, 0)
Clutter/background (RGB: 255, 0, 0)

Я хотел бы передать это изображение на 2d-изображение, где

Impervious surfaces --> 0
Building --> 1
Low vegetation --> 2
Tree --> 3
Car --> 4
Clutter/background --> 5

Я мог только вычислить, чтобы использовать для цикла как:

im = imageio.imread('kPUoO.png')
w,h = im.shape[:2]
im_ = np.zeros((w,h), dtype=np.uint8)
for i in range(w):
    for j in range(h):
        if list(im[i,j]) == [0,0,255]:
            im_[i,j] = 1
        if list(im[i,j]) == [0,255,255]:
            im_[i,j] = 2
        if list(im[i,j]) == [0,255,0]:
            im_[i,j] = 3
        if list(im[i,j]) == [255,255,0]:
            im_[i,j] = 4
        if list(im[i,j]) == [255,0,0]:
            im_[i,j] = 5

Мне интересно, есть ли более простой способ этой работы. Спасибо!

  • 0
    Может быть, ваши данные изначально были всего шесть классов, но теперь их больше. Например, im[0, 0] равно [ 14, 255, 237] . В этом изображении более 4000 различных цветов. Изображение хранится в формате JPEG , который является форматом с потерями . Если у вас изначально было только шесть цветов, упомянутых в вопросе, и вы хотите сохранить эти значения точно в файле изображения, используйте формат без потерь, такой как PNG .
  • 0
    Хорошо, я вижу это, спасибо!
Теги:
numpy

2 ответа

2
Лучший ответ

Я пытался подумать о более общей проблеме, где вы могли бы иметь любую ценность от 0 до 255, присутствующих в каждой группе, или даже более трех групп...

Мы можем кодировать позиции 0 и 255 путем применения другого сдвига бит к каждому столбцу (от 0 до 3 бит для нулей в столбцах 0, 1 и/или 2 и от 4 до 6 бит для 255 в столбцах 0, 1 и/или 2):

a = (im == 0) << numpy.array([0,1,2], numpy.uint8)
a += (im == 255) << numpy.array([3,4,5], numpy.uint8)

Сумма вдоль последней оси тогда однозначно кодирует классы. Разделение на 7 не обязательно, оно просто дает более простые метки классов.

numpy.add.reduce(a, -1) // 7

Оттуда это стандартная карта 1:1 для повторной маркировки классов. Я думаю, что для больших изображений или большого количества изображений этот подход может быть быстрее.

Чтобы увидеть, как это работает:

0,0,0 = 1<<0 + 1<<1 + 1<<2 + 0<<3 + 0<<4 + 0<<5 = 7, /7 = 1
0,0,255 = 1<<0 + 1<<1 + 0<<2 + 0<<3 + 0<<4 + 1<<5 = 35, /7 = 5
0,255,255 = 1<<0 + 0<<1 + 0<<2 + 0<<3 + 1<<4 + 1<<5 = 49, /7 = 7
255,255,255 = 0<<0 + 0<<1 + 0<<2 + 1<<3 + 1<<4 + 1<<5 = 56, /7 = 8
etc...

Эквивалентная формулировка:

a = (im == 0) * numpy.array([1,2,4], numpy.uint8)
a += (im == 255) * numpy.array([8,16,32], numpy.uint8)
numpy.add.reduce(a, -1) //7
0
im = imageio.imread('kPUoO.png')
w,h = im.shape[:2]
im_ = np.zeros((w,h), dtype=np.uint8)
pos1 = np.where((im[:,:,0]==0) & (im[:,:,1]==0) & (im[:,:,2]==255))
pos2 = np.where((im[:,:,0]==0) & (im[:,:,1]==255) & (im[:,:,2]==255))
pos3 = np.where((im[:,:,0]==0) & (im[:,:,1]==255) & (im[:,:,2]==0))
pos4 = np.where((im[:,:,0]==255) & (im[:,:,1]==255) & (im[:,:,2]==0))
pos5 = np.where((im[:,:,0]==255) & (im[:,:,1]==0) & (im[:,:,2]==0))
im_[pos1] = 1
im_[pos2] = 2
im_[pos3] = 3
im_[pos4] = 4
im_[pos5] = 5

Ещё вопросы

Сообщество Overcoder
Наверх
Меню