I have a numpy array from a rgb image (64,64,3) and I need to convert each existing rgb combination to one class, represented by an integer value. So that in the end I have an array (64,64) which contains integer values (0-N). These values represent specific rgb combination from the picture. Of course every rgb combination just gets one value. In short: Every color is one class, and every pixel has one fitting class-value (0-N) :)
Obviously its not a big problem, I could just go through each pixel, check the rgb values and if they are not in an "already discovered RGB" tempList, I add these values and give those rgb values an integer value representing the class, otherwise I search in the tempList for the rgb values and give the integer value I wrote down in the List - or something like that.
But to be honest, I need to do this for a lot of images and I try to get better with python. So I want to know if someone has a more efficent way to do this? I scrolled through the libaries and boards and couldn't find a good approach.
CodePudding user response:
You can convert three 8 bit integers into a 32bit integer and easily recover the three integer back. The idea is to use bitwise operations, this way each 8 bit represents one of the rgb colors. This way you already know the N = 16777215 (including zero) = 256**3.
The following code can do this:
def rgbtoint32(rgb):
color = 0
for c in rgb[::-1]:
color = (color<<8) c
# Do not forget parenthesis.
# color<< 8 c is equivalent of color << (8 c)
return color
def int32torgb(color):
rgb = []
for i in range(3):
rgb.append(color&0xff)
color = color >> 8
return rgb
rgb = [32,253,200]
color = rgbtoint32(rgb)
rgb_c = int32torgb(color)
print(rgb)
print(color)
print(rgb_c)
This gives:
[32, 253, 200]
13172000
[32, 253, 200]
Update: Using "view" from numpy, as denoted below by "Mad Physicist ", one can efficiently do the above process as
rgb = np.array([[[32,253,200], [210,25,42]]],dtype = np.uint8)
size_d = list(rgb.shape)
size_d[2] = -1
# Converting to 2D int32 array
colorint32 = np.dstack((rgb,np.zeros(rgb.shape[:2], 'uint8'))).view('uint32').squeeze(-1)
# Converting back from the int32 array to RGB space
rgb_c = colorint32.view('uint8').reshape(size_d)[:,:,:3]
# Print results
print(rgb)
print(colorint32)
print(rgb_c)
Which gives
[[[ 32 253 200]
[210 25 42]]]
[[13172000 2759122]]
[[[ 32 253 200]
[210 25 42]]]
CodePudding user response:
If you have a MxNx3 numpy array of type uint8
, you can add an empty alpha channel and view it as a unit32
:
np.dstack((img, np.zeros(img.shape[:2], 'uint8'))).view('uint32').squeeze(-1)