Реконструкция изображения с использованием генетического алгоритма не эволюционирует - PullRequest
0 голосов
/ 31 декабря 2018

Я хочу создать генетический алгоритм, который воссоздает изображения.Я создал программу для этой обработки, но эволюционирующие изображения не являются чем-то близким к входному изображению.

Я считаю, что у меня проблема с моей функцией пригодности.Я пробовал много вещей от изменения типов полигонов, которые являются частью ДНК, я пытался сделать как кроссовер, так и одного родителя, и я пробовал несколько функций пригодности: сравнение гистограммы по всем каналам, сравнение пикселей, сравнение яркости (длячерно-белые изображения).

    public void calcFitness(PImage tar){
    tar.loadPixels();
    image.loadPixels();
    int brightness = 0;
    for(int i = 0; i < image.pixels.length;i++){
        brightness += Math.abs(parent.brightness(tar.pixels[i])-parent.brightness(image.pixels[i]));
    }
    fitness = 1.0/ (Math.pow(1+brightness,2)/2);
}

public void calculateFitness(){
    int[] rHist= new int[256], gHist= new int[256], bHist = new int[256];
    image.loadPixels();

    //Calculate Red Histogram
    for(int i =0; i<image.pixels.length;i++) {
        int red = image.pixels[i] >> 16 & 0xFF;
        rHist[red]++;
    }

    //Calculate Green Histogram
    for(int i =0; i<image.pixels.length;i++) {
        int green = image.pixels[i] >> 8 & 0xFF;
        gHist[green]++;
    }

    //Calculate Blue Histogram
    for(int i =0; i<image.pixels.length;i++) {
        int blue = image.pixels[i] & 0xFF;
        bHist[blue]++;
    }

    //Compare the target histogram and the current one
    for(int i = 0; i < 256; i++){
        double totalDiff = 0;
        totalDiff += Math.pow(main.rHist[i]-rHist[i],2)/2;
        totalDiff += Math.pow(main.gHist[i]-gHist[i],2)/2;
        totalDiff += Math.pow(main.bHist[i]-bHist[i],2)/2;

        fitness+=Math.pow(1+totalDiff,-1);
    }

}

public void evaluate(){
    int totalFitness = 0;
    for(int i = 0; i<POPULATION_SIZE;i++){
        population[i].calcFitness(target);
        //population[i].calculateFitness();
        totalFitness+=population[i].fitness;
    }
    if(totalFitness>0) {
        for (int i = 0; i < POPULATION_SIZE; i++) {
            population[i].prob = population[i].fitness / totalFitness;
        }
    }
}
   public void selection() {
    SmartImage[] newPopulation = new SmartImage[POPULATION_SIZE];
    for (int i = 0; i < POPULATION_SIZE; i++) {
        DNA child;
        DNA parentA = pickOne();
        DNA parentB = pickOne();
        child = parentA.crossover(parentB);
        child.mutate(mutationRate);
        newPopulation[i] = new SmartImage(parent, child, target.width, target.height);
    }
    population = newPopulation;
    generation++;
}

От этого я ожидаю получить общую форму и цвет, аналогичные моему целевому изображению, но все, что я получаю, - это случайные многоугольники со случайными цветами и альфами.

1 Ответ

0 голосов
/ 01 января 2019

Код выглядит на первый взгляд хорошо.Сначала вы должны убедиться, что ваш код вообще способен сходиться к цели, например, передав целевое изображение, сгенерированное вашим алгоритмом, случайным геномом (или очень простое изображение, которое должно быть легко воссоздано вашим алгоритмом).).

Вы используете метрику SAD (сумма абсолютных разностей) между пикселями для расчета пригодности.Вы можете попробовать использовать SSD (сумму квадратов разностей), как вы делаете это в методе различий гистограммы, но между пикселями или блоками, что сильно штрафует большие различия, поэтому оставшиеся изображения не будут слишком отличаться от цели.Вы можете попытаться использовать более воспринимаемое пространство изображений, например HSV, чтобы изображения были ближе визуально, даже если они находятся дальше в пространстве RGB.

Я думаю, что сравнение гистограммы всего изображения может быть слишком слабым, посколькумного разных изображений, которые приведут к одной и той же гистограмме.Сравнение отдельных пикселей может быть слишком строгим, изображение должно быть выровнено очень точно, чтобы получить низкие различия, поэтому все получает низкие значения пригодности, если вам не очень повезло, поэтому сходимость будет слишком медленной.Я бы порекомендовал вам сравнить гистограмму между перекрывающимися блоками, и не использовать все 256 уровней, использовать только около 16 уровней или около того (или использовать какое-то перекрытие).

Читать о Гистограммаориентированных градиентов (HOG) и других подобных техник, чтобы получить идеи для улучшения вашей фитнес-функции.Я прошел онлайн-курс о распознавании объектов в изображениях, Coursera - Deteccion de Objetos от Университета Барселоны , но на испанском языке.Я почти уверен, что вы можете найти похожие учебные материалы на английском языке.

Редактировать: прежде чем пытаться что-то более сложное, хорошей идеей было бы сделать SAD или SSD в среднем для каждого перекрывающегося блока (который имел бы похожееэффект сильного размытия эталонных и сгенерированных изображений и последующего сравнения пикселей, но быстрее).Фитнес-функция должна быть устойчивой к небольшим изменениям.Изображение, смещенное на несколько пикселей или очень похожее после отбрасывания деталей низкого уровня, должно иметь гораздо лучшую пригодность, чем совсем другое изображение, и я думаю, что размытие будет иметь такой эффект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...