Libraryless. Click here for Pure Java version (1586L/11K/35K).
!636 !standard functions !quicknew !ctex !* constructor import java.awt.*; import java.awt.image.*; import java.util.List; import javax.imageio.*; !include #2000447 // image classes !include #1000539 // FrameWithImages public class main { static RGBImage originalImage; static int imageWidth = 200; static FrameWithImages frame; // XXX - main reproduce function static Reproducer reproducer = /*new Layers( new RandomSolid()) .add(2, RandomBox.class) .varyBest;*/ //new OptimizeIndividual(new RandomBox()); new ProduceIndividual(new RandomBox()); static abstract class Img { RGBImage img; *(RGBImage *img) {} int getWidth() { return img.getWidth(); } int getHeight() { return img.getHeight(); } //abstract void setPixel(int x, int y, int rgb); abstract void setPixel(int x, int y, RGB rgb);/* { setPixel(x, y, rgb.asInt()); }*/ } static class Painting extends Img { *(RGBImage img) { super(img); } void setPixel(int x, int y, RGB rgb) { img.setPixel(x, y, rgb); } } static class Diffing extends Img { int pixelsDiffed; double totalDiff; double[] diffed; *(RGBImage img) { super(img); diffed = new double[img.getWidth()*img.getHeight()]; for (int i = 0; i < diffed.length; i++) diffed[i] = -1; } void setPixel(int x, int y, RGB rgb) { int w = img.getWidth(), h = img.getHeight(); if (x < 0 || y < 0 || x >= w || y >= h) return; double old = diffed[x+y*w]; if (old >= 0) totalDiff -= old; else pixelsDiffed++; double diff = pixelDiff(img.getPixel(x, y), rgb); diffed[x+y*w] = diff; totalDiff += diff; } double getScore() { int totalPixels = img.getWidth()*img.getHeight(); int emptyPixels = totalPixels-pixelsDiffed; double innerQuality = totalDiff/Math.max(pixelsDiffed, 1); double outerQuality = 0.8; // makes objects shrink or grow double result = mix(innerQuality, outerQuality, emptyPixels/(double) totalPixels); //System.out.println("inner=" + innerQuality + ", outer=" + outerQuality + ", pixels diffed=" + pixelsDiffed + ", result=" + result); return result; } } 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(Img 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(Img 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; *() {} *(RGB *col) {} Solid copy() { new Solid p; p.col = col; return p; } public String toString() { return "Solid " + col; } void renderOn(Img 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; new Solid p; 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; *(Reproducer *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); Painting img = new Painting(image); for (int i = 0; i < list.length; i++) list[i].renderOn(img); return image; } void vary() { int i = random(list.length); if (random(2) == 0 || myMaker == null) { //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); *(OverlayReproducer... *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); } static class ProduceIndividual implements Reproducer { OverlayReproducer producer; *(OverlayReproducer *producer) {} public Params reproduce(RGBImage original) { Overlay overlay = producer.reproduce(original); Layered result = new Layered(null, new Solid(new RGB(Color.white)), overlay); result.originalImage = original; return result; } } static class OptimizeIndividual implements Reproducer { OverlayReproducer producer; double bestScore; Overlay best; *(OverlayReproducer *producer) {} public Params reproduce(RGBImage original) { Overlay overlay = producer.reproduce(original); //System.out.println("overlay: " + overlay); double score = scoreOverlay(overlay, original); if (best == null || score <= bestScore) { best = overlay; bestScore = score; } Layered result = new Layered(null, new Solid(new RGB(Color.black)), best); result.originalImage = original; return result; } } static double scoreOverlay(Overlay overlay, RGBImage original) { Diffing d = new Diffing(original); overlay.renderOn(d); return d.getScore(); } static class HoldBest implements Reproducer { Reproducer base; Params best; *(Reproducer *base) {} public Params reproduce(RGBImage original) { Params p = base.reproduce(original); if (best == null || p.isBetterThan(best)) best = p; return best; } } static class BestHolder { Params best; public boolean receive(Params p) { if (best == null || p.isBetterThan(best)) { best = p; return true; } return false; } } 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; frame = new FrameWithImages(3); frame.frame.setVisible(true); exitOnFrameClose(frame.frame); new Thread() { public void run() { originalImage = loadImage(_imageID); originalImage = resizeToWidth(originalImage, imageWidth); frame.setImage(frame.n-1, originalImage); reproduceOpenEnd(originalImage); } }.start(); } static void reproduceOpenEnd(RGBImage original) { new BestHolder bestHolder; long lastPrint = 0, lastN = 0; for (long ntry = 1; ; ntry++) { Params p = reproduce(original); frame.setImage(0, p.getImage()); if (bestHolder.receive(p)) frame.setImage(1, bestHolder.best.getImage()); 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)"; System.out.println(s + ", score: " + formatDouble(p.getScore()*100, 2) + "%, structure size: " + structureSize(p, Params.class)); } if (p != null && p.getScore() == 0.0) break; // perfect result, end } } !include #1000522 !include #1000540 // box painting function }
Began life as a copy of #726
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: | #1000529 |
Snippet name: | Reproducing with boxes v4 (developing) |
Eternal ID of this version: | #1000529/1 |
Text MD5: | 2265e47b036c0f46fb8d5f9bb038e4d0 |
Transpilation MD5: | 5997f2504c2b8074f2571eba69062ef3 |
Author: | stefan |
Category: | |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2015-08-28 11:43:53 |
Source code size: | 12686 bytes / 480 lines |
Pitched / IR pitched: | No / Yes |
Views / Downloads: | 629 / 667 |
Referenced in: | [show references] |