Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

367
LINES

< > BotCompany Repo | #724 // Reproducing with boxes

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (8633L/57K/207K).

!7

!include #1000522 // helper functions

static RGBImage originalImage;
static int imageWidth = 200;

// XXX - main reproduce function
static Reproducer reproducer =
  new Layers(
    new RandomSolid())
    .add(2, RandomBox.class)
  .varyBest;


static abstract class Base {
  abstract Base copy();
  
  abstract void vary();
  
  Base copyVary() {
    Base copy = copy();
    copy.vary();
    return copy;
  }
}

static abstract class Overlay extends Base {
  abstract Overlay copy();
  abstract void renderOn(RGBImage image);
}

// Params must be immutable!
static abstract class Params extends Base {
  RGBImage originalImage;
  abstract Params copy();
  abstract RGBImage render();

  void baseClone(Params p) {
    p.originalImage = originalImage;
  }
  
  RGBImage rendered;
  RGBImage getImage() {
    if (rendered == null)
      rendered = render();
    return rendered;
  }
  
  double score = 2.0;
  double getScore() {
    if (score == 2.0)
      score = calcScore();
    return score;
  }
  
  double calcScore() {
    return diff(originalImage, getImage());
  }
  
  boolean isBetterThan(Params p) {
    return getScore() < p.getScore();
  }
}

static class Box extends Overlay {
  double cx, cy, w, h;
  RGB color;

  Box copy() {
    Box p = new Box();
    p.cx = cx;
    p.cy = cy;
    p.w = w;
    p.h = h;
    p.color = color;
    return p;
  }
  
  public String toString() {
    return "Box " + cx + " " + cy + " " + w + " " + h + " " + color;
  }

  void renderOn(RGBImage image) {
    box(image, this);
  }
  
  void vary() {
    int s = random(5);
    if (s == 0)
      cx = vary01(cx);
    else if (s == 1)
      cy = vary01(cy);
    else if (s == 2)
      w = vary01(w);
    else if (s == 3)
      h = vary01(h);
    else
      color = varyColor(color);
  }
}

static class Solid extends Overlay {
  RGB col;
  
  Solid copy() {
    Solid p = new Solid();
    p.col = col;
    return p;
  }
  
  public String toString() {
    return "Solid " + col;
  }

  void renderOn(RGBImage image) {
    int w = image.getWidth(), h = image.getHeight();
    for (int y = 0; y < h; y++)
      for (int x = 0; x < w; x++)
        image.setPixel(x, y, col);
  }
  
  void vary() {
    col = varyColor(col);
  }
}

interface Reproducer {
  public Params reproduce(RGBImage original);
}

interface OverlayReproducer {
  public Overlay reproduce(RGBImage original);
}

static class RandomBox implements OverlayReproducer {
  int n = -1;
  public Overlay reproduce(RGBImage original) {
    ++n;
    new Box p;
    p.cx = random();
    p.cy = random();
    p.w = random()*0.1;
    p.h = random()*0.1;
    if (n % 2 == 0)
      p.color = randomColor();
    else
      p.color = probeRandomPixel(original);
    return p;
  }
}

static class RandomSolid implements OverlayReproducer {
  int n = -1;
  public Overlay reproduce(RGBImage original) {
    ++n;
    Solid p = new Solid();
    if (n % 2 == 0) {
      p.col = randomColor();
    } else {
      p.col = probeRandomPixel(original);
    }
    return p;
  }
}

static class WhiteSolid implements OverlayReproducer {
  public Overlay reproduce(RGBImage original) {
    Solid p = new Solid();
    p.col = new RGB(Color.white);
    return p;
  }
}

static class VaryBest implements Reproducer {
  Reproducer base;
  Params best;
  
  VaryBest(Reproducer base) {
    this.base = base;
  }
  
  public Params reproduce(RGBImage original) {
    Params p = base.reproduce(original);
    if (best == null || p.isBetterThan(best))
      best = p;
    Params variation = (Params) best.copyVary();
    //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
    if (variation.isBetterThan(best)) {
      //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
      best = variation;
    }
    return best;
  }
  
  void reset() {
    best = null;
  }
}

static class Layered extends Params {
  Layers myMaker;
  Overlay[] list;
  
  Layered(Layers myMaker, Overlay[] list) {
    this.myMaker = myMaker;
    this.list = list;
  }
  
  Layered copy() {
    Layered p = new Layered(myMaker, new Overlay[list.length]);
    baseClone(p);
    for (int i = 0; i < list.length; i++)
      p.list[i] = (Overlay) list[i].copy();
    return p;
  }
  
  public String toString() {
    StringBuilder buf = new StringBuilder("layered{");
    for (int i = 0; i < list.length; i++) {
      if (i != 0)
        buf.append(", ");
      buf.append(list[i]);
    }
    return buf + "}";
  }

  RGBImage render() {
    RGBImage image = new RGBImage(originalImage.getWidth(), originalImage.getHeight(), Color.white);
    for (int i = 0; i < list.length; i++)
      list[i].renderOn(image);
    return image;
  }
  
  void vary() {
    int i = random(list.length);
    if (random(2) == 0) {
      //System.out.println("Varying layer " + i);
      list[i] = (Overlay) list[i].copyVary();
    } else {
      //double score = getScore();
      OverlayReproducer maker = myMaker.list[i];
      list[i] = maker.reproduce(originalImage);
      //System.out.println("Exchanging layer " + i + " from " + maker + ", improvement: " + (score-getFreshScore()));
    }
  }
}

static class Layers implements Reproducer {
  OverlayReproducer[] list;
  long ntry = -1;
  int stepTime = 0/*500*/;
  VaryBest varyBest = new VaryBest(this);
  
  Layers(OverlayReproducer... list) {
    this.list = list;
  }
  
  Layers add(int n, Class<? extends OverlayReproducer> xClass) ctex {
    OverlayReproducer l[] = new OverlayReproducer[list.length+n];
    System.arraycopy(list, 0, l, 0, list.length);
    for (int i = 0; i < n; i++)
      l[list.length+i] = xClass.newInstance();
    list = l;
    return this;
  }
  
  public Params reproduce(RGBImage original) {
    ++ntry;
    int n = this.list.length;
    if (stepTime != 0) {
      // build up image gradually to optimize lower layers first
      n = (int) Math.min(n, ntry/stepTime+1);
      varyBest.reset();
    }
    Overlay[] list = new Overlay[n];
    for (int i = 0; i < n; i++)
      list[i] = this.list[i].reproduce(original);
    Layered result = new Layered(this, list);
    result.originalImage = original;
    return result;
  }
}

static Params reproduce(RGBImage original) {
  int w = original.getWidth(), h = original.getHeight();
  return reproducer.reproduce(original);
}

psvm {
  String imageID = "#1000332"; // Picture of two coins
  
  for (int i = 0; i < args.length; i++) {
    String arg = args[i];
    if (arg.equals("width"))
      imageWidth = Integer.parseInt(args[++i]);
    else if (isSnippetID(arg))
      imageID = arg;
  }
  
  final String _imageID = imageID;
  
  JFrame frame = new JFrame("A JavaX Frame");
  
  JPanel grid = new JPanel(new GridLayout(2, 1));
  
  final ImageSurface imageSurface = new ImageSurface();
  final ImageSurface original = new ImageSurface();
  grid.add(imageSurface);
  grid.add(original);
  
  frame.add(grid);
  frame.setBounds(100, 100, 100+imageWidth+20, 300);
  frame.setVisible(true);
  exitOnFrameClose(frame);
  
  new Thread() {
    public void run() {
      originalImage = loadImage(_imageID);
      originalImage = resizeToWidth(originalImage, imageWidth);
      original.setImage(originalImage);
      
      reproduceOpenEnd(originalImage, imageSurface);
    }
  }.start();
}

static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) {
  Params best = null;
  long lastPrint = 0, lastN = 0;
  for (long ntry = 1; ; ntry++) {
    long now = System.currentTimeMillis();
    if (now >= lastPrint+1000) {
      long tps = (ntry-lastN)*1000/(now-lastPrint);
      lastPrint = now;
      lastN = ntry;
      String s = "Try " + ntry + " (" + tps + "/s)";
      if (best == null)
        System.out.println(s);
      else {
        System.out.println("Best: " + best);
        System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class));
      }
    }
    Params p = reproduce(original);
    if (best == null || p != null && p.getScore() < best.getScore()) {
      //System.out.println("New best! " + p.getScore());
      best = p;
      imageSurface.setImage(p.getImage());
    }
    
    if (p != null && p.getScore() == 0.0)
      break;
  }
}

static void box(RGBImage img, Box p) {
  int w = img.getWidth(), h = img.getHeight();
  double x1 = normalize(p.cx-p.w), x2 = normalize(p.cx+p.w);
  double y1 = normalize(p.cy-p.h), y2 = normalize(p.cy+p.h);
  int xx1 = round(x1*(w-1)), xx2 = round(x2*(w-1));
  int yy1 = round(y1*(h-1)), yy2 = round(y2*(h-1));
  
  for (int yy = yy1; yy <= yy2; yy++)
    for (int xx = xx1; xx <= xx2; xx++)
      img.setPixel(xx, yy, p.color);
}

Author comment

Began life as a copy of #671

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, teubizvjbppd, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #724
Snippet name: Reproducing with boxes
Eternal ID of this version: #724/2
Text MD5: 1956f845025d299caeeff78cf968c0f4
Transpilation MD5: 4bf9f0b903b28d9af03f523d00816e8c
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2018-05-06 16:26:21
Source code size: 9043 bytes / 367 lines
Pitched / IR pitched: No / No
Views / Downloads: 611 / 645
Version history: 1 change(s)
Referenced in: [show references]