I am trying to reduce the color of a ppm image file from 255 colors to 5 colors(red, blue, green, black and white). When I initiate my test file, the pixel_list generated is only reds, which is not correct. I'm using the Euclidean distance formula to find which of the 5 colors the pixel is closest too and changing the values to that color. (Color Reduction)
Here is an example of my data: (The first three rows are file type, dimensions and total colors. The following rows are pixel data ordered in r, g, b.)
P3
200 200
255
0
48
255
216
52
180
252
255
176
212
96
4
0
108
20
40
64
80
140
0
80
My code:
import math
with open('test_pattern.ppm','r') as f:
output = f.read().split("\n")
i = 0
r_point = 3 + i
g_point = 4 + i
b_point = 5 + i
pixel_list = []
resolution = []
resolution.append(output[1].split(" "))
file_size = resolution[0]
file_size = int(file_size[0]) * int(file_size[1])
file_size = int(file_size*3)
print(file_size)
while file_size >= i:
r = int(output[r_point])
g = int(output[g_point])
b = int(output[b_point])
if all(math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2) < x for x in [math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)]):
r = 255
g = 0
b = 0
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
elif all(math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2) < x for x in [math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2) , math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)]):
r = 0
g = 255
b = 0
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i +=3
elif all(math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2) < x for x in [math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2) , math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)]):
r = 0
g = 0
b = 255
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
elif all(math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2) < x for x in [math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2) , math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2) , math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)]):
r = 0
g = 0
b = 0
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
elif all(math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2) < x for x in [math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2) , math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2) , math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2)]):
r = 255
g = 255
b = 255
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
print(pixel_list)
Second Try:
import math
with open('test_pattern.ppm','r') as f:
output = f.read().split("\n")
i = 0
r_point = 3 + i
g_point = 4 + i
b_point = 5 + i
pixel_list = []
resolution = []
resolution.append(output[1].split(" "))
file_size = resolution[0]
file_size = int(file_size[0]) * int(file_size[1])
file_size = int(file_size*3)
print(file_size)
while file_size >= i:
r = int(output[r_point])
g = int(output[g_point])
b = int(output[b_point])
a = math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2)
b = math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2)
c = math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2)
d = math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2)
e = math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)
L = [a, b, c, d, e]
idx = min(range(len(L)), key=L.__getitem__)
if idx == 0:
# red
r = 255
g = 0
b = 0
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
if idx == 1:
# green
r = 0
g = 255
b = 0
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
if idx == 2:
# blue
r = 0
g = 0
b = 255
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
if idx == 3:
# white
r = 0
g = 0
b = 0
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
if idx == 4:
# black
r = 255
g = 255
b = 255
pixel_list.append(r)
pixel_list.append(g)
pixel_list.append(b)
i += 3
print(pixel_list)
What you seem to be trying to say here
a < b and c and d and e
is
a < b and a < c and a < d and a < e
But it's pretty inefficient to compute and compare those values over and over anyway, when all you are really interested in is the minimum.
so consider:
a = math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2)
b = math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2)
c = math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2)
d = math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2)
e = math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)
and
L = [a, b, c, d, e]
idx = min(range(len(L)), key=L.__getitem__)
Now idx
is the index of the smallest item in L
, so you can use that index to select the colour
if idx == 0:
# red
if idx == 1:
# green
if idx == 2:
# blue
if idx == 3:
# white
if idx == 4:
# black
Aside: It's a good optimisation not to bother with the sqrt as it doesn't affect the ordering.
Here is an example run using the first pixel of you question (r=0, g=48, b=255)
>>> import math
>>> r = 0
>>> g = 48
>>> b = 255
>>> a = math.sqrt((r-255)**2 + (g - 0)**2 + (b-0)**2)
>>> b = math.sqrt((r-0)**2 + (g - 255)**2 + (b-0)**2)
>>> c = math.sqrt((r-0)**2 + (g - 0)**2 + (b-255)**2)
>>> d = math.sqrt((r-0)**2 + (g - 0)**2 + (b-0)**2)
>>> e = math.sqrt((r-255)**2 + (g - 255)**2 + (b-255)**2)
>>> L = [a, b, c, d, e]
>>> idx = min(range(len(L)), key=L.__getitem__)
>>> idx
2