Search code examples
pythonnumpygenetic-algorithm

Numpy array index out of range with Genetic Algorithm


I wrote a script to generate an image based from a source, with randomized ellipses using genetic algorithms. I keep receiving this error (the length of seeds is different every time, this is just an example) after running it:

Output:

[[ 42 166  88  21]
 [ 25 201 321 227]
 [ 21  78 153  53]
 [  5  74 231  20]
 [  3  96 394  15]
 [ 20 239  28 244]
 [ 33   6  94  27]
 [  4 253 193 113]
 [ 10 139 323  16]
 [ 31   9  97 117]
 [ 23 273 181 214]
 [ 24 286 361 231]
 [ 33   2 187  47]
 [ 35  98 133 177]
 [ 10 307 136  76]
 [ 35 132 269 161]
 [ 25 147  11   2]
 [ 36 141 338 100]
 [ 23 163 430  37]
 [ 17 285 216  53]
 [ 18   2 181 119]
 [ 43 199 117 253]] 22

Traceback (most recent call last):
  File "E:/genetic image/genetic_image.py", line 106, in <module>
    generate()
  File "E:/genetic image/genetic_image.py", line 93, in generate
    params, test_image = seed_test(seeds[:random.randint(0, reproduce)])
  File "E:/genetic image/genetic_image.py", line 41, in seed_test
    r = int(seeds[i, 0] + random.random() - 0.5)
IndexError: index (22) out of range (0<=index<22) in dimension 0

Here is the script:

import random
import copy
import numpy
from PIL import Image, ImageDraw

optimal = Image.open("charles-darwin_large.jpg")
optimal = optimal.convert("RGB")
size = width, height = optimal.size
population = 2
generations = 5000
elements = int(1e3)
reproduce = height / 10
max_radius = height / 10
diff_max = height / 10

def random_test():
    test_elements = []
    test_image = Image.new("RGB", (width, height), "white")
    draw = ImageDraw.Draw(test_image)

    for i in range(elements):
        r = int(max_radius * random.random())
        x, y = random.randint(0, width), random.randint(0, height)
        color_value = random.randint(0, 255)
        color = (color_value, color_value, color_value)

        test_elements.append([r, x, y, color_value])

        draw.ellipse((x - r, y - r, x + r, y + r), fill = color)

    return test_elements, test_image

def seed_test(seeds):
    test_elements = []
    test_image = Image.new("RGB", (width, height), "white")
    draw = ImageDraw.Draw(test_image)

    print seeds, len(seeds)

    for i in range(elements):
        r = int(seeds[i, 0] + random.random() - 0.5)
        x, y = seeds[i, 1] + random.randint(-5, 5), seeds[i, 2] + random.randint(-5, 5)
        color_value = seeds[i, 3] + random.randint(-5, 5)
        color = (color_value, color_value, color_value)

        test_elements.append([r, x, y, color_value])

        draw.ellipse((x - r, y - r, x + r, y + r), fill = color)

    return test_elements, test_image

def grayscale(image):
    return image.convert("LA")

def fitness(source, generated):
    fitness = 0
    for i in range(height - 1):
        for j in range(width - 1):

            r1, g1, b1 = source.getpixel((j, i))
            r2, g2, b2 = generated.getpixel((j, i))

            deltaRed = r1 - r2
            deltaGreen = g1 - g2
            deltaBlue = b1 - b2

            pixelFitness = deltaRed ** 2 + deltaGreen ** 2 + deltaBlue ** 2

            fitness += pixelFitness

    return fitness

def generate():
    samples = []
    scores = [0] * reproduce

    for i in range(population):
        params, test_image = random_test()
        fitness_score = fitness(optimal, test_image)

        if fitness_score > scores[-1]:
            scores[-1] = fitness_score
            scores = sorted(scores)

            samples.append(params)

    for generation in range(generations):
        seeds = numpy.array(copy.deepcopy(samples))[0]
        samples = []
        scores = [0] * reproduce

        for i in range(population):
            params, test_image = seed_test(seeds[:random.randint(0, reproduce)])
            fitness_score = fitness(optimal, test_image)

            if fitness_score > scores[-1]:
                scores[-1] = fitness_score
                scores = sorted(scores)

                samples.append(params)

        for each in samples:
            print each

if __name__ == "__main__":
    generate()

The source image can be found here.

What does the error mean?


Solution

  • you have 1000 elements (1e3) and 22 seeds (indexes 0 - 21), so when you try to get the item seeds[22, 0] in following loop, the index is out of range:

    for i in range(elements):
        r = int(seeds[i, 0] ...
    

    I suspect tha what you need to do is:

    for i in range(len(seeds)):
        ...