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

484
LINES

< > BotCompany Repo | #726 // Reproducing with boxes v3 (with individual diffs, developing)

JavaX source code - run with: x30.jar

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

Author comment

Began life as a copy of #1000528

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #726
Snippet name: Reproducing with boxes v3 (with individual diffs, developing)
Eternal ID of this version: #726/1
Text MD5: 6a084a6b5cedeeb023ad88ac7385cc84
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-10 17:53:16
Source code size: 13065 bytes / 484 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 568 / 511
Referenced in: [show references]