Skip to content

Instantly share code, notes, and snippets.

@jes
Created September 8, 2021 12:24
Show Gist options
  • Save jes/aff9bf4b09e8ac75d78691d9d9403fec to your computer and use it in GitHub Desktop.
Save jes/aff9bf4b09e8ac75d78691d9d9403fec to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
# neural net to represent an image by mapping (x,y) => (r,g,b)
# James Stanley 2021
# inspired by https://news.ycombinator.com/item?id=28448626
use strict;
use warnings;
use AI::FANN qw(:all);
use GD;
my $usage = "usage: img2nn IMGFILE\n";
my $imgfile = shift or die $usage;
my $img = GD::Image->new($imgfile)
or die "can't open $imgfile: $!\n";
my ($w,$h) = $img->getBounds;
my @train;
for my $y (0 .. $h-1) {
for my $x (0 .. $w-1) {
my $col = $img->getPixel($x,$y);
my ($r,$g,$b) = $img->rgb($col);
$r = $r/255;
$g = $g/255;
$b = $b/255;
push @train, [($x-$w/2)/($w/2),($y-$h/2)/($h/2)], [$r,$g,$b];
}
}
my $traindata = AI::FANN::TrainData->new(@train);
my $ann = AI::FANN->new_standard(2, 3,15,3, 3);
$ann->hidden_activation_function(FANN_GAUSSIAN_SYMMETRIC);
$ann->output_activation_function(FANN_ELLIOT);
my $max_epochs = 40;
my $epochs_between_reports = 100;
my $desired_error = 0;
saveimg($ann, 0);
for my $i (1..1000) {
$max_epochs = int((4**($i/250)))+1; # get frames more frequently at the start, while more is changing
$ann->train_on_data($traindata, $max_epochs, $epochs_between_reports, $desired_error);
saveimg($ann, $i);
}
sub saveimg {
my ($ann, $i) = @_;
my ($w,$h) = (200,200);
my $img = GD::Image->new($w,$h,1);
for my $y (0 .. $h-1) {
for my $x (0 .. $w-1) {
my ($r,$g,$b) = @{ $ann->run([($x-$w/2)/($w/2),($y-$h/2)/($h/2)]) };
$r = $r * 255;
$g = $g * 255;
$b = $b * 255;
$r = 0 if $r < 0;
$g = 0 if $g < 0;
$b = 0 if $b < 0;
$img->setPixel($x, $y, $img->colorAllocate($r,$g,$b));
}
}
open(my $fh, '>', sprintf("anim/%04d.png", $i))
or die "can't write under anim/: $!";
print $fh $img->png;
close $fh;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment