首页 > 解决方案 > 使用不进化的遗传算法重建图像

问题描述

我想创建一个重新创建图像的遗传算法。我已经为这个处理创建了程序,但是进化的图像与输入图像并不接近。

我相信我的健身功能有问题。我已经尝试了很多事情,从改变作为 DNA 一部分的多边形类型,我尝试了交叉和单亲,我尝试了多个适应度函数:跨所有通道的直方图比较、像素比较、亮度比较(对于黑白图像)。

    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++;
}

我对此的期望是获得与我的目标图像相似的一般形状和颜色,但我得到的只是具有随机颜色和 alpha 的随机多边形。

标签: javaprocessinggenetic-algorithm

解决方案


乍一看,代码看起来不错。您应该首先检查您的代码是否能够完全收敛到目标,例如通过提供由您的算法生成的具有随机基因组的目标图像(或者一个非常简单的图像,它应该可以很容易地由您的算法重新创建) )。

您正在使用像素之间的 SAD(绝对差之和)度量来计算适应度。您可以尝试使用 SSD(差异平方和),就像您在直方图差异方法中所做的那样,但在像素或块之间,这将严重惩罚较大的差异,因此剩余图像与目标的差异不会太大。您可以尝试使用像 HSV 这样更具感知性的图像空间,这样即使图像在 RGB 空间中更远,它们在视觉上也会更接近。

我认为比较整个图像的直方图可能过于宽松,因为有许多不同的图像会产生相同的直方图。比较单个像素可能过于严格,图像需要非常精确地对齐以获得低差异,所以除非你非常幸运,否则一切都会得到低适应度值,因此收敛会太慢。我建议您比较重叠块之间的直方图,不要使用所有 256 个级别,只使用大约 16 个级别左右(或使用某种重叠)。

阅读定向梯度直方图 (HOG)和其他类似技术,以获得改善您的健身功能的想法。我参加了巴塞罗那大学的 Coursera - Deteccion de Objetos图像中的对象识别在线课程,但它是西班牙语的。我很确定你可以找到类似的英语学习资料。

编辑:在尝试更复杂的事情之前,一个好主意是对每个重叠块的平均值进行 SAD 或 SSD(这与强烈模糊参考和生成的图像然后比较像素具有类似的效果,但速度更快)。适应度函数应该能够抵抗小的变化。偏移了几个像素或在丢弃低级细节后非常相似的图像应该比非常不同的图像具有更好的适应度,我认为模糊会产生这种效果。


推荐阅读