def _crossover(self, population, selected_imgs, crossover_prob):
     new_population = Population()
     new_population.phenotype = population.phenotype
     range_of_selected_images = range(len(selected_imgs))
     for i in range_of_selected_images:
         selected_img_index_range = list(range_of_selected_images)
         random.shuffle(selected_img_index_range)
         first_index = selected_img_index_range[0]
         second_index = selected_img_index_range[1]
         parent_1 = selected_imgs[first_index]
         parent_2 = selected_imgs[second_index]
         child = FakeImgCandidate(np.copy(self.img))
         for x, y in population.phenotype:
             r = random.random()
             if r <= crossover_prob:
                 new_pixel_value = (parent_1.get_pixel_value(x, y) + parent_2.get_pixel_value(x, y)) / 2
                 child.set_pixel_value(x, y, new_pixel_value)
         new_population.add_img(child)
     for selected_img in selected_imgs:
         new_population.add_img(selected_img)
     return new_population
    def _init_population(self, population_size, pixels_to_change_count):

        population = Population()
        width = self.img.shape[0] - 1
        height = self.img.shape[1] - 1
        all_indices = []
        for i in range(0, width):
            for j in range(0, height):
                all_indices.append((i, j))
        random.shuffle(all_indices)
        population.phenotype = all_indices[0:pixels_to_change_count]

        for i in range(population_size):
            fake_img_candidate = FakeImgCandidate(np.copy(self.img))
            for x, y in population.phenotype:
                current_pixel_value = fake_img_candidate.get_pixel_value(x, y)
                new_pixel_value = self._generate_new_pixel_value(current_pixel_value)
                fake_img_candidate.set_pixel_value(x, y, new_pixel_value)

            population.add_img(fake_img_candidate)

        return population