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

494
LINES

< > BotCompany Repo | #670 // Reproducing 1 Coin

JavaX source code - run with: x30.jar

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

Author comment

Began life as a copy of #669

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #670
Snippet name: Reproducing 1 Coin
Eternal ID of this version: #670/1
Text MD5: be8eedfe8c72a15c1762f3a6fca6454f
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-07-15 01:54:07
Source code size: 13993 bytes / 494 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 607 / 508
Referenced in: [show references]