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

542
LINES

< > BotCompany Repo | #669 // Reproducing Coins

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

Libraryless. Click here for Pure Java version (1387L/10K/31K).

1  
!636
2  
!629 // standard functions
3  
!658 // image classes
4  
5  
import java.awt.*;
6  
import java.awt.image.*;
7  
import java.util.List;
8  
import javax.imageio.*;
9  
import java.lang.reflect.*;
10  
11  
public class main {
12  
  static RGBImage originalImage;
13  
  static int imageWidth = 200;
14  
  
15  
  static abstract class Base {
16  
    abstract Base copy();
17  
    abstract void vary();
18  
  }
19  
  
20  
  static abstract class Overlay extends Base {
21  
    abstract Overlay copy();
22  
    abstract void renderOn(RGBImage image);
23  
  }
24  
  
25  
  static abstract class Params extends Base {
26  
    RGBImage originalImage;
27  
    abstract Params copy();
28  
    abstract RGBImage render();
29  
30  
    void baseClone(Params p) {
31  
      p.originalImage = originalImage;
32  
    }
33  
    
34  
    RGBImage rendered;
35  
    RGBImage getImage() {
36  
      if (rendered == null)
37  
        rendered = render();
38  
      return rendered;
39  
    }
40  
    
41  
    double score = 2.0;
42  
    double getScore() {
43  
      if (score == 2.0)
44  
        score = calcScore();
45  
      return score;
46  
    }
47  
    
48  
    // when object has changed
49  
    double getFreshScore() {
50  
      resetScore();
51  
      return getScore();
52  
    }
53  
    
54  
    void resetScore() {
55  
      score = 2.0;
56  
      rendered = null;
57  
    }
58  
    
59  
    double calcScore() {
60  
      return diff(originalImage, getImage());
61  
    }
62  
    
63  
    boolean isBetterThan(Params p) {
64  
      return getScore() < p.getScore();
65  
    }
66  
  }
67  
  
68  
  static class Coin extends Overlay {
69  
    double cx, cy, radius;
70  
    RGB color;
71  
72  
    Coin copy() {
73  
      Coin p = new Coin();
74  
      p.cx = cx;
75  
      p.cy = cy;
76  
      p.radius = radius;
77  
      p.color = color;
78  
      return p;
79  
    }
80  
    
81  
    public String toString() {
82  
      return "Coin " + cx + " " + cy + " " + radius + " " + color;
83  
    }
84  
85  
    void renderOn(RGBImage image) {
86  
      coin(image, this);
87  
    }
88  
    
89  
    void vary() {
90  
      int s = random(4);
91  
      if (s == 0)
92  
        cx = vary01(cx);
93  
      else if (s == 1)
94  
        cy = vary01(cy);
95  
      else if (s == 2)
96  
        radius = vary01(radius);
97  
      else
98  
        color = varyColor(color);
99  
    }
100  
  }
101  
  
102  
  static class Solid extends Overlay {
103  
    RGB col;
104  
    
105  
    Solid copy() {
106  
      Solid p = new Solid();
107  
      p.col = col;
108  
      return p;
109  
    }
110  
    
111  
    public String toString() {
112  
      return "Solid " + col;
113  
    }
114  
115  
    void renderOn(RGBImage image) {
116  
      int w = image.getWidth(), h = image.getHeight();
117  
      for (int y = 0; y < h; y++)
118  
        for (int x = 0; x < w; x++)
119  
          image.setPixel(x, y, col);
120  
    }
121  
    
122  
    void vary() {
123  
      col = varyColor(col);
124  
    }
125  
  }
126  
  
127  
  interface Reproducer {
128  
    public Params reproduce(RGBImage original);
129  
  }
130  
  
131  
  interface OverlayReproducer {
132  
    public Overlay reproduce(RGBImage original);
133  
  }
134  
  
135  
  static class RandomCoin implements OverlayReproducer {
136  
    int n = -1;
137  
    public Overlay reproduce(RGBImage original) {
138  
      ++n;
139  
      Coin p = new Coin();
140  
      p.cx = random();
141  
      p.cy = random();
142  
      p.radius = random()*0.2;
143  
      if (n % 2 == 0)
144  
        p.color = randomColor();
145  
      else
146  
        p.color = probeRandomPixel(original);
147  
      return p;
148  
    }
149  
  }
150  
  
151  
  static class RandomSolid implements OverlayReproducer {
152  
    int n = -1;
153  
    public Overlay reproduce(RGBImage original) {
154  
      ++n;
155  
      Solid p = new Solid();
156  
      if (n % 2 == 0) {
157  
        p.col = randomColor();
158  
      } else {
159  
        p.col = probeRandomPixel(original);
160  
      }
161  
      return p;
162  
    }
163  
  }
164  
  
165  
  static class WhiteSolid implements OverlayReproducer {
166  
    public Overlay reproduce(RGBImage original) {
167  
      Solid p = new Solid();
168  
      p.col = new RGB(Color.white);
169  
      return p;
170  
    }
171  
  }
172  
  
173  
  static class VaryBest implements Reproducer {
174  
    Reproducer base;
175  
    Params best;
176  
    
177  
    VaryBest(Reproducer base) {
178  
      this.base = base;
179  
    }
180  
    
181  
    public Params reproduce(RGBImage original) {
182  
      Params p = base.reproduce(original);
183  
      if (best == null || p.isBetterThan(best))
184  
        best = p;
185  
      Params variation = best.copy();
186  
      variation.vary();
187  
      //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
188  
      if (variation.isBetterThan(best)) {
189  
        //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
190  
        best = variation;
191  
      }
192  
      return best;
193  
    }
194  
    
195  
    void reset() {
196  
      best = null;
197  
    }
198  
  }
199  
  
200  
  static class Layered extends Params {
201  
    Layers myMaker;
202  
    Overlay[] list;
203  
    
204  
    Layered(Layers myMaker, Overlay[] list) {
205  
      this.myMaker = myMaker;
206  
      this.list = list;
207  
    }
208  
    
209  
    Layered copy() {
210  
      Layered p = new Layered(myMaker, new Overlay[list.length]);
211  
      baseClone(p);
212  
      for (int i = 0; i < list.length; i++)
213  
        p.list[i] = list[i].copy();
214  
      return p;
215  
    }
216  
    
217  
    public String toString() {
218  
      StringBuilder buf = new StringBuilder("layered{");
219  
      for (int i = 0; i < list.length; i++) {
220  
        if (i != 0)
221  
          buf.append(", ");
222  
        buf.append(list[i]);
223  
      }
224  
      return buf + "}";
225  
    }
226  
227  
    RGBImage render() {
228  
      RGBImage image = new RGBImage(originalImage.getWidth(), originalImage.getHeight(), Color.white);
229  
      for (int i = 0; i < list.length; i++)
230  
        list[i].renderOn(image);
231  
      return image;
232  
    }
233  
    
234  
    void vary() {
235  
      int i = random(list.length);
236  
      if (random(2) == 0) {
237  
        //System.out.println("Varying layer " + i);
238  
        list[i].vary();
239  
      } else {
240  
        //double score = getScore();
241  
        OverlayReproducer maker = myMaker.list[i];
242  
        list[i] = maker.reproduce(originalImage);
243  
        //System.out.println("Exchanging layer " + i + " from " + maker + ", improvement: " + (score-getFreshScore()));
244  
      }
245  
      resetScore();
246  
    }
247  
  }
248  
249  
  static class Layers implements Reproducer {
250  
    OverlayReproducer[] list;
251  
    long ntry = -1;
252  
    int stepTime = 0/*500*/;
253  
    VaryBest varyBest = new VaryBest(this);
254  
    
255  
    Layers(OverlayReproducer... list) {
256  
      this.list = list;
257  
    }
258  
    
259  
    public Params reproduce(RGBImage original) {
260  
      ++ntry;
261  
      int n = this.list.length;
262  
      if (stepTime != 0) {
263  
        // build up image gradually to optimize lower layers first
264  
        n = (int) Math.min(n, ntry/stepTime+1);
265  
        varyBest.reset();
266  
      }
267  
      Overlay[] list = new Overlay[n];
268  
      for (int i = 0; i < n; i++)
269  
        list[i] = this.list[i].reproduce(original);
270  
      Layered result = new Layered(this, list);
271  
      result.originalImage = original;
272  
      return result;
273  
    }
274  
  }
275  
  
276  
  // main reproduce function
277  
  static Reproducer reproducer =
278  
    /*new VaryBest*/(new Layers(
279  
      /*new RandomSolid()*/new WhiteSolid(),
280  
      new RandomCoin(),
281  
      new RandomCoin(),
282  
      new RandomCoin(),
283  
      new RandomCoin(),
284  
      new RandomCoin(),
285  
      new RandomCoin()
286  
    )).varyBest;
287  
  
288  
  static Params reproduce(RGBImage original) {
289  
    int w = original.getWidth(), h = original.getHeight();
290  
    return reproducer.reproduce(original);
291  
  }
292  
  
293  
  public static void main(String[] args) {
294  
    String imageID = "#1000329"; // Picture of some coins
295  
    if (args.length != 0) imageID = args[0];
296  
    final String _imageID = imageID;
297  
    
298  
    JFrame frame = new JFrame("A JavaX Frame");
299  
    
300  
    final ImageSurface imageSurface = new ImageSurface();
301  
    Component panel = imageSurface;
302  
    
303  
    frame.add(panel);
304  
    frame.setBounds(100, 100, 300, 300);
305  
    frame.setVisible(true);
306  
    exitOnFrameClose(frame);
307  
    
308  
    new Thread() {
309  
      public void run() {
310  
        originalImage = loadImage(_imageID);
311  
        originalImage = resizeToWidth(originalImage, imageWidth);
312  
        
313  
        reproduceOpenEnd(originalImage, imageSurface);
314  
      }
315  
    }.start();
316  
  }
317  
  
318  
  static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) {
319  
    Params best = null;
320  
    long lastPrint = 0, lastN = 0;
321  
    for (long ntry = 1; ; ntry++) {
322  
      long now = System.currentTimeMillis();
323  
      if (now >= lastPrint+1000) {
324  
        long tps = (ntry-lastN)*1000/(now-lastPrint);
325  
        lastPrint = now;
326  
        lastN = ntry;
327  
        String s = "Try " + ntry + " (" + tps + "/s)";
328  
        if (best == null)
329  
          System.out.println(s);
330  
        else {
331  
          System.out.println("Best: " + best);
332  
          System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class));
333  
        }
334  
      }
335  
      Params p = reproduce(original);
336  
      if (best == null || p != null && p.getScore() < best.getScore()) {
337  
        //System.out.println("New best! " + p.getScore());
338  
        best = p;
339  
        imageSurface.setImage(p.getImage());
340  
      }
341  
      
342  
      if (p != null && p.getScore() == 0.0)
343  
        break;
344  
    }
345  
  }
346  
  
347  
  static RGB probeRandomPixel(RGBImage image) {
348  
    int x = (int) (random()*(image.getWidth()-1));
349  
    int y = (int) (random()*(image.getHeight()-1));
350  
    return image.getPixel(x, y);
351  
  }
352  
  
353  
  static RGB randomColor() {
354  
    return new RGB(random(), random(), random());
355  
  }
356  
  
357  
  static RGBImage resizeToWidth(RGBImage image, int w) {
358  
    return resize(image, w, (int) ((image.getHeight()*(double) w)/image.getWidth()));
359  
  }
360  
  
361  
  public static RGBImage resize(RGBImage image, int w, int h) {
362  
    if (w == image.getWidth() && h == image.getHeight()) return image;
363  
364  
    int[] pixels = new int[w*h];
365  
    for (int y = 0; y < h; y++)
366  
      for (int x = 0; x < w; x++)
367  
        pixels[y*w+x] = image.getInt(x*image.getWidth()/w, y*image.getHeight()/h);
368  
    return new RGBImage(w, h, pixels);
369  
  }
370  
371  
  static boolean useImageCache = true;
372  
  static RGBImage loadImage(String snippetID) {
373  
   try {
374  
    File dir = new File(System.getProperty("user.home"), ".tinybrain/image-cache");
375  
    if (useImageCache) {
376  
      dir.mkdirs();
377  
      File file = new File(dir, snippetID + ".png");
378  
      if (file.exists() && file.length() != 0)
379  
        try {
380  
          return new RGBImage(ImageIO.read(file));
381  
        } catch (Throwable e) {
382  
          e.printStackTrace();
383  
          // fall back to loading from sourceforge
384  
        }
385  
    }
386  
387  
    String imageURL = getImageURL(parseSnippetID(snippetID));
388  
    System.err.println("Loading image: " + imageURL);
389  
    BufferedImage image = ImageIO.read(new URL(imageURL));
390  
391  
    if (useImageCache) {
392  
      File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis());
393  
      ImageIO.write(image, "png", tempFile);
394  
      tempFile.renameTo(new File(dir, snippetID + ".png"));
395  
      //Log.info("Cached image.");
396  
    }
397  
398  
    //Log.info("Loaded image.");
399  
    return new RGBImage(image);
400  
   } catch (IOException e) {
401  
    throw new RuntimeException(e);
402  
   }
403  
  }
404  
405  
  static String getImageURL(long snippetID) throws IOException {
406  
    String url;
407  
    if (snippetID == 1000010 || snippetID == 1000012)
408  
      url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + snippetID;
409  
    else
410  
      url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + snippetID
411  
        + "&contentType=image/png";
412  
    return url;
413  
  }
414  
415  
  public static long parseSnippetID(String snippetID) {
416  
    return Long.parseLong(shortenSnippetID(snippetID));
417  
  }
418  
419  
  private static String shortenSnippetID(String snippetID) {
420  
    if (snippetID.startsWith("#"))
421  
      snippetID = snippetID.substring(1);
422  
    String httpBlaBla = "http://tinybrain.de/";
423  
    if (snippetID.startsWith(httpBlaBla))
424  
      snippetID = snippetID.substring(httpBlaBla.length());
425  
    return snippetID;
426  
  }
427  
  
428  
  static Random _random = new Random();
429  
  static double random() {
430  
    return _random.nextInt(100001)/100000.0;
431  
  }
432  
  
433  
  static int random(int max) {
434  
    return _random.nextInt(max);
435  
  }
436  
  
437  
  static double random(double min, double max) {
438  
    return min+random()*(max-min);
439  
  }
440  
  
441  
  static void coin(RGBImage img, Coin p) {
442  
    int w = img.getWidth(), h = img.getHeight();
443  
    double ratio = ((double) w)/h;
444  
    for (int yy = 0; yy < h; yy++) {
445  
      double y = ((double) yy)/(h-1);
446  
      double ybla = Math.abs(y-p.cy)/p.radius;
447  
      if (ybla <= 1) {
448  
        double xbla = Math.sqrt(1-ybla*ybla)/ratio;
449  
        double l = p.cx-xbla*p.radius, r = p.cx+xbla*p.radius;
450  
        int ll = (int) (l*w), rr = (int) (r*w);
451  
        ll = Math.max(0, ll);
452  
        rr = Math.min(w-1, rr);
453  
        for (int xx = ll; xx <= rr; xx++)
454  
          img.setPixel(xx, yy, p.color);
455  
      }
456  
    }
457  
  }
458  
  
459  
  static double mix(double a, double b, double bishness) {
460  
    return a+(b-a)*bishness;
461  
  }
462  
  
463  
  public static double pixelDiff(RGB a, RGB b) {
464  
    return (Math.abs(a.r-b.r) + Math.abs(a.g-b.g) + Math.abs(a.b-b.b))/3;
465  
  }
466  
467  
  public static double diff(RGBImage image, RGBImage image2) {
468  
    int w = image.getWidth(), h = image.getHeight();
469  
    double sum = 0;
470  
    for (int y = 0; y < h; y++)
471  
      for (int x = 0; x < w; x++)
472  
        sum += pixelDiff(image.getRGB(x, y), image2.getRGB(x, y));
473  
    return sum/(w*h);
474  
  }
475  
  
476  
  public static void copy(RGBImage src, int srcX, int srcY, RGBImage dst, int dstX, int dstY, int w, int h) {
477  
    for (int y = 0; y < h; y++)
478  
      for (int x = 0; x < w; x++)
479  
        dst.setPixel(dstX+x, dstY+y, src.getPixel(srcX+x, srcY+y));
480  
  }
481  
  
482  
  public static int structureSize(Object o, Class baseClass) {
483  
    return structureSize(o, baseClass, new IdentityHashMap());
484  
  }
485  
  
486  
  static int structureSize(Object o, Class baseClass,
487  
    IdentityHashMap seen) {
488  
    if (o == null || seen.containsKey(o)) return 0;
489  
    seen.put(o, Boolean.TRUE);
490  
    int size = 1;
491  
    Class c = o.getClass();
492  
    if (c.isArray()) {
493  
      int n = Array.getLength(o);
494  
      for (int i = 0; i < n; i++)
495  
        size += structureSize(Array.get(o, i), baseClass, seen);
496  
    } else
497  
      while (c != Object.class && c != baseClass) {
498  
        Field[] fields = c.getDeclaredFields();
499  
        for (Field field : fields) {
500  
          if ((field.getModifiers() & Modifier.STATIC) != 0)
501  
            continue;
502  
          if (field.getType().isPrimitive())
503  
            ++size;
504  
          else {
505  
            Object value = null;
506  
            try {
507  
              value = field.get(o);
508  
            } catch (IllegalAccessException e) {
509  
              throw new RuntimeException(e);
510  
            }
511  
            size += structureSize(value, baseClass, seen);
512  
          }
513  
        }
514  
        c = c.getSuperclass();
515  
      }
516  
    return size;
517  
  }
518  
  
519  
  public static String formatDouble(double d, int digits) {
520  
    String format = "0.";
521  
    for (int i = 0; i < digits; i++) format += "#";
522  
    return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d);
523  
  }
524  
525  
  static float varyChannel(float x) {
526  
    return Math.max(0f, Math.min(1f, (float) (x+random(-0.1, 0.1))));
527  
  }
528  
  
529  
  static double vary01(double x) {
530  
    return Math.max(0, Math.min(1, x+random(-0.1, 0.1)));
531  
  }
532  
  
533  
  static RGB varyColor(RGB rgb) {
534  
    int s = random(3);
535  
    if (s == 0)
536  
      return new RGB(varyChannel(rgb.r), rgb.g, rgb.b);
537  
    else if (s == 1)
538  
      return new RGB(rgb.r, varyChannel(rgb.g), rgb.b);
539  
    else
540  
      return new RGB(rgb.r, rgb.g, varyChannel(rgb.b));
541  
  }
542  
}

Author comment

Began life as a copy of #668

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: #669
Snippet name: Reproducing Coins
Eternal ID of this version: #669/1
Text MD5: 6318af112f75828bdcd43e2deb334681
Transpilation MD5: d925d6b17425472b289b2033e3cdb517
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-07-15 14:32:59
Source code size: 15380 bytes / 542 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 814 / 759
Referenced in: [show references]