Целое в массив битов и обратно в целочисленное ((многократное) однократное кодирование на основе битовых значений в RGB-изображении) - PullRequest
0 голосов
/ 01 ноября 2018

Я работаю с набором данных, аннотированным для пиксельной классификации. В изображениях с метками пикселей классы кодируются значениями RGB следующим образом:

RGB = 0b00 ... 1000 = 0x000008: основное текстовое тело

RGB = 0b00 ... 0100 = 0x000004: украшение

RGB = 0b00 ... 0010 = 0x000002: комментарий

RGB = 0b00 ... 0001 = 0x000001: фон (вне страницы)

В идеале, я бы напрямую преобразовал целые числа в синем канале в трехмерный массив битов, вырезав последние 4 слоя глубины. Затем для обратного преобразования просто добавьте один из 0 и конвертируйте обратно в целое число.

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

Ниже приведен код, который я написал до сих пор, который работает, но некоторые операции выполняются очень медленно, когда я перехожу к большим изображениям, и я уверен, что numpy не лучшим образом использует предоставленные функции.

Есть идеи, как это улучшить и сделать быстрее?

from PIL import Image
import numpy as np


def int_to_one_hot(x, n_classes):
    s = '{0:0' + str(n_classes) + 'b}'
    return list(map(int, list(s.format(x))))


def label_img_to_one_hot(np_array, nb_classes):
    im_np = np.array(np_array)[:, :, 2].astype(np.int8)

    class_dict = {x: int_to_one_hot(x, nb_classes) for x in np.unique(im_np)}

    # create an empty matrix to fill
    one_hot_matrix = np.ndarray(shape=(im_np.shape[0], im_np.shape[1], nb_classes), dtype=np.int8)

    # fill the matrix
    for key, value in class_dict.items():
        ind = np.where(im_np == key)
        for i, j in zip(ind[0], ind[1]):
            one_hot_matrix[i, j, ] = value

    return one_hot_matrix


def one_hot_to_output(matrix):
    # create RGB
    matrix = np.char.mod('%d', matrix)
    zeros = (32 - matrix.shape[2]) * '0'
    B = np.array([[int('{}{}'.format(zeros, ''.join(matrix[i][j])), 2) for j in range(matrix.shape[1])] for i in
              range(matrix.shape[0])])

    RGB = np.dstack((np.zeros(shape=(matrix.shape[0], matrix.shape[1], 2), dtype=np.int8), B))
    return RGB

Пример использования (массив - синий канал входного изображения RGB):

array = np.array([[[0, 0, 8],
    [0, 0, 1],
    [0, 0, 1]],

   [[0, 0, 8],
    [0, 0, 1],
    [0, 0, 1]],

   [[0, 0, 8],
    [0, 0, 1],
    [0, 0, 1]]])

one_hot = label_img_to_one_hot(array, 4)
out = one_hot_to_output(one_hot)

Вот пример входного изображения. Красный канал также имеет кодировку (которая является единственной видимой, поскольку кодировки синего канала находятся в диапазоне 0-14 и отображаются черным цветом). Меня интересуют только кодировки в синем канале.

Sample image

1 Ответ

0 голосов
/ 06 ноября 2018

Обновленный ответ

Спасибо за предоставление изображения, если вы запустите это изображение через мой код, вы получите это, которое, кажется, правильно идентифицирует по-разному классифицированные элементы вашего изображения:

enter image description here

Оригинальный ответ

Я сделал образец изображения, поскольку вы его не предоставили. Цвета в нем следующие:

  • красный фон - RGB (255,0,1)
  • синее слово "комментарий" - это rgb (0,0,130) - примечание 130 = 128 + 2
  • зеленое слово "украшение" - это RGB (0,255,4),
  • желтое слово "основной" - это rgb (255,255,8)

enter image description here

Теперь код, который вы хотите получить, выглядит следующим образом:

#!/usr/bin/env python3

import numpy as np
from PIL import Image

# Load image and convert to numpy array
im=np.array(Image.open('image.png').convert('RGB'))

# Make masks of main, decoration, comment, background
blue       = im[:,:,2]          # Extract just blue channel
bg         = (blue & 1) > 0
comment    = (blue & 2) > 0
decoration = (blue & 4) > 0
text       = (blue & 8) > 0

# Now edit image using masks
im[bg]         = 0,0,0          # background => black
im[comment]    = 255,255,0      # comments => yellow
im[decoration] = 0,255,255      # decorations => cyan
im[text]       = 255,0,255      # text => magenta

# Save result
Image.fromarray(im).save("result.png")

и дает это:

enter image description here

...