我想创建一种遗传算法来重新创建图像。我已经创建了用于该处理的程序,但是生成的图像与输入的图像没有任何相似之处。
我认为我的健身功能有问题。我已经尝试了许多更改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的随机多边形。
答案 0 :(得分:1)
乍一看,代码看起来不错。您首先应该检查代码是否完全能够收敛到目标,例如,通过馈入由您的算法生成的带有随机基因组的目标图像(或非常简单的图像,该图像应易于通过算法重新创建) )。
您正在使用像素之间的SAD(绝对差之和)度量标准来计算适合度。您可以像在直方图差异方法中一样,但在像素或块之间尝试使用SSD(平方差的总和),这将严重惩罚较大的差异,因此其余图像不会与目标差异太大。您可以尝试使用更具感知性的图像空间(例如HSV),以便即使在RGB空间中更远的图像也可以在视觉上更接近。
我认为比较整个图像的直方图可能太松懈,因为有许多不同的图像会导致相同的直方图。比较单个像素可能太严格,需要非常精确地对齐图像才能获得较小的差异,因此除非您非常幸运,否则所有内容都将具有较低的适应性值,因此收敛速度将太慢。我建议您比较重叠块之间的直方图,不要使用全部256个级别,仅使用大约16个级别(或使用某种重叠)。
阅读有关Histogram of oriented gradients (HOG)和其他类似技术的知识,以改善健身功能。我上了一门有关图像中物体识别的在线课程,Coursera - Deteccion de Objetos by the University of Barcelona是西班牙语。我相信您可以找到类似的英语学习材料。
编辑:在尝试更复杂的方法之前,一个好主意是对每个重叠块的平均值进行SAD或SSD(这将具有与强烈模糊参考图像和生成的图像然后比较像素的效果相似,但速度更快) )。适应功能应可抵抗微小的变化。偏移低像素细节后移动了几个像素或非常相似的图像比完全不同的图像具有更好的适应性,我认为模糊会产生这种效果。