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

350
LINES

< > BotCompany Repo | #671 // Reproducing 2 Coins

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

Uses 3874K of libraries. Click here for Pure Java version (6166L/42K/151K).

1  
!7
2  
3  
static int imageWidth = 200;
4  
5  
static RGBImage originalImage;
6  
static ImageSurface imageSurface;
7  
static JLabel isTitle;
8  
9  
!include #1000522 // helper functions for image reproduction
10  
11  
static abstract class Base {
12  
  abstract Base copy();
13  
  abstract void vary();
14  
}
15  
16  
static abstract class Overlay extends Base {
17  
  abstract Overlay copy();
18  
  abstract void renderOn(RGBImage image);
19  
}
20  
21  
static abstract class Params extends Base {
22  
  RGBImage originalImage;
23  
  abstract Params copy();
24  
  abstract RGBImage render();
25  
26  
  void baseClone(Params p) {
27  
    p.originalImage = originalImage;
28  
  }
29  
  
30  
  RGBImage rendered;
31  
  RGBImage getImage() {
32  
    if (rendered == null)
33  
      rendered = render();
34  
    return rendered;
35  
  }
36  
  
37  
  double score = 2.0;
38  
  double getScore() {
39  
    if (score == 2.0)
40  
      score = calcScore();
41  
    return score;
42  
  }
43  
  
44  
  // when object has changed
45  
  double getFreshScore() {
46  
    resetScore();
47  
    return getScore();
48  
  }
49  
  
50  
  void resetScore() {
51  
    score = 2.0;
52  
    rendered = null;
53  
  }
54  
  
55  
  double calcScore() {
56  
    return diff(originalImage, getImage());
57  
  }
58  
  
59  
  boolean isBetterThan(Params p) {
60  
    return getScore() < p.getScore();
61  
  }
62  
}
63  
64  
static class Coin extends Overlay {
65  
  double cx, cy, radius;
66  
  RGB color;
67  
68  
  Coin copy() {
69  
    Coin p = new Coin();
70  
    p.cx = cx;
71  
    p.cy = cy;
72  
    p.radius = radius;
73  
    p.color = color;
74  
    return p;
75  
  }
76  
  
77  
  public String toString() {
78  
    return "Coin " + cx + " " + cy + " " + radius + " " + color;
79  
  }
80  
81  
  void renderOn(RGBImage image) {
82  
    coin(image, this);
83  
  }
84  
  
85  
  void vary() {
86  
    int s = random(4);
87  
    if (s == 0)
88  
      cx = vary01(cx);
89  
    else if (s == 1)
90  
      cy = vary01(cy);
91  
    else if (s == 2)
92  
      radius = vary01(radius);
93  
    else
94  
      color = varyColor(color);
95  
  }
96  
}
97  
98  
static class Solid extends Overlay {
99  
  RGB col;
100  
  
101  
  Solid copy() {
102  
    Solid p = new Solid();
103  
    p.col = col;
104  
    return p;
105  
  }
106  
  
107  
  public String toString() {
108  
    return "Solid " + col;
109  
  }
110  
111  
  void renderOn(RGBImage image) {
112  
    int w = image.getWidth(), h = image.getHeight();
113  
    for (int y = 0; y < h; y++)
114  
      for (int x = 0; x < w; x++)
115  
        image.setPixel(x, y, col);
116  
  }
117  
  
118  
  void vary() {
119  
    col = varyColor(col);
120  
  }
121  
}
122  
123  
interface Reproducer {
124  
  public Params reproduce(RGBImage original);
125  
}
126  
127  
interface OverlayReproducer {
128  
  public Overlay reproduce(RGBImage original);
129  
}
130  
131  
static class RandomCoin implements OverlayReproducer {
132  
  int n = -1;
133  
  public Overlay reproduce(RGBImage original) {
134  
    ++n;
135  
    Coin p = new Coin();
136  
    p.cx = random();
137  
    p.cy = random();
138  
    p.radius = random()*0.2;
139  
    if (n % 2 == 0)
140  
      p.color = randomColor();
141  
    else
142  
      p.color = probeRandomPixel(original);
143  
    return p;
144  
  }
145  
}
146  
147  
static class RandomSolid implements OverlayReproducer {
148  
  int n = -1;
149  
  public Overlay reproduce(RGBImage original) {
150  
    ++n;
151  
    Solid p = new Solid();
152  
    if (n % 2 == 0) {
153  
      p.col = randomColor();
154  
    } else {
155  
      p.col = probeRandomPixel(original);
156  
    }
157  
    return p;
158  
  }
159  
}
160  
161  
static class WhiteSolid implements OverlayReproducer {
162  
  public Overlay reproduce(RGBImage original) {
163  
    Solid p = new Solid();
164  
    p.col = new RGB(Color.white);
165  
    return p;
166  
  }
167  
}
168  
169  
static class VaryBest implements Reproducer {
170  
  Reproducer base;
171  
  Params best;
172  
  
173  
  VaryBest(Reproducer base) {
174  
    this.base = base;
175  
  }
176  
  
177  
  public Params reproduce(RGBImage original) {
178  
    Params p = base.reproduce(original);
179  
    if (best == null || p.isBetterThan(best))
180  
      best = p;
181  
    Params variation = best.copy();
182  
    variation.vary();
183  
    //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
184  
    if (variation.isBetterThan(best)) {
185  
      //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
186  
      best = variation;
187  
    }
188  
    return best;
189  
  }
190  
  
191  
  void reset() {
192  
    best = null;
193  
  }
194  
}
195  
196  
static class Layered extends Params {
197  
  Layers myMaker;
198  
  Overlay[] list;
199  
  
200  
  Layered(Layers myMaker, Overlay[] list) {
201  
    this.myMaker = myMaker;
202  
    this.list = list;
203  
  }
204  
  
205  
  Layered copy() {
206  
    Layered p = new Layered(myMaker, new Overlay[list.length]);
207  
    baseClone(p);
208  
    for (int i = 0; i < list.length; i++)
209  
      p.list[i] = list[i].copy();
210  
    return p;
211  
  }
212  
  
213  
  public String toString() {
214  
    StringBuilder buf = new StringBuilder("layered{");
215  
    for (int i = 0; i < list.length; i++) {
216  
      if (i != 0)
217  
        buf.append(", ");
218  
      buf.append(list[i]);
219  
    }
220  
    return buf + "}";
221  
  }
222  
223  
  RGBImage render() {
224  
    RGBImage image = new RGBImage(originalImage.getWidth(), originalImage.getHeight(), Color.white);
225  
    for (int i = 0; i < list.length; i++)
226  
      list[i].renderOn(image);
227  
    return image;
228  
  }
229  
  
230  
  void vary() {
231  
    int i = random(list.length);
232  
    if (random(2) == 0) {
233  
      //System.out.println("Varying layer " + i);
234  
      list[i].vary();
235  
    } else {
236  
      //double score = getScore();
237  
      OverlayReproducer maker = myMaker.list[i];
238  
      list[i] = maker.reproduce(originalImage);
239  
      //System.out.println("Exchanging layer " + i + " from " + maker + ", improvement: " + (score-getFreshScore()));
240  
    }
241  
    resetScore();
242  
  }
243  
}
244  
245  
static class Layers implements Reproducer {
246  
  OverlayReproducer[] list;
247  
  long ntry = -1;
248  
  int stepTime = 0/*500*/;
249  
  VaryBest varyBest = new VaryBest(this);
250  
  
251  
  Layers(OverlayReproducer... list) {
252  
    this.list = list;
253  
  }
254  
  
255  
  public Params reproduce(RGBImage original) {
256  
    ++ntry;
257  
    int n = this.list.length;
258  
    if (stepTime != 0) {
259  
      // build up image gradually to optimize lower layers first
260  
      n = (int) Math.min(n, ntry/stepTime+1);
261  
      varyBest.reset();
262  
    }
263  
    Overlay[] list = new Overlay[n];
264  
    for (int i = 0; i < n; i++)
265  
      list[i] = this.list[i].reproduce(original);
266  
    Layered result = new Layered(this, list);
267  
    result.originalImage = original;
268  
    return result;
269  
  }
270  
}
271  
272  
// main reproduce function
273  
static Reproducer reproducer =
274  
  /*new VaryBest*/(new Layers(
275  
    /*new RandomSolid()*/new WhiteSolid(),
276  
    new RandomCoin(),
277  
    new RandomCoin()
278  
  )).varyBest;
279  
280  
static Params reproduce(RGBImage original) {
281  
  int w = original.getWidth(), h = original.getHeight();
282  
  return reproducer.reproduce(original);
283  
}
284  
285  
p-substance-thread {
286  
  String imageID = "#1000332"; // Picture of two coins
287  
  if (args.length != 0) imageID = args[0];
288  
  final String _imageID = imageID;
289  
  originalImage = loadImage(_imageID);
290  
  originalImage = resizeToWidth(originalImage, imageWidth);
291  
  
292  
  swing {
293  
    imageSurface = new ImageSurface;
294  
    isTitle = jCenteredLabel("Reproduction");
295  
      
296  
    showPackedFrame(vgrid(
297  
      withCenteredTitle("Original Image", new ImageSurface(originalImage)),
298  
      withTitle(isTitle, imageSurface)));
299  
  }
300  
  
301  
  reproduceOpenEnd(originalImage, imageSurface);
302  
}
303  
304  
static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) {
305  
  Params best = null;
306  
  long lastPrint = 0, lastN = 0;
307  
  for (long ntry = 1; ; ntry++) {
308  
    long now = System.currentTimeMillis();
309  
    if (now >= lastPrint+1000) {
310  
      long tps = (ntry-lastN)*1000/(now-lastPrint);
311  
      lastPrint = now;
312  
      lastN = ntry;
313  
      String s = "Try " + ntry + " (" + tps + "/s)";
314  
      if (best == null)
315  
        System.out.println(s);
316  
      else {
317  
        System.out.println("Best: " + best);
318  
        System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class));
319  
      }
320  
    }
321  
    Params p = reproduce(original);
322  
    if (best == null || p != null && p.getScore() < best.getScore()) {
323  
      //System.out.println("New best! " + p.getScore());
324  
      best = p;
325  
      imageSurface.setImage(p.getImage());
326  
      setText(isTitle, print("Reproduction (" + formatDouble(100*(1-p.getScore()), 1) + "%)"));
327  
    }
328  
    
329  
    if (p != null && p.getScore() == 0.0)
330  
      break;
331  
  }
332  
}
333  
334  
static void coin(RGBImage img, Coin p) {
335  
  int w = img.getWidth(), h = img.getHeight();
336  
  double ratio = ((double) w)/h;
337  
  for (int yy = 0; yy < h; yy++) {
338  
    double y = ((double) yy)/(h-1);
339  
    double ybla = Math.abs(y-p.cy)/p.radius;
340  
    if (ybla <= 1) {
341  
      double xbla = Math.sqrt(1-ybla*ybla)/ratio;
342  
      double l = p.cx-xbla*p.radius, r = p.cx+xbla*p.radius;
343  
      int ll = (int) (l*w), rr = (int) (r*w);
344  
      ll = Math.max(0, ll);
345  
      rr = Math.min(w-1, rr);
346  
      for (int xx = ll; xx <= rr; xx++)
347  
        img.setPixel(xx, yy, p.color);
348  
    }
349  
  }
350  
}

Author comment

Began life as a copy of #669

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #671
Snippet name: Reproducing 2 Coins
Eternal ID of this version: #671/17
Text MD5: 7875379eb79815532f7e6b97b5b0c9c2
Transpilation MD5: c4cea5ac04af475a769dca57de6422c2
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-02-19 13:40:24
Source code size: 8677 bytes / 350 lines
Pitched / IR pitched: No / No
Views / Downloads: 781 / 805
Version history: 16 change(s)
Referenced in: [show references]