Mar-21-2020, 12:25 PM
Hello!
I'm working on a project that requires an example image to only have specific colours in it.
SO, what I've done is gone ahead and made the following script to scan over every pixel in the image and find which of the valid colours are closest to that colour. Then it saves that under a different image name. It works just fine, but it's really slow when I start adding even more valid colours (I suspect because it has to loop over every single valid colour for each pixel seperately). I was wondering if it's some way that I've designed it that makes it slow, or whether it is pretty much as fast as possible for what I'm trying to achieve.
So, is there a faster way to do what I'm trying to? Or is my code pretty much as fast as it's gonna get without sacrificing functionality?
I'm working on a project that requires an example image to only have specific colours in it.
SO, what I've done is gone ahead and made the following script to scan over every pixel in the image and find which of the valid colours are closest to that colour. Then it saves that under a different image name. It works just fine, but it's really slow when I start adding even more valid colours (I suspect because it has to loop over every single valid colour for each pixel seperately). I was wondering if it's some way that I've designed it that makes it slow, or whether it is pretty much as fast as possible for what I'm trying to achieve.
import os,operator from PIL import Image src = "test.jpg" dst = "dst.jpg" #Delete destination file if it already exists if (os.path.exists(dst)): os.remove(dst) #Load up the image im = Image.open(src) pixels = im.load() width, height = im.size #Define the nearest pixels validColours = [] totalPixels = width * height loops = 0 oneTimeTrigger = False def findNearestPixelColour(pixel): global validColours,loops,totalPixels,oneTimeTrigger if (loops % 10000 == 0): print("Image Conversion: " + str(round(100 * float(loops) / float(totalPixels),2)) + "\t% complete") loops += 1 if (oneTimeTrigger == False): oneTimeTrigger = True f = open("colours.txt","r") for i in f.readlines(): validColours.append(i.replace("\n","").replace(" ","").split(',')) f.close() r = pixel[0] g = pixel[1] b = pixel[2] best = [0,0,0] for i in validColours: r_temp = int(i[0]) g_temp = int(i[1]) b_temp = int(i[2]) bestDiff = abs(pixel[0] - best[0]) + abs(pixel[1] - best[1]) + abs(pixel[2] - best[2]) curntDif = abs(pixel[0] - r_temp) + abs(pixel[1] - g_temp) + abs(pixel[2] - b_temp) if (bestDiff > curntDif): best = [r_temp,g_temp,b_temp] return best #Edit the image for i in range(0,width): for j in range(0,height): pixel = findNearestPixelColour(pixels[i,j]) pixels[i,j] = (pixel[0],pixel[1],pixel[2],255) im.save(dst)And inside the "colours.txt" file:
0,0,0, 0,0,127, 0,0,254, 0,127,0, 0,127,127, 0,127,254, 0,254,0, 0,254,127, 0,254,254, 127,0,0, 127,0,127, 127,0,254, 127,127,0, 127,127,127, 127,127,254, 127,254,0, 127,254,127, 127,254,254, 254,0,0, 254,0,127, 254,0,254, 254,127,0, 254,127,127, 254,127,254, 254,254,0, 254,254,127, 254,254,254,I am aware that the commas at the end of each line is unnecessary, but it allows for commenting code if ever I need to.
So, is there a faster way to do what I'm trying to? Or is my code pretty much as fast as it's gonna get without sacrificing functionality?