使用不进化的遗传算法进行图像重建
Image reconstruction using a genetic algorithm not evolving
我想创建一个重新创建图像的遗传算法。我已经为这个处理创建了程序,但是进化的图像与输入图像没有任何关系。
我认为我的健身功能有问题。我尝试了很多事情,包括改变作为 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 的随机多边形。
代码乍一看还不错。您应该首先检查您的代码是否能够完全收敛到一个目标,例如,通过提供一个由您的算法生成的目标图像和一个随机基因组(或者一个非常简单的图像,它应该可以很容易地由您的算法重新创建) ).
您正在使用像素之间的 SAD(绝对差之和)度量来计算适应度。您可以像在直方图差异方法中那样尝试使用 SSD(差异平方和),但在像素或块之间,这将严重惩罚较大的差异,因此剩余的图像不会与目标差异太大。您可以尝试使用更直观的图像 space,例如 HSV,这样图像在视觉上会更接近,即使它们在 RGB space.
中更远。
我认为比较整个图像的直方图可能过于松懈,因为有许多不同的图像会导致相同的直方图。比较单个像素可能过于严格,图像需要非常精确地对齐以获得低差异,所以除非你非常幸运,否则一切都会得到低适应度值,这样收敛会太慢。我建议您比较重叠块之间的直方图,不要使用所有 256 个级别,只使用大约 16 个级别左右(或使用某种重叠)。
阅读有关 Histogram of oriented gradients (HOG) and other similar techniques to get ideas to improve your fitness function. I took an online course about object recognition in images, Coursera - Deteccion de Objetos by the University of Barcelona 但它是西班牙语的。我很确定你可以找到类似的英语学习资料。
编辑:在尝试更复杂的事情之前,一个好主意是对每个重叠块的平均值进行 SAD 或 SSD(这与强烈模糊参考和生成的图像然后比较像素具有类似的效果,但更快)。适应度函数应该对小的变化有弹性。移动了几个像素或在丢弃低级细节后非常相似的图像应该比非常不同的图像具有更好的适应性,我认为模糊会产生这种效果。
我想创建一个重新创建图像的遗传算法。我已经为这个处理创建了程序,但是进化的图像与输入图像没有任何关系。
我认为我的健身功能有问题。我尝试了很多事情,包括改变作为 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 的随机多边形。
代码乍一看还不错。您应该首先检查您的代码是否能够完全收敛到一个目标,例如,通过提供一个由您的算法生成的目标图像和一个随机基因组(或者一个非常简单的图像,它应该可以很容易地由您的算法重新创建) ).
您正在使用像素之间的 SAD(绝对差之和)度量来计算适应度。您可以像在直方图差异方法中那样尝试使用 SSD(差异平方和),但在像素或块之间,这将严重惩罚较大的差异,因此剩余的图像不会与目标差异太大。您可以尝试使用更直观的图像 space,例如 HSV,这样图像在视觉上会更接近,即使它们在 RGB space.
中更远。我认为比较整个图像的直方图可能过于松懈,因为有许多不同的图像会导致相同的直方图。比较单个像素可能过于严格,图像需要非常精确地对齐以获得低差异,所以除非你非常幸运,否则一切都会得到低适应度值,这样收敛会太慢。我建议您比较重叠块之间的直方图,不要使用所有 256 个级别,只使用大约 16 个级别左右(或使用某种重叠)。
阅读有关 Histogram of oriented gradients (HOG) and other similar techniques to get ideas to improve your fitness function. I took an online course about object recognition in images, Coursera - Deteccion de Objetos by the University of Barcelona 但它是西班牙语的。我很确定你可以找到类似的英语学习资料。
编辑:在尝试更复杂的事情之前,一个好主意是对每个重叠块的平均值进行 SAD 或 SSD(这与强烈模糊参考和生成的图像然后比较像素具有类似的效果,但更快)。适应度函数应该对小的变化有弹性。移动了几个像素或在丢弃低级细节后非常相似的图像应该比非常不同的图像具有更好的适应性,我认为模糊会产生这种效果。