1

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?

3
  • Quick question what happens when you remove the -1 parts from for i in range(height - 1): for j in range(width - 1):? Commented Aug 4, 2014 at 7:44
  • If you are talking about removing them from the fitness function, nothing happens, the error still persists. Commented Aug 4, 2014 at 7:45
  • Sorry I didn't read the stack trace so I was looking at your loops to see if anything looked questionable, I would focus on the generate and seed_test code, print the lengths and content of the params to see if they look valid Commented Aug 4, 2014 at 7:53

2 Answers 2

2

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)):
    ...
1
  • Thank you sir. This script is an adaptation of another I found, and I'm still trying to work out the kinks in it. Commented Aug 4, 2014 at 8:41
0

In your code you are setting the global elements to 100, why not set it to len(elements)? At present if there are less that 100 seed valuers the algorithm id guaranteed to fail in the way you describe.

A problem with your current solution attempt is the fact that much of the "coupling" between the various functions takes place through global variables. In Python we like to say "implicit is better than explicit", and best software engineering practice would be to pass the data explicitly to those functions that use it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.