I want to transform RGB labels of a mask of PASCAL to integer labels, how can I do that using numpy? I searched for a long time, but I cannot find a fast way to do it.
Say, I have a ( W = 3, H = 3, C=3) image, the value in each pixel is a RGB label, say [128, 0, 128] means this label belongs to Class 1, and [128, 256, 0] means this is labeled as Class 2, and [1, 1, 1] means this is labeled as Class 3. For example, in this image, pixels are labeled as [[1, 1, 1], [2, 2, 2], [3, 3, 3]] conceptually and encoded physically by such RGB label convention. And I want to exactly convert this ( W = 3, H = 3, C=3) mask to a ( W = 3, H = 3, C=1) mask, which in this case is exactly [[[1, 1, 1], [2, 2, 2], [3, 3, 3]]].
For clearity, the input is [[[128, 0, 128],[128, 0, 128],[128, 0, 128]],[[128, 256, 0],[128, 256, 0],[128, 256, 0]], [[1, 1, 1],[1, 1, 1],[1, 1, 1]]], which is (3,3,3), and the output should be [[[1],[1],[1]],[[2],[2],[2]],[[3],[3],[3]]], which is (3,3,1)
Such conversion means we need to pick the vector of each pixel and compare it with a list of encoding of length 3 in this example and get the index of a match. How can I do that in a fast way using numpy?
A very trivial and very slow implementation will be
labels = np.array([[128, 0, 128], [128, 256, 0], [1, 1, 1]])
def convert(x):
a = np.zeros((x.shape[0], x.shape[1], 1), x.dtype)
a = a-1 # defaut label is -1
for i in range(x.shape[0]):
for j in range(x.shape[1]):
# for each pixel, compare its color vector with those in `labels`, and find out the idx of matched one
for idx, l in enumerate(labels):
if np.array_equal(x[i][j], l):
a[i][j] = idx+1
return a