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

460
LINES

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

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

Author comment

Began life as a copy of #725

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: #1000528
Snippet name: Reproducing with boxes v3 (with individual diffs, developing)
Eternal ID of this version: #1000528/1
Text MD5: bb3a28d1ce7e322cbefb1a7897ddd7b7
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-10 17:39:43
Source code size: 12332 bytes / 460 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 754 / 653
Referenced in: [show references]