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

480
LINES

< > BotCompany Repo | #1000529 // Reproducing with boxes v4 (developing)

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

Libraryless. Click here for Pure Java version (1586L/11K/35K).

1  
!636
2  
!standard functions
3  
!quicknew
4  
!ctex
5  
!* constructor
6  
7  
import java.awt.*;
8  
import java.awt.image.*;
9  
import java.util.List;
10  
import javax.imageio.*;
11  
12  
!include #2000447 // image classes
13  
!include #1000539 // FrameWithImages
14  
15  
public class main {
16  
  static RGBImage originalImage;
17  
  static int imageWidth = 200;
18  
  
19  
  static FrameWithImages frame;
20  
  
21  
  // XXX - main reproduce function
22  
  static Reproducer reproducer =
23  
    /*new Layers(
24  
      new RandomSolid())
25  
      .add(2, RandomBox.class)
26  
    .varyBest;*/
27  
    //new OptimizeIndividual(new RandomBox());
28  
    new ProduceIndividual(new RandomBox());
29  
    
30  
  static abstract class Img {
31  
    RGBImage img;
32  
    
33  
    *(RGBImage *img) {}
34  
    
35  
    int getWidth() { return img.getWidth(); }
36  
    int getHeight() { return img.getHeight(); }
37  
    //abstract void setPixel(int x, int y, int rgb);
38  
    
39  
    abstract void setPixel(int x, int y, RGB rgb);/* {
40  
      setPixel(x, y, rgb.asInt());
41  
    }*/
42  
  }
43  
  
44  
  static class Painting extends Img {
45  
    *(RGBImage img) { super(img); }
46  
    
47  
    void setPixel(int x, int y, RGB rgb) {
48  
      img.setPixel(x, y, rgb);
49  
    }
50  
  }
51  
    
52  
  static class Diffing extends Img {
53  
    int pixelsDiffed;
54  
    double totalDiff;
55  
    double[] diffed;
56  
    
57  
    *(RGBImage img) {
58  
      super(img);
59  
      diffed = new double[img.getWidth()*img.getHeight()];
60  
      for (int i = 0; i < diffed.length; i++) diffed[i] = -1;
61  
    }
62  
63  
    void setPixel(int x, int y, RGB rgb) {
64  
      int w = img.getWidth(), h = img.getHeight();
65  
      if (x < 0 || y < 0 || x >= w || y >= h) return;
66  
      double old = diffed[x+y*w];
67  
      if (old >= 0)
68  
        totalDiff -= old;
69  
      else
70  
        pixelsDiffed++;
71  
      double diff = pixelDiff(img.getPixel(x, y), rgb);
72  
      diffed[x+y*w] = diff;
73  
      totalDiff += diff;
74  
    }
75  
    
76  
    double getScore() {
77  
      int totalPixels = img.getWidth()*img.getHeight();
78  
      int emptyPixels = totalPixels-pixelsDiffed;
79  
      double innerQuality = totalDiff/Math.max(pixelsDiffed, 1);
80  
      double outerQuality = 0.8; // makes objects shrink or grow
81  
      double result = mix(innerQuality, outerQuality, emptyPixels/(double) totalPixels);
82  
      //System.out.println("inner=" + innerQuality + ", outer=" + outerQuality + ", pixels diffed=" + pixelsDiffed + ", result=" + result);
83  
      return result;
84  
    }
85  
  }
86  
87  
  static abstract class Base {
88  
    abstract Base copy();
89  
    
90  
    abstract void vary();
91  
    
92  
    Base copyVary() {
93  
      Base copy = copy();
94  
      copy.vary();
95  
      return copy;
96  
    }
97  
  }
98  
  
99  
  static abstract class Overlay extends Base {
100  
    abstract Overlay copy();
101  
    abstract void renderOn(Img image);
102  
  }
103  
  
104  
  // Params must be immutable!
105  
  static abstract class Params extends Base {
106  
    RGBImage originalImage;
107  
    abstract Params copy();
108  
    abstract RGBImage render();
109  
110  
    void baseClone(Params p) {
111  
      p.originalImage = originalImage;
112  
    }
113  
    
114  
    RGBImage rendered;
115  
    RGBImage getImage() {
116  
      if (rendered == null)
117  
        rendered = render();
118  
      return rendered;
119  
    }
120  
    
121  
    double score = 2.0;
122  
    double getScore() {
123  
      if (score == 2.0)
124  
        score = calcScore();
125  
      return score;
126  
    }
127  
    
128  
    double calcScore() {
129  
      return diff(originalImage, getImage());
130  
    }
131  
    
132  
    boolean isBetterThan(Params p) {
133  
      return getScore() < p.getScore();
134  
    }
135  
  }
136  
  
137  
  static class Box extends Overlay {
138  
    double cx, cy, w, h;
139  
    RGB color;
140  
141  
    Box copy() {
142  
      Box p = new Box();
143  
      p.cx = cx;
144  
      p.cy = cy;
145  
      p.w = w;
146  
      p.h = h;
147  
      p.color = color;
148  
      return p;
149  
    }
150  
    
151  
    public String toString() {
152  
      return "Box " + cx + " " + cy + " " + w + " " + h + " " + color;
153  
    }
154  
155  
    void renderOn(Img image) {
156  
      box(image, this);
157  
    }
158  
    
159  
    void vary() {
160  
      int s = random(5);
161  
      if (s == 0)
162  
        cx = vary01(cx);
163  
      else if (s == 1)
164  
        cy = vary01(cy);
165  
      else if (s == 2)
166  
        w = vary01(w);
167  
      else if (s == 3)
168  
        h = vary01(h);
169  
      else
170  
        color = varyColor(color);
171  
    }
172  
  }
173  
  
174  
  static class Solid extends Overlay {
175  
    RGB col;
176  
    
177  
    *() {}
178  
    *(RGB *col) {}
179  
    
180  
    Solid copy() {
181  
      new Solid p;
182  
      p.col = col;
183  
      return p;
184  
    }
185  
    
186  
    public String toString() {
187  
      return "Solid " + col;
188  
    }
189  
190  
    void renderOn(Img image) {
191  
      int w = image.getWidth(), h = image.getHeight();
192  
      for (int y = 0; y < h; y++)
193  
        for (int x = 0; x < w; x++)
194  
          image.setPixel(x, y, col);
195  
    }
196  
    
197  
    void vary() {
198  
      col = varyColor(col);
199  
    }
200  
  }
201  
  
202  
  interface Reproducer {
203  
    public Params reproduce(RGBImage original);
204  
  }
205  
  
206  
  interface OverlayReproducer {
207  
    public Overlay reproduce(RGBImage original);
208  
  }
209  
  
210  
  static class RandomBox implements OverlayReproducer {
211  
    int n = -1;
212  
    public Overlay reproduce(RGBImage original) {
213  
      ++n;
214  
      new Box p;
215  
      p.cx = random();
216  
      p.cy = random();
217  
      p.w = random()*0.1;
218  
      p.h = random()*0.1;
219  
      if (n % 2 == 0)
220  
        p.color = randomColor();
221  
      else
222  
        p.color = probeRandomPixel(original);
223  
      return p;
224  
    }
225  
  }
226  
  
227  
  static class RandomSolid implements OverlayReproducer {
228  
    int n = -1;
229  
    public Overlay reproduce(RGBImage original) {
230  
      ++n;
231  
      new Solid p;
232  
      if (n % 2 == 0) {
233  
        p.col = randomColor();
234  
      } else {
235  
        p.col = probeRandomPixel(original);
236  
      }
237  
      return p;
238  
    }
239  
  }
240  
  
241  
  static class WhiteSolid implements OverlayReproducer {
242  
    public Overlay reproduce(RGBImage original) {
243  
      Solid p = new Solid();
244  
      p.col = new RGB(Color.white);
245  
      return p;
246  
    }
247  
  }
248  
  
249  
  static class VaryBest implements Reproducer {
250  
    Reproducer base;
251  
    Params best;
252  
    *(Reproducer *base) {}
253  
    
254  
    public Params reproduce(RGBImage original) {
255  
      Params p = base.reproduce(original);
256  
      if (best == null || p.isBetterThan(best))
257  
        best = p;
258  
      Params variation = (Params) best.copyVary();
259  
      //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
260  
      if (variation.isBetterThan(best)) {
261  
        //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
262  
        best = variation;
263  
      }
264  
      return best;
265  
    }
266  
    
267  
    void reset() {
268  
      best = null;
269  
    }
270  
  }
271  
  
272  
  static class Layered extends Params {
273  
    Layers myMaker;
274  
    Overlay[] list;
275  
    
276  
    Layered(Layers myMaker, Overlay... list) {
277  
      this.myMaker = myMaker;
278  
      this.list = list;
279  
    }
280  
    
281  
    Layered copy() {
282  
      Layered p = new Layered(myMaker, new Overlay[list.length]);
283  
      baseClone(p);
284  
      for (int i = 0; i < list.length; i++)
285  
        p.list[i] = (Overlay) list[i].copy();
286  
      return p;
287  
    }
288  
    
289  
    public String toString() {
290  
      StringBuilder buf = new StringBuilder("layered{");
291  
      for (int i = 0; i < list.length; i++) {
292  
        if (i != 0)
293  
          buf.append(", ");
294  
        buf.append(list[i]);
295  
      }
296  
      return buf + "}";
297  
    }
298  
299  
    RGBImage render() {
300  
      RGBImage image = new RGBImage(originalImage.getWidth(), originalImage.getHeight(), Color.white);
301  
      Painting img = new Painting(image);
302  
      for (int i = 0; i < list.length; i++)
303  
        list[i].renderOn(img);
304  
      return image;
305  
    }
306  
    
307  
    void vary() {
308  
      int i = random(list.length);
309  
      if (random(2) == 0 || myMaker == null) {
310  
        //System.out.println("Varying layer " + i);
311  
        list[i] = (Overlay) list[i].copyVary();
312  
      } else {
313  
        //double score = getScore();
314  
        OverlayReproducer maker = myMaker.list[i];
315  
        list[i] = maker.reproduce(originalImage);
316  
        //System.out.println("Exchanging layer " + i + " from " + maker + ", improvement: " + (score-getFreshScore()));
317  
      }
318  
    }
319  
  }
320  
321  
  static class Layers implements Reproducer {
322  
    OverlayReproducer[] list;
323  
    long ntry = -1;
324  
    int stepTime = 0/*500*/;
325  
    VaryBest varyBest = new VaryBest(this);
326  
    
327  
    *(OverlayReproducer... *list) {}
328  
    
329  
    Layers add(int n, Class<? extends OverlayReproducer> xClass) ctex {
330  
      OverlayReproducer l[] = new OverlayReproducer[list.length+n];
331  
      System.arraycopy(list, 0, l, 0, list.length);
332  
      for (int i = 0; i < n; i++)
333  
        l[list.length+i] = xClass.newInstance();
334  
      list = l;
335  
      return this;
336  
    }
337  
    
338  
    public Params reproduce(RGBImage original) {
339  
      ++ntry;
340  
      int n = this.list.length;
341  
      if (stepTime != 0) {
342  
        // build up image gradually to optimize lower layers first
343  
        n = (int) Math.min(n, ntry/stepTime+1);
344  
        varyBest.reset();
345  
      }
346  
      Overlay[] list = new Overlay[n];
347  
      for (int i = 0; i < n; i++)
348  
        list[i] = this.list[i].reproduce(original);
349  
      Layered result = new Layered(this, list);
350  
      result.originalImage = original;
351  
      return result;
352  
    }
353  
  }
354  
  
355  
  static Params reproduce(RGBImage original) {
356  
    int w = original.getWidth(), h = original.getHeight();
357  
    return reproducer.reproduce(original);
358  
  }
359  
  
360  
  static class ProduceIndividual implements Reproducer {
361  
    OverlayReproducer producer;
362  
363  
    *(OverlayReproducer *producer) {}
364  
365  
    public Params reproduce(RGBImage original) {
366  
      Overlay overlay = producer.reproduce(original);
367  
      Layered result = new Layered(null, new Solid(new RGB(Color.white)), overlay);
368  
      result.originalImage = original;
369  
      return result;
370  
    }
371  
  }
372  
  
373  
  static class OptimizeIndividual implements Reproducer {
374  
    OverlayReproducer producer;
375  
    double bestScore;
376  
    Overlay best;
377  
    
378  
    *(OverlayReproducer *producer) {}
379  
380  
    public Params reproduce(RGBImage original) {
381  
      Overlay overlay = producer.reproduce(original);
382  
      //System.out.println("overlay: " + overlay);
383  
      double score = scoreOverlay(overlay, original);
384  
      if (best == null || score <= bestScore) {
385  
        best = overlay;
386  
        bestScore = score;
387  
      }
388  
      Layered result = new Layered(null, new Solid(new RGB(Color.black)), best);
389  
      result.originalImage = original;
390  
      return result;
391  
    }
392  
  }
393  
  
394  
  static double scoreOverlay(Overlay overlay, RGBImage original) {
395  
    Diffing d = new Diffing(original);
396  
    overlay.renderOn(d);
397  
    return d.getScore();
398  
  }
399  
  
400  
  static class HoldBest implements Reproducer {
401  
    Reproducer base;
402  
    Params best;
403  
    *(Reproducer *base) {}
404  
    
405  
    public Params reproduce(RGBImage original) {
406  
      Params p = base.reproduce(original);
407  
      if (best == null || p.isBetterThan(best))
408  
        best = p;
409  
      return best;
410  
    }
411  
  }
412  
413  
  static class BestHolder {
414  
    Params best;
415  
416  
    public boolean receive(Params p) {
417  
      if (best == null || p.isBetterThan(best)) {
418  
        best = p;
419  
        return true;
420  
      }
421  
      return false;
422  
    }
423  
  }
424  
425  
  psvm {
426  
    String imageID = "#1000332"; // Picture of two coins
427  
    
428  
    for (int i = 0; i < args.length; i++) {
429  
      String arg = args[i];
430  
      if (arg.equals("width"))
431  
        imageWidth = Integer.parseInt(args[++i]);
432  
      else if (isSnippetID(arg))
433  
        imageID = arg;
434  
    }
435  
    
436  
    final String _imageID = imageID;
437  
    
438  
    frame = new FrameWithImages(3);
439  
    frame.frame.setVisible(true);
440  
    exitOnFrameClose(frame.frame);
441  
    
442  
    new Thread() {
443  
      public void run() {
444  
        originalImage = loadImage(_imageID);
445  
        originalImage = resizeToWidth(originalImage, imageWidth);
446  
        frame.setImage(frame.n-1, originalImage);
447  
        
448  
        reproduceOpenEnd(originalImage);
449  
      }
450  
    }.start();
451  
  }
452  
  
453  
  static void reproduceOpenEnd(RGBImage original) {
454  
    new BestHolder bestHolder;
455  
    
456  
    long lastPrint = 0, lastN = 0;
457  
    for (long ntry = 1; ; ntry++) {
458  
      Params p = reproduce(original);
459  
      frame.setImage(0, p.getImage());
460  
      
461  
      if (bestHolder.receive(p))
462  
        frame.setImage(1, bestHolder.best.getImage());
463  
      
464  
      long now = System.currentTimeMillis();
465  
      if (now >= lastPrint+1000) {
466  
        long tps = (ntry-lastN)*1000/(now-lastPrint);
467  
        lastPrint = now;
468  
        lastN = ntry;
469  
        String s = "Try " + ntry + " (" + tps + "/s)";
470  
        System.out.println(s + ", score: " + formatDouble(p.getScore()*100, 2) + "%, structure size: " + structureSize(p, Params.class));
471  
      }
472  
473  
      if (p != null && p.getScore() == 0.0)
474  
        break; // perfect result, end
475  
    }
476  
  }
477  
  
478  
  !include #1000522  
479  
  !include #1000540 // box painting function
480  
}

Author comment

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: 631 / 671
Referenced in: [show references]