Я работаю с набором данных, аннотированным для пиксельной классификации. В изображениях с метками пикселей классы кодируются значениями 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 и отображаются черным цветом). Меня интересуют только кодировки в синем канале.