Browse Source

started writing genetic algorithm

main
Thomas Johnson 12 months ago
parent
commit
1c22147a46
  1. 2
      Cargo.toml
  2. 34
      src/genetic.rs
  3. 14
      src/main.rs
  4. 42
      src/map.rs
  5. 23
      src/transform.rs

2
Cargo.toml

@ -5,3 +5,5 @@ edition = "2018"
[dependencies]
image = "0.23"
rand = "0.8"
rand_distr = "0.4"

34
src/genetic.rs

@ -0,0 +1,34 @@
pub struct Arena<T: Genetic> {
pub keep: usize,
pub mutate: usize,
pub breed: usize,
set: Vec<T>,
pub config: T::Configuration,
}
impl<T: Genetic> Arena<T> {
pub fn new(keep: usize, mutate: usize, breed: usize, config: T::Configuration) -> Self {
let mut set = Vec::new();
for _ in 0..keep {
set.push(T::generate(&config));
}
Arena {
keep,
mutate,
breed,
set,
config,
}
}
}
pub trait Genetic {
type Configuration;
fn generate(config: &Self::Configuration) -> Self;
fn mutate(&self, config: &Self::Configuration) -> Self;
fn breed(&self, other: &Self, config: &Self::Configuration) -> Self;
fn compare(&self, other: &Self, config: &Self::Configuration) -> std::cmp::Ordering;
}

14
src/main.rs

@ -1,6 +1,10 @@
#![allow(confusable_idents)]
#![allow(mixed_script_confusables)]
use image::{ImageBuffer, Rgb};
mod transform;
mod genetic;
mod map;
use transform::Transform;
@ -8,15 +12,15 @@ fn main() {
let args: Vec<_> = std::env::args().collect();
let image_in_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = image::open(args.get(1).expect("input file not provided")).expect("could not open input file").to_rgb16();
let dims = image_in_u16.dimensions();
let image_in: ImageBuffer<Rgb<f64>, Vec<f64>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
let image_in: ImageBuffer<Rgb<f32>, Vec<f32>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
let pix = image_in_u16.get_pixel(x, y);
Rgb([pix[0] as f64 / 65535.0, pix[1] as f64 / 65535.0, pix[2] as f64 / 65535.0])
Rgb([pix[0] as f32 / 65535.0, pix[1] as f32 / 65535.0, pix[2] as f32 / 65535.0])
});
let mut image_out: ImageBuffer<Rgb<f64>, Vec<f64>> = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
let mut image_out: ImageBuffer<Rgb<f32>, Vec<f32>> = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
let transform = Transform {
color_matrix: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
from: [(0.0, 0.0), ((dims.0 / 2) as f64, 0.0), (0.0, (dims.1 - 1) as f64)],
to: [(0.0, 0.0), ((dims.0 - 1) as f64, (dims.1 / 2) as f64), (0.0, (dims.1 - 1) as f64)],
from: [(0.0, 0.0), ((dims.0 / 2) as f32, 0.0), (0.0, (dims.1 - 1) as f32)],
to: [(0.0, 0.0), ((dims.0 - 1) as f32, (dims.1 / 2) as f32), (0.0, (dims.1 - 1) as f32)],
};
transform.apply_add(&image_in, &mut image_out, dims);
let image_out_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {

42
src/map.rs

@ -0,0 +1,42 @@
use crate::{transform::Transform, genetic::Genetic};
use rand::{Rng, distributions::Uniform};
use rand_distr::{Poisson};
pub struct Map<R: rand::Rng>
{
transforms: Vec<Transform>,
pd: core::marker::PhantomData<R>,
}
pub fn random_transform<R: rand::Rng>(cfg: &mut MapGeneticConfig<R>) -> Transform {
unimplemented!()
}
pub struct MapGeneticConfig<R: rand::Rng>
{
pub rng: R,
pub dims: (u32, u32),
pub add_mean: usize,
pub rm_mean: usize,
}
impl<R: rand::Rng> Genetic for Map<R>
{
type Configuration = MapGeneticConfig<R>;
fn generate(cfg: &MapGeneticConfig<R>) -> Self {
unimplemented!()
}
fn mutate(&self, cfg: &MapGeneticConfig<R>) -> Self {
unimplemented!()
}
fn breed(&self, other: &Self, config: &Self::Configuration) -> Self {
unimplemented!()
}
fn compare(&self, other: &Self, config: &Self::Configuration) -> std::cmp::Ordering {
unimplemented!()
}
}

23
src/transform.rs

@ -1,16 +1,16 @@
use image::{ImageBuffer, Rgb, GenericImage};
use image::{Rgb, GenericImage};
const NCOLORS: usize = 3;
const OVERSAMPLE_RATE: usize = 4;
pub struct Transform {
pub color_matrix: [f64; NCOLORS * NCOLORS],
pub from: [(f64, f64); 3],
pub to: [(f64, f64); 3],
pub color_matrix: [f32; NCOLORS * NCOLORS],
pub from: [(f32, f32); 3],
pub to: [(f32, f32); 3],
}
impl Transform {
pub fn apply_add<I: GenericImage<Pixel=Rgb<f64>>, O: GenericImage<Pixel=Rgb<f64>>>(&self, input: &I, output: &mut O, dims: (u32, u32)) {
pub fn apply_add<I: GenericImage<Pixel=Rgb<f32>>, O: GenericImage<Pixel=Rgb<f32>>>(&self, input: &I, output: &mut O, dims: (u32, u32)) {
let v1 = (self.from[0].0 - self.from[1].0, self.from[0].1 - self.from[1].1);
let v2 = (self.from[2].0 - self.from[1].0, self.from[2].1 - self.from[1].1);
let v3 = (self.from[0].0 - self.from[2].0, self.from[0].1 - self.from[2].1);
@ -27,23 +27,22 @@ impl Transform {
let sample_rate = lmaxsq.sqrt().ceil() as usize * OVERSAMPLE_RATE;
let twice_area_from = self.from[0].0 * self.from[1].1 + self.from[1].0 * self.from[2].1 + self.from[2].0 * self.from[0].1 - (self.from[0].1 * self.from[1].0 + self.from[1].1 * self.from[2].0 + self.from[2].1 * self.from[0].0);
let twice_area_to = self.to[0].0 * self.to[1].1 + self.to[1].0 * self.to[2].1 + self.to[2].0 * self.to[0].1 - (self.to[0].1 * self.to[1].0 + self.to[1].1 * self.to[2].0 + self.to[2].1 * self.to[0].0);
let scale_ratio = twice_area_to / twice_area_from / (OVERSAMPLE_RATE * OVERSAMPLE_RATE) as f64 * 0.5;
let scale_ratio = twice_area_to / twice_area_from / (OVERSAMPLE_RATE * OVERSAMPLE_RATE) as f32 * 0.5;
// Sample at barycentric coordinates
for α_idx in 0..=sample_rate {
for β_idx in 0..=(sample_rate - α_idx) {
let α = α_idx as f64 * (sample_rate as f64).recip();
let β = β_idx as f64 * (sample_rate as f64).recip();
let α = α_idx as f32 * (sample_rate as f32).recip();
let β = β_idx as f32 * (sample_rate as f32).recip();
let γ = 1.0 - α - β;
// Find absolute coordinates from barycentric
let in_coords = (α * self.from[0].0 + β * self.from[1].0 + γ * self.from[2].0, α * self.from[0].1 + β * self.from[1].1 + γ * self.from[2].1);
let out_coords = (α * self.to[0].0 + β * self.to[1].0 + γ * self.to[2].0, α * self.to[0].1 + β * self.to[1].1 + γ * self.to[2].1);
// let out_coords = (2.0 * out_coords.0, 2.0 * out_coords.1);
// Get input color from pixels near sample
let mut in_pix = [0.0; NCOLORS];
let mut total_area: f64 = 0.0;
let mut total_area: f32 = 0.0;
let in_coords_u32 = (in_coords.0.floor() as u32, in_coords.1.floor() as u32);
let out_coords_u32 = (out_coords.0.floor() as u32, out_coords.1.floor() as u32);
for x in in_coords_u32.0..=in_coords_u32.0 + 1 {
@ -52,7 +51,7 @@ impl Transform {
continue;
}
let val = input.get_pixel(x, y).0;
let area = ((x as f64 - in_coords.0) * (y as f64 - in_coords.1)).abs();
let area = ((x as f32 - in_coords.0) * (y as f32 - in_coords.1)).abs();
for i in 0..NCOLORS {
in_pix[i] += val[i] * area;
}
@ -78,7 +77,7 @@ impl Transform {
continue;
}
let mut pix = output.get_pixel(x, y).0;
let area = ((x as f64 - out_coords.0) * (y as f64 - out_coords.1)).abs();
let area = ((x as f32 - out_coords.0) * (y as f32 - out_coords.1)).abs();
for i in 0..NCOLORS {
pix[i] += color[i] * area;
}

Loading…
Cancel
Save