I need to find a random color, given a specific seed number - fast. given the same ID twice, should return the same color.
I did this:
def id_to_random_color(number):
random_bytes = hashlib.sha1(bytes(number)).digest()
return [int(random_bytes[-1]) / 255, int(random_bytes[-2]) / 255, int(random_bytes[-3]) / 255, 1.0]
The problem is that calculating the sha1 of numbers many times is very slow in total. (I'm using this function about 100k times)
Edit: The reason I use a hash function is that I want to have colors that are different for numbers that are close
e.g id_to_random_color(7)
should be very different from id_to_random_color(9)
In the hexadecimal format, the #symbol is followed by six hexadecimal numbers. RGB colors are hexadecimal colors. To acquire a random color, the random() method is used. Random() is a commonly used Python module that can produce random integers or colors.
Python Random seed() Method The seed() method is used to initialize the random number generator. The random number generator needs a number to start with (a seed value), to be able to generate a random number. By default the random number generator uses the current system time.
To generate random number in Python, randint() function is used. This function is defined in random module.
Many researchers worry about how to choose a random number seed. Some people use an easy-to-remember sequence such as their phone number or the first few digits of pi. Others use long prime numbers such as 937162211.
Using simple random number generators with kind of static variables could improve performance:
import random
prev, r, g, b = None, 0, 0, 0
def id_to_random_color(number):
global prev, r, g, b
if number != prev:
r = random.random()
g = random.random()
b = random.random()
prev = number
return r, g, b, 1.0
Update:
As AndrewMcDowell stated in his comment, the function could return different values if the input is repeated in not sequential occasions.
Here is a possible workaround:
import random
memory = {}
def id_to_random_color(number, memory):
if not number in memory:
r = random.random()
g = random.random()
b = random.random()
memory[number] = (r, g, b, 1.0)
return memory[number]
Further update:
The same function skeleton could be used even to calculate hash:
memory = {}
def id_to_random_color(number):
if not number in memory:
numByte = str.encode(number)
hashObj = hashlib.sha1(numByte).digest()
r, g, b = hashObj[-1] / 255.0, hashObj[-2] / 255.0, hashObj[-3] / 255.0
memory[number]= (r, g, b, 1.0)
return r, g, b, 1.0
else:
return memory[number]
Despite it is a bit more verbose syntax, the else
statement improves a bit performances, avoiding subsequent memory write and read (as Jake stated in his answer).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With