Compare images in fitness function and benchmark them
This commit is contained in:
parent
0183d4737c
commit
d38e45dac8
7 changed files with 189 additions and 11 deletions
2
Makefile
2
Makefile
|
|
@ -8,7 +8,7 @@ SOURCEFILES = cpp
|
||||||
SRCDIR = src
|
SRCDIR = src
|
||||||
TMPDIR = build
|
TMPDIR = build
|
||||||
TARGET = gross
|
TARGET = gross
|
||||||
FILES = Chromosome main
|
FILES = Chromosome Fitness main
|
||||||
|
|
||||||
#SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES))
|
#SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES))
|
||||||
OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(FILES))
|
OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(FILES))
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@
|
||||||
|
|
||||||
// try isampler2D, ivec4 etc.? Probably not
|
// try isampler2D, ivec4 etc.? Probably not
|
||||||
uniform vec2 size;
|
uniform vec2 size;
|
||||||
uniform vec2 offs;
|
// uniform vec2 offs;
|
||||||
uniform sampler2D base;
|
uniform sampler2D base;
|
||||||
uniform sampler2D curr;
|
uniform sampler2D curr;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec2 pos = (gl_FragCoord.xy-offs)/size;
|
vec2 pos = gl_FragCoord.xy/size;
|
||||||
pos.y = 1.0 - pos.y;
|
|
||||||
vec4 color = texture2D(curr, pos);
|
vec4 color = texture2D(curr, pos);
|
||||||
|
pos.y = 1.0 - pos.y;
|
||||||
vec4 basecolor = texture2D(base, pos);
|
vec4 basecolor = texture2D(base, pos);
|
||||||
color.xyz = abs(color.xyz - basecolor.xyz);
|
color.rgb = abs(color.rgb - basecolor.rgb);
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,11 @@ void Chromosome::mutate()
|
||||||
|
|
||||||
void Chromosome::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
void Chromosome::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||||
{
|
{
|
||||||
|
this->circle.setPosition(0, 0);
|
||||||
|
this->circle.setRadius(Chromosome::size.x + Chromosome::size.y);
|
||||||
|
this->circle.setOrigin(Chromosome::size);
|
||||||
|
this->circle.setFillColor(sf::Color::White);
|
||||||
|
target.draw(this->circle, states);
|
||||||
for (auto gene : this->genes) {
|
for (auto gene : this->genes) {
|
||||||
this->circle.setPosition(gene.position);
|
this->circle.setPosition(gene.position);
|
||||||
this->circle.setRadius(gene.radius);
|
this->circle.setRadius(gene.radius);
|
||||||
|
|
@ -115,9 +120,15 @@ size_t Chromosome::length()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Chromosome::maxRadius()
|
||||||
|
{
|
||||||
|
return std::min(Chromosome::size.x, Chromosome::size.y)/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Chromosome::Gene Chromosome::randomGene()
|
Chromosome::Gene Chromosome::randomGene()
|
||||||
{
|
{
|
||||||
float max_radius = std::min(Chromosome::size.x, Chromosome::size.y)/4;
|
float max_radius = this->maxRadius();
|
||||||
std::uniform_real_distribution<> xdist(0, Chromosome::size.x);
|
std::uniform_real_distribution<> xdist(0, Chromosome::size.x);
|
||||||
std::uniform_real_distribution<> ydist(0, Chromosome::size.y);
|
std::uniform_real_distribution<> ydist(0, Chromosome::size.y);
|
||||||
std::uniform_real_distribution<> rdist(0, sqrt(max_radius));
|
std::uniform_real_distribution<> rdist(0, sqrt(max_radius));
|
||||||
|
|
@ -125,7 +136,12 @@ Chromosome::Gene Chromosome::randomGene()
|
||||||
|
|
||||||
sf::Vector2f position(xdist(*Chromosome::re), ydist(*Chromosome::re));
|
sf::Vector2f position(xdist(*Chromosome::re), ydist(*Chromosome::re));
|
||||||
float radius = (pow(rdist(*Chromosome::re), 2));
|
float radius = (pow(rdist(*Chromosome::re), 2));
|
||||||
sf::Color color(colordist(*Chromosome::re), colordist(*Chromosome::re), colordist(*Chromosome::re), 50);
|
sf::Color color(
|
||||||
|
colordist(*Chromosome::re),
|
||||||
|
colordist(*Chromosome::re),
|
||||||
|
colordist(*Chromosome::re),
|
||||||
|
150
|
||||||
|
);
|
||||||
|
|
||||||
Chromosome::Gene gene;
|
Chromosome::Gene gene;
|
||||||
gene.position = position;
|
gene.position = position;
|
||||||
|
|
@ -139,7 +155,7 @@ Chromosome::Gene Chromosome::randomGene()
|
||||||
void Chromosome::mutateGene(Gene& gene)
|
void Chromosome::mutateGene(Gene& gene)
|
||||||
{
|
{
|
||||||
std::uniform_int_distribution<> booldist(0, 1);
|
std::uniform_int_distribution<> booldist(0, 1);
|
||||||
float max_radius = std::min(Chromosome::size.x, Chromosome::size.y)/4;
|
float max_radius = this->maxRadius();
|
||||||
|
|
||||||
if (booldist(*Chromosome::re)) { // position
|
if (booldist(*Chromosome::re)) { // position
|
||||||
std::normal_distribution<> posdist(0, Chromosome::stddev_position);
|
std::normal_distribution<> posdist(0, Chromosome::stddev_position);
|
||||||
|
|
@ -158,7 +174,7 @@ void Chromosome::mutateGene(Gene& gene)
|
||||||
if (booldist(*Chromosome::re)) { // radius
|
if (booldist(*Chromosome::re)) { // radius
|
||||||
std::normal_distribution<> raddist(0, Chromosome::stddev_radius);
|
std::normal_distribution<> raddist(0, Chromosome::stddev_radius);
|
||||||
gene.radius = std::clamp<float>(
|
gene.radius = std::clamp<float>(
|
||||||
gene.radius + raddist(*Chromosome::re)*max_radius,
|
gene.radius + pow(raddist(*Chromosome::re)*sqrt(max_radius), 2),
|
||||||
0,
|
0,
|
||||||
max_radius
|
max_radius
|
||||||
);
|
);
|
||||||
|
|
@ -169,6 +185,7 @@ void Chromosome::mutateGene(Gene& gene)
|
||||||
gene.color.r = std::clamp<unsigned int>(gene.color.r + coldist(*Chromosome::re), 0, 255);
|
gene.color.r = std::clamp<unsigned int>(gene.color.r + coldist(*Chromosome::re), 0, 255);
|
||||||
gene.color.g = std::clamp<unsigned int>(gene.color.g + coldist(*Chromosome::re), 0, 255);
|
gene.color.g = std::clamp<unsigned int>(gene.color.g + coldist(*Chromosome::re), 0, 255);
|
||||||
gene.color.b = std::clamp<unsigned int>(gene.color.b + coldist(*Chromosome::re), 0, 255);
|
gene.color.b = std::clamp<unsigned int>(gene.color.b + coldist(*Chromosome::re), 0, 255);
|
||||||
|
gene.color.a = std::clamp<unsigned int>(gene.color.a + coldist(*Chromosome::re), 0, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ protected:
|
||||||
sf::Color color;
|
sf::Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float maxRadius();
|
||||||
|
|
||||||
Gene randomGene();
|
Gene randomGene();
|
||||||
void mutateGene(Gene& gene);
|
void mutateGene(Gene& gene);
|
||||||
|
|
||||||
|
|
|
||||||
63
src/Fitness.cpp
Normal file
63
src/Fitness.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "Fitness.hpp"
|
||||||
|
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Fitness::Fitness() {}
|
||||||
|
|
||||||
|
|
||||||
|
Fitness::Fitness(sf::Texture target, float scale)
|
||||||
|
{
|
||||||
|
this->target = target;
|
||||||
|
|
||||||
|
sf::Vector2u targetSize = this->target.getSize();
|
||||||
|
this->tex.create(targetSize.x, targetSize.y);
|
||||||
|
this->sprite.setTexture(this->tex.getTexture());
|
||||||
|
this->comp.create(targetSize.x*scale, targetSize.y*scale);
|
||||||
|
// this->comp.setSmooth(true);
|
||||||
|
|
||||||
|
this->view.reset(sf::FloatRect(0, 0, targetSize.x, targetSize.y));
|
||||||
|
this->view.setViewport(sf::FloatRect(0, 0, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Fitness::loadShader(std::string filename)
|
||||||
|
{
|
||||||
|
this->compshdr.loadFromFile(filename, sf::Shader::Fragment);
|
||||||
|
if (this->compshdr.isAvailable()) {
|
||||||
|
this->compshdr.setUniform("base", this->target);
|
||||||
|
this->compshdr.setUniform("curr", this->tex.getTexture());
|
||||||
|
this->compshdr.setUniform("size", sf::Vector2f(this->comp.getSize()));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double Fitness::of(Chromosome chr)
|
||||||
|
{
|
||||||
|
// first, render a reduced, shaderized version to RenderTextures
|
||||||
|
this->tex.clear();
|
||||||
|
this->tex.draw(chr);
|
||||||
|
this->tex.display();
|
||||||
|
|
||||||
|
this->comp.clear(sf::Color::Blue);
|
||||||
|
this->comp.setView(this->view);
|
||||||
|
this->comp.draw(this->sprite, &this->compshdr);
|
||||||
|
// this->comp.draw(this->sprite);
|
||||||
|
this->comp.display();
|
||||||
|
|
||||||
|
// then, download the result as an image and add the pixels
|
||||||
|
sf::Image image = this->comp.getTexture().copyToImage();
|
||||||
|
sf::Vector2u size = image.getSize();
|
||||||
|
double fitness = 0;
|
||||||
|
for (unsigned int x=0; x<size.x; ++x) {
|
||||||
|
for (unsigned int y=0; y<size.y; ++y) {
|
||||||
|
sf::Color color = image.getPixel(x, y);
|
||||||
|
fitness += color.r + color.g + color.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fitness;
|
||||||
|
}
|
||||||
25
src/Fitness.hpp
Normal file
25
src/Fitness.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Chromosome.hpp"
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Fitness
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Fitness();
|
||||||
|
Fitness(sf::Texture target, float scale=0.5);
|
||||||
|
bool loadShader(std::string filename);
|
||||||
|
|
||||||
|
double of(Chromosome chr);
|
||||||
|
|
||||||
|
sf::Texture target; // base image to compare against
|
||||||
|
sf::RenderTexture tex; // big RenderWindow containg the Chromosome to be evaluated
|
||||||
|
sf::RenderTexture comp; // smaller RenderWindow which is downloaded as Image
|
||||||
|
|
||||||
|
private:
|
||||||
|
sf::Sprite sprite; // sprite to render tex to comp
|
||||||
|
sf::Shader compshdr; // shader to perform pixel-wise image diff with
|
||||||
|
sf::View view; // reduces tex to comp size while drawing
|
||||||
|
};
|
||||||
75
src/main.cpp
75
src/main.cpp
|
|
@ -2,6 +2,7 @@
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
#include "Chromosome.hpp"
|
#include "Chromosome.hpp"
|
||||||
|
#include "Fitness.hpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UI Modes:
|
* UI Modes:
|
||||||
|
|
@ -109,11 +110,12 @@ int main() {
|
||||||
const float winW = 480;
|
const float winW = 480;
|
||||||
const float winH = 480;
|
const float winH = 480;
|
||||||
std::mt19937_64 randomEngine;
|
std::mt19937_64 randomEngine;
|
||||||
randomEngine.seed(1);
|
randomEngine.seed(1337);
|
||||||
|
|
||||||
sf::RenderWindow window(sf::VideoMode(winW, winH), "gross");
|
sf::RenderWindow window(sf::VideoMode(winW, winH), "gross");
|
||||||
window.setMouseCursorVisible(false); // hide the cursor
|
window.setMouseCursorVisible(false); // hide the cursor
|
||||||
|
|
||||||
|
/* test mating
|
||||||
Chromosome::size = sf::Vector2f(winW/2, winH/2);
|
Chromosome::size = sf::Vector2f(winW/2, winH/2);
|
||||||
Chromosome::re = &randomEngine;
|
Chromosome::re = &randomEngine;
|
||||||
Chromosome father, mother, child, monster;
|
Chromosome father, mother, child, monster;
|
||||||
|
|
@ -125,6 +127,37 @@ int main() {
|
||||||
vmother.setViewport(sf::FloatRect(.5, 0, .5, .5));
|
vmother.setViewport(sf::FloatRect(.5, 0, .5, .5));
|
||||||
vchild.setViewport(sf::FloatRect(0, .5, .5, .5));
|
vchild.setViewport(sf::FloatRect(0, .5, .5, .5));
|
||||||
vmonster.setViewport(sf::FloatRect(.5, .5, .5, .5));
|
vmonster.setViewport(sf::FloatRect(.5, .5, .5, .5));
|
||||||
|
*/
|
||||||
|
|
||||||
|
Chromosome::size = sf::Vector2f(winW/2, winH/2);
|
||||||
|
Chromosome::re = &randomEngine;
|
||||||
|
Chromosome target, chr;
|
||||||
|
|
||||||
|
sf::View vtarget(sf::FloatRect(0, 0, winW/2, winH/2));
|
||||||
|
sf::View vchr(sf::FloatRect(0, 0, winW/2, winH/2));
|
||||||
|
sf::View vtex(sf::FloatRect(0, 0, winW/2, winH/2));
|
||||||
|
sf::View vcomp(sf::FloatRect(0, 0, winW/2, winH/2));
|
||||||
|
vtarget.setViewport(sf::FloatRect(0, 0, 0.5, 0.5));
|
||||||
|
vchr.setViewport(sf::FloatRect(0.5, 0, 0.5, 0.5));
|
||||||
|
vtex.setViewport(sf::FloatRect(0, 0.5, 0.5, 0.5));
|
||||||
|
vcomp.setViewport(sf::FloatRect(0.5, 0.5, 0.5, 0.5));
|
||||||
|
for (int i=0; i<1000; ++i) target.mutate();
|
||||||
|
|
||||||
|
sf::RenderTexture targettex;
|
||||||
|
targettex.create(winW/2, winH/2);
|
||||||
|
// targettex.clear(sf::Color::White);
|
||||||
|
targettex.clear();
|
||||||
|
targettex.draw(target);
|
||||||
|
targettex.display();
|
||||||
|
|
||||||
|
Fitness fitn(targettex.getTexture(), 1);
|
||||||
|
if (!fitn.loadShader("compare.glsl")) {
|
||||||
|
std::cout << "Shader not loaded" << std::endl;
|
||||||
|
return 123;
|
||||||
|
}
|
||||||
|
sf::Sprite starget(fitn.target);
|
||||||
|
sf::Sprite stex(fitn.tex.getTexture());
|
||||||
|
sf::Sprite scomp(fitn.comp.getTexture());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// load images
|
// load images
|
||||||
|
|
@ -176,6 +209,7 @@ int main() {
|
||||||
while (window.pollEvent(event)) {
|
while (window.pollEvent(event)) {
|
||||||
// Exit the app when a key is pressed
|
// Exit the app when a key is pressed
|
||||||
if (event.type == sf::Event::KeyPressed) {
|
if (event.type == sf::Event::KeyPressed) {
|
||||||
|
/* test mating
|
||||||
father = Chromosome();
|
father = Chromosome();
|
||||||
// mother = Chromosome();
|
// mother = Chromosome();
|
||||||
for (int i=0; i<1000; ++i) {
|
for (int i=0; i<1000; ++i) {
|
||||||
|
|
@ -195,6 +229,17 @@ int main() {
|
||||||
std::cout << "mother size: " << mother.length() << std::endl;
|
std::cout << "mother size: " << mother.length() << std::endl;
|
||||||
std::cout << "child size: " << child.length() << std::endl;
|
std::cout << "child size: " << child.length() << std::endl;
|
||||||
std::cout << "monster size: " << monster.length() << std::endl;
|
std::cout << "monster size: " << monster.length() << std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
chr = target;
|
||||||
|
// for (int i=0; i<20; ++i) {
|
||||||
|
chr.mutate();
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::cout << "----------SIZES----------" << std::endl;
|
||||||
|
std::cout << "target size: " << target.length() << std::endl;
|
||||||
|
std::cout << "chr size: " << chr.length() << std::endl;
|
||||||
|
std::cout << "fitness: " << fitn.of(chr) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,13 +249,39 @@ int main() {
|
||||||
// sf::Vector2i mousePos = sf::Mouse::getPosition(window);
|
// sf::Vector2i mousePos = sf::Mouse::getPosition(window);
|
||||||
// shader.setParameter("mouse", sf::Vector2f(mousePos.x, mousePos.y - winH));
|
// shader.setParameter("mouse", sf::Vector2f(mousePos.x, mousePos.y - winH));
|
||||||
|
|
||||||
// Draw the sprites
|
/* test mating
|
||||||
window.clear();
|
window.clear();
|
||||||
window.setView(vfather); window.draw(father);
|
window.setView(vfather); window.draw(father);
|
||||||
window.setView(vmother); window.draw(mother);
|
window.setView(vmother); window.draw(mother);
|
||||||
window.setView(vchild); window.draw(child);
|
window.setView(vchild); window.draw(child);
|
||||||
window.setView(vmonster); window.draw(monster);
|
window.setView(vmonster); window.draw(monster);
|
||||||
window.display();
|
window.display();
|
||||||
|
*/
|
||||||
|
|
||||||
|
// window.clear(sf::Color::White)
|
||||||
|
|
||||||
|
window.clear();
|
||||||
|
window.setView(vtarget); window.draw(starget);
|
||||||
|
window.setView(vchr); window.draw(chr);
|
||||||
|
window.setView(vtex); window.draw(stex);
|
||||||
|
window.setView(vcomp); window.draw(scomp);
|
||||||
|
window.display();
|
||||||
|
|
||||||
|
/* benchmark
|
||||||
|
sf::Clock clk;
|
||||||
|
clk.restart(); // start the timer
|
||||||
|
for (int h=0; h<10000; ++h) {
|
||||||
|
chr = target;
|
||||||
|
// for (int i=0; i<20; ++i) {
|
||||||
|
chr.mutate();
|
||||||
|
// }
|
||||||
|
|
||||||
|
fitn.of(chr);
|
||||||
|
// std::cout << fitn.of(chr) << "\n";
|
||||||
|
}
|
||||||
|
std::cout << "10000 images: " << clk.getElapsedTime().asSeconds() << std::endl;
|
||||||
|
return 2;
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
window.draw(sprbase);
|
window.draw(sprbase);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue