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

934
LINES

< > BotCompany Repo | #1034151 // Gazelle Screen Cam / Gazelle 22 Module [backup]

JavaX source code (Dynamic Module) - run with: Stefan's OS

1  
!7
2  
3  
need latest indexOf.
4  
5  
// Note: It's ok again to use db_mainConcepts()
6  
7  
!include early #1033884 // Compact Module Include Gazelle V [dev version]
8  
9  
module GazelleScreenCam {
10  
  !include early #1025212 // +Enabled without visualization
11  
  
12  
  int pixelRows = 128, colors = 8;
13  
  S script = "64p 8c gradientImage";
14  
  S testScreenScript;
15  
  S newScript;
16  
  S screenCamScript;
17  
  S selectedTab;
18  
  S javaCode;
19  
  bool animate = true;
20  
  bool horizontalLayout; // flat layout
21  
  int fpsTarget = 20;
22  
  S webCamName;
23  
  bool webCamAccessEnabled = true;
24  
  
25  
  WatchTarget watchTarget;
26  
27  
  transient ImageSurface isPosterized, isTestScreen;
28  
  transient new ScreenCamStream imageStream;
29  
  
30  
  transient Gazelle22_ImageToRegions imageToRegions_finished;
31  
  transient new DoubleFPSCounter fpsCounter;
32  
  transient int fps;
33  
  transient WatchTargetSelector watchTargetSelector;
34  
  transient new RollingAverage remainingMSPerFrame;
35  
  transient int remainingMS;
36  
  
37  
  transient new FunctionTimings<S> functionTimings;
38  
  
39  
  transient ReliableSingleThread rstRunScript = dm_rst(me(), r _runScript);
40  
  
41  
  transient JGazelleVScriptRunner scriptRunner;
42  
  transient JGazelleVScriptRunner testScreenScriptRunner;
43  
  
44  
  transient Animation animation;
45  
  
46  
  transient UIURLSystem uiURLs;
47  
48  
  //transient L<Webcam> availableWebCams;
49  
  transient JComboBox<Webcam> cbWebCam;
50  
  transient SingleComponentPanel scpWebCamImage;
51  
  transient WebcamPanel webCamPanel;
52  
53  
  transient JLeftArrowScriptIDE screenCamScriptIDE;
54  
  transient GazelleV_LeftArrowScript.Script runningScreenCamScript;
55  
  
56  
  // set by host
57  
  transient Concepts concepts;
58  
  
59  
  S uiURL = "Main Tabs";
60  
  
61  
  transient FileWatchService fileWatcher;
62  
  
63  
  transient SimpleCRUD_v2<Label> labelCRUD;
64  
  transient SimpleCRUD_v2<GalleryImage> imageCRUD;
65  
66  
  transient JGallery gallery;
67  
  transient JComponent galleryComponent;
68  
69  
  transient FlexibleRateTimer screenCamTimer;
70  
  transient SingleComponentPanel scpMain;
71  
  transient JTabbedPane mainTabs;
72  
  transient bool showRegionsAsOutline = true;
73  
  transient JComponent watchScreenPane;
74  
  transient S screenCamRecognitionOutput;
75  
76  
  transient BackgroundProcessesUI backgroundProcessesUI;
77  
78  
  // add fields here
79  
80  
  start {
81  
    dm_onFieldChange horizontalLayout(
82  
      //r dm_revisualize // deh buggy
83  
      r dm_reload
84  
    );
85  
    
86  
    if (concepts == null) {
87  
      // non-standalone mode (doesn't work yet)
88  
      printWithMS("Starting DB");
89  
      db();
90  
      concepts = db_mainConcepts();
91  
    } else
92  
      assertSame(concepts, db_mainConcepts());
93  
      
94  
    concepts.quietSave = true;
95  
96  
    // make indexes
97  
    indexConceptField(concepts, GalleryImage, "path");
98  
    indexConceptField(concepts, Example, "item");
99  
    
100  
    // update count in tab when tab isn't selected
101  
    onConceptChanges(concepts, -> {
102  
      labelCRUD?.updateEnclosingTabTitle();
103  
      //imageCRUD?.updateEnclosingTabTitle();
104  
      updateEnclosingTabTitleWithCount(galleryComponent, countConcepts(GalleryImage));
105  
    });
106  
    
107  
    uiURLs = new UIURLSystem(me(), dm_fieldLiveValue uiURL());
108  
109  
    backgroundProcessesUI = new BackgroundProcessesUI;
110  
111  
    dm_watchFieldAndNow enabled(-> backgroundProcessesUI.addOrRemove(enabled, "Screen Cam"));
112  
    
113  
    scriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue script(me()));
114  
    testScreenScriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue testScreenScript(me()));
115  
116  
    printWithMS("Making image stream");
117  
118  
    imageStream.onNewElement(img -> {
119  
      fpsCounter.inc();
120  
      setField(fps := iround(fpsCounter!));
121  
122  
      // perform analysis on screen cam image
123  
124  
      // new G22_ImageAnalysis screenCamImageAnalysis;
125  
      
126  
      assertTrue("meta", getMetaSrc(img) instanceof ScreenShotMeta);
127  
      Gazelle22_ImageToRegions itr = new(functionTimings, img, new SnPSettings(pixelRows, colors));
128  
      itr.run();
129  
      imageToRegions_finished = itr;
130  
131  
      // run "linear" script on image if any
132  
      
133  
      if (shouldRunScript()) rstRunScript.go();
134  
135  
      // run left-arrow script
136  
137  
      if (screenCamScriptIDE != null 
138  
        && screenCamScriptIDE.visible()) try {
139  
          g22_runPostAnalysisLeftArrowScript(itr, runningScreenCamScript);
140  
        } catch e {
141  
          printStackTrace(e);
142  
          screenCamScriptIDE.showRuntimeError(e);
143  
        }
144  
145  
      // make textual result of analysis
146  
      
147  
      S text = nRegions(itr.regions.regionCount());
148  
      setField(screenCamRecognitionOutput := text);
149  
      
150  
      // display image after analysis so we can highlight a region
151  
152  
      g22_renderPosterizedHighlightedImage(isPosterized, itr, showRegionsAsOutline);
153  
    });
154  
155  
    watchTargetSelector = new WatchTargetSelector;
156  
157  
    /*if (webCamAccessEnabled) {
158  
      printWithMS("Detecting web cams");
159  
      watchTargetSelector.updateCamCount();
160  
      printWithMS("Found " + n2(availableWebCams, "web cam"));
161  
    }*/
162  
    
163  
    printWithMS("Starting screen cam");
164  
    
165  
    ownResource(screenCamTimer = new FlexibleRateTimer(fpsTarget, rEnter {
166  
      if (!enabled) ret;
167  
      watchTargetSelector?.updateScreenCount();
168  
      Timestamp deadline = tsNowPlusMS(1000/fpsTarget);
169  
      if (watchTarget cast WatchScreen)
170  
        imageStream.useScreen(watchTarget.screenNr-1);
171  
      else if (watchTarget cast WatchMouse)
172  
        imageStream.area(mouseArea(watchTarget.width, watchTarget.height));
173  
      imageStream.step();
174  
      long remaining = deadline.minus(tsNow());
175  
      remainingMSPerFrame.add(remaining);
176  
      setField(remainingMS := iround(remainingMSPerFrame!));
177  
    }));
178  
    screenCamTimer.start();
179  
    dm_onFieldChange fpsTarget(-> screenCamTimer.setFrequencyImmediately(fpsTarget));
180  
181  
    printWithMS("Starting dir watcher");
182  
    
183  
    startDirWatcher();
184  
    
185  
    printWithMS("Gathering images from disk");
186  
    for (f : allImageFiles(galleryDir()))
187  
      addToGallery(f);
188  
    printWithMS("Got dem images");
189  
190  
    transpileRaw_makeTranslator = -> hotwire(#7);
191  
192  
    // OSHI adds 4.5 MB to the jar...
193  
    //doAfter(5.0, r { print("Process size: ", toM_str(oshi_currentProcessResidentSize_noZGCFix())) });
194  
  }
195  
  
196  
  void startDirWatcher {
197  
    fileWatcher = new FileWatchService;
198  
    fileWatcher.addRecursiveListener(picturesDir(), file -> {
199  
      if (!isImageFile(file)) ret;
200  
      addToGallery(file);
201  
    });
202  
  }
203  
  
204  
  ImageSurface stdImageSurface() {
205  
    var is = pixelatedImageSurface().setAutoZoomToDisplay(true).repaintInThread(false);
206  
    new ImageSurface_PositionToolTip(is);
207  
    ret is;
208  
  }
209  
210  
  ImageSurface stdImageSurface(BufferedImage etc img) {
211  
    var is = stdImageSurface();
212  
    is.setImage(img);
213  
    ret is;
214  
  }
215  
  
216  
  visualize {
217  
    gallery = new JGallery;
218  
    galleryComponent = gallery.visualize();
219  
220  
    new AWTOnConceptChanges(concepts, galleryComponent, -> {
221  
      gallery.setImageFiles(map(list(GalleryImage), i -> i.path));
222  
    }).install();
223  
    
224  
    isPosterized = stdImageSurface();
225  
    
226  
    //isRegions = stdImageSurface();
227  
    isTestScreen = stdImageSurface();
228  
    
229  
    // when test screen is visible, do the animation
230  
    awtEvery(isTestScreen, 1000/20, r stepAnimation);
231  
    
232  
    //print("Labels: " + list(concepts, Label));
233  
    labelCRUD = new SimpleCRUD_v2(concepts, Label);
234  
    labelCRUD.hideFields("globalID");
235  
    labelCRUD.addCountToEnclosingTab(true);
236  
    labelCRUD.itemToMap_inner2 = l
237  
      -> litorderedmap(
238  
        "Name" := l.name,
239  
        "# Examples" := n2(countConcepts(concepts, Example, label := l)));
240  
    
241  
    imageCRUD = new SimpleCRUD_v2(concepts, GalleryImage);
242  
    imageCRUD.addCountToEnclosingTab(true);
243  
    imageCRUD.itemToMap_inner2 = img
244  
      -> litorderedmap(
245  
        "File" := fileName(img.path),
246  
        "Folder" := dirPath(img.path));
247  
    var imageCRUDVis = imageCRUD.visualize();
248  
    imageCRUD.addButton(jPopDownButton_noText(
249  
      "Forget missing images" := rThreadEnter forgetMissingImages
250  
    ));
251  
    
252  
    // main visual
253  
254  
    var studyPanel = new StudyPanel;
255  
256  
    watchScreenPane = borderlessScrollPane(jHigherScrollPane(
257  
      jfullcenter(vstack(
258  
        withLeftAndRightMargin(hstack(
259  
          dm_rcheckBox enabled("Watch"),
260  
          watchTargetSelector.visualize(),
261  
          jlabel(" in "),
262  
          withLabelToTheRight("colors @ ", dm_spinner colors(2, 256)),
263  
          withLabelToTheRight("p", dm_powersOfTwoSpinner pixelRows(512)),
264  
        )),
265  
        verticalStrut(2),
266  
        withSideMargins(centerAndEastWithMargin(
267  
          dm_fieldLabel screenCamRecognitionOutput(),
268  
          dm_transientCalculatedToolTip speedInfo_long(rightAlignLabel(dm_transientCalculatedLabel speedInfo()))
269  
        )),
270  
      ))));
271  
272  
    mainTabs = scrollingTabs(jTopOrLeftTabs(horizontalLayout,
273  
      "Screen Cam" := jOnDemand screenCamPanel(),
274  
      "Screen Cam + Script" := jOnDemand screenCamPlusScriptPanel(),
275  
      WithToolTip("Study", "Here you can analyze gallery images")
276  
        := withTopAndBottomMargin(studyPanel.visualize()),
277  
      WithToolTip("Java", "Write & run actual Java code")
278  
        := withBottomMargin(jOnDemand javaPanel()),
279  
      WithToolTip("Gallery", "Gallery view with preview images")
280  
        := withBottomMargin(galleryComponent),
281  
      WithToolTip("Gallery 2", "Gallery view with more functions (delete etc)")
282  
        := wrapCRUD(imageCRUD, imageCRUDVis),
283  
    ));
284  
    
285  
    persistSelectedTabAsLiveValue(mainTabs, dm_fieldLiveValue selectedTab());
286  
287  
    var cbEnabled = toolTip("Switch screen cam on or off", dm_checkBox enabled(""));
288  
    var lblScreenCam = setToolTip("Show scaled down and color-reduced screen image",
289  
      jlabel("Screen Cam"));
290  
    tabComponentClickFixer(lblScreenCam);
291  
    var screenCamTab = hstackWithSpacing(cbEnabled, lblScreenCam);
292  
    
293  
    replaceTabTitleComponent(mainTabs, "Screen Cam", screenCamTab);
294  
    
295  
    // for tab titles
296  
    labelCRUD.update();
297  
    imageCRUD.update();
298  
    
299  
    initUIURLs();
300  
301  
    var urlBar = uiURLs.urlBar();
302  
    setToolTip(uiURLs.comboBox, "UI navigation system (partially populated)");
303  
304  
    scpMain = singleComponentPanel();
305  
    uiURLs.scp(scpMain);
306  
307  
    uiURLs.showUIURL(uiURL);
308  
              
309  
    var vis = northAndCenter(
310  
      withSideAndTopMargin(centerAndEastWithMargin(urlBar, backgroundProcessesUI.shortLabel())),
311  
      //centerAndSouthOrEast(horizontalLayout,
312  
        /*withBottomMargin*/(scpMain),
313  
      /*  watchScreenPane
314  
      )*/
315  
    );
316  
    setHorizontalMarginForAllButtons(vis, 4);
317  
    ret vis;
318  
  }
319  
320  
  JComponent screenCamPanel() {
321  
    ret centerAndSouthOrEast(horizontalLayout,
322  
      withTools(isPosterized),
323  
      watchScreenPane);
324  
  }
325  
  
326  
  JComponent screenCamPlusScriptPanel() enter {
327  
    print("screenCamPlusScriptPanel");
328  
    //ret watchScreenPane;
329  
    try {
330  
      var ide = screenCamScriptIDE = leftArrowScriptIDE();
331  
      ide.runButtonShouldBeEnabled = ->
332  
         eq(getText(ide.btnRun), "Stop")
333  
          || ide.runButtonShouldBeEnabled_base();
334  
      
335  
      ide.runButtonAction = -> {
336  
        if (eq(getText(ide.btnRun), "Stop"))
337  
          runningScreenCamScript = null;
338  
        else {
339  
          runningScreenCamScript = screenCamScriptIDE.parsedScript();
340  
          ide.showStatus("Running");
341  
        }
342  
        setText(ide.btnRun,
343  
          runningScreenCamScript == null ? "Run" : "Stop");
344  
      };
345  
      
346  
      ret centerAndSouthOrEast(horizontalLayout,
347  
        //withTools(
348  
          jhsplit(
349  
            jscroll_centered_borderless(isPosterized),
350  
            screenCamScriptIDE
351  
              .lvScript(dm_fieldLiveValue screenCamScript())
352  
              .visualize())
353  
        //, isPosterized)
354  
        , watchScreenPane);
355  
    } on fail e { print(e); }
356  
  }
357  
  
358  
  S speedInfo() {
359  
    ret "FPS " + fps + " idle " + remainingMS + " ms";
360  
  }
361  
  
362  
  S speedInfo_long() {
363  
    ret "Screen cam running at " + nFrames(fps) + "/second. " + n2(remainingMS) + " ms remaining per frame in first core"
364  
      + " (of targeted " + fpsTarget + " FPS)";
365  
  }
366  
  
367  
  bool useErrorHandling() { false; }
368  
  
369  
  S renderFunctionTimings() {
370  
    ret lines(ciSorted(map(functionTimings!, (f, avg) ->
371  
      firstToUpper(f) + ": " + n2(iround(nsToMicroseconds(avg!))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")")));
372  
  }
373  
  
374  
  transient long _runScript_idx;
375  
376  
  void _runScript() {
377  
    scriptRunner.parseAndRunOn(imageToRegions_finished.ii);
378  
  }
379  
  
380  
  bool shouldRunScript() {
381  
    ret isShowing(scriptRunner.scpScriptResult);
382  
  }
383  
  
384  
  void stepAnimation {
385  
    if (!animate) ret;
386  
    if (animation == null) {
387  
      animation = new AnimatedLine;
388  
      animation.start();
389  
    }
390  
    animation.nextFrame();
391  
    var img = whiteImage(animation.w, animation.h);
392  
    animation.setGraphics(createGraphics(img));
393  
    animation.paint();
394  
    isTestScreen?.setImage(img);
395  
    
396  
    var ii = bwIntegralImage_withMeta(img);
397  
    testScreenScriptRunner.parseAndRunOn(ii);
398  
  }
399  
  
400  
  JComponent testScreenPanel() {
401  
    ret centerAndSouthWithMargin(
402  
      hsplit(
403  
        northAndCenterWithMargin(centerAndEastWithMargin(
404  
          jlabel("Input"), dm_fieldCheckBox animate()),
405  
        jscroll_centered_borderless(isTestScreen)),
406  
        
407  
        northAndCenterWithMargin(centerAndEastWithMargin(
408  
          jlabel("Output"), testScreenScriptRunner.lblScore),
409  
        testScreenScriptRunner.scpScriptResult)
410  
      ),
411  
        
412  
      testScreenScriptRunner.scriptInputField()
413  
    );
414  
  }
415  
  
416  
  L popDownItems() {
417  
    ret ll(jCheckBoxMenuItem_dyn("Horizontal Layout",
418  
      -> horizontalLayout,
419  
      b -> setField(horizontalLayout := b)));
420  
  }
421  
  
422  
  void unvisualize {} // don't zero transient component fields
423  
  
424  
  void resetTimings { functionTimings.reset(); }
425  
  
426  
  // add tool side bar to image surface
427  
  JComponent withTools(
428  
    JComponent component default jscroll_centered_borderless(is),
429  
    ImageSurface is) {
430  
    ret centerAndEastWithMargin(component,
431  
      vstack(
432  
        verticalStrut(5),
433  
        jimageButtonScaledToWidth(16, #1103054, "Save screenshot in gallery", rThread saveScreenshotToGallery),
434  
        /*jPopDownButton_noText(
435  
          jCheckBoxMenuItem_dyn("Live scripting", -> liveScripting, b -> setLiveScripting(b)
436  
        ),*/
437  
      )
438  
    );
439  
  }
440  
  
441  
  class WatchTargetSelector {
442  
    JComboBox<WatchTarget> cb = jComboBox();
443  
    int screenCount, camCount;
444  
    
445  
    visualize {
446  
      updateList();
447  
      //print("Selecting watchTarget: " + watchTarget);
448  
      selectItem(cb, watchTarget);
449  
      main onChange(cb, watchTarget -> {
450  
        setField(+watchTarget);
451  
        //print("Chose watchTarget: " + GazelleScreenCam.this.watchTarget);
452  
      });
453  
      ret cb;
454  
    }
455  
    
456  
    void updateScreenCount() {
457  
      if (screenCount != screenCount())
458  
        updateList();
459  
    }
460  
461  
    /*void updateCamCount() pcall {
462  
      availableWebCams = listWebCams();
463  
      updateList();
464  
    }*/
465  
    
466  
    void updateList() swing {
467  
      setComboBoxItems(cb, makeWatchTargets());
468  
    }
469  
    
470  
    L<WatchTarget> makeWatchTargets() {
471  
      ret flattenToList(
472  
        countIteratorAsList_incl(1, screenCount = screenCount(),
473  
          i -> WatchScreen(i)),
474  
        new WatchMouse,
475  
        /*countIteratorAsList_incl(1, l(availableWebCams),
476  
          i -> new WatchWebCam(i))*/
477  
      );
478  
    }
479  
  }
480  
481  
  class SnPSelector {
482  
    settable new SnPSettings settings;
483  
    
484  
    event change;
485  
486  
    visualize {
487  
      var colors = jspinner(settings.colors, 2, 256);
488  
      main onChange(colors, -> {
489  
        settings.colors = intFromSpinner(colors);
490  
        change();
491  
      });
492  
      
493  
      var pixelRows = jPowersOfTwoSpinner(512, settings.pixelRows);
494  
      main onChange(pixelRows, -> {
495  
        settings.pixelRows = intFromSpinner(pixelRows);
496  
        change();
497  
      });
498  
      
499  
      ret hstack(
500  
        colors,
501  
        jlabel(" colors @ "),
502  
        pixelRows,
503  
        jlabel(" p"));
504  
    }
505  
  }
506  
  
507  
  JComponent wrapCRUD(SimpleCRUD_v2 crud, JComponent vis default crud.visualize()) {
508  
    ret crud == null ?: withTopAndBottomMargin(jRaisedSection(withMargin(vis)));
509  
  }
510  
  
511  
  File galleryDir() {
512  
    ret picturesDir(gazelle22_imagesSubDirName());
513  
  }
514  
  
515  
  void saveScreenshotToGallery enter {
516  
    var img = imageStream!;
517  
    saveImageWithCounter(galleryDir(), "Screenshot", img);
518  
  }
519  
  
520  
  GalleryImage addToGallery(File imgFile) {
521  
    if (!isImageFile(imgFile)) null;
522  
    var img = uniq(concepts, GalleryImage, path := imgFile);
523  
    //printVars("addToGallery", +imgFile, +img);
524  
    ret img;
525  
  }
526  
527  
  class StudyPanel {
528  
    new SnPSelector snpSelector;
529  
    GalleryImage image;
530  
    BufferedImage originalImage;
531  
    //ImageSurface isOriginal = stdImageSurface();
532  
    ImageSurface isOriginalWithRegions = stdImageSurface();
533  
    ImageSurface isPosterized = stdImageSurface();
534  
    SingleComponentPanel scp = singleComponentPanel();
535  
    SingleComponentPanel analysisPanel = singleComponentPanel();
536  
    SingleComponentPanel scpExampleCRUD = singleComponentPanel();
537  
    ConceptsComboBox<GalleryImage> cbImage = new(concepts, GalleryImage);
538  
    Gazelle22_ImageToRegions itr;
539  
    int iSelectedRegion;
540  
    SimpleCRUD_v2<SavedRegion> regionCRUD;
541  
    SimpleCRUD_v2<Example> exampleCRUD;
542  
543  
    *() {
544  
      //cbImage.sortTheList = l -> sortConceptsByIDDesc(l);
545  
      cbImage.sortTheList = l -> sortedByComparator(l, (a, b)
546  
        -> cmpAlphanumIC(fileName(a.path), fileName(b.path)));
547  
548  
      main onChangeAndNow(cbImage, img -> dm_q(me(), r {
549  
        image = img;
550  
        scp.setComponent(studyImagePanel());
551  
      }));
552  
553  
      isPosterized.removeAllTools();
554  
      isPosterized.onMousePositionChanged(r_dm_q(me(), l0 regionUpdate));
555  
556  
      imageSurfaceOnLeftMouseDown(isPosterized, pt -> dm_q(me(), r { chooseRegionAt(pt) }));
557  
558  
      snpSelector.onChange(r_dm_q(me(), l0 runSnP));
559  
    }
560  
561  
    void chooseRegionAt(Pt p) {
562  
      if (itr == null) ret;
563  
      iSelectedRegion = itr.regions.regionAt(p);
564  
565  
      if (iSelectedRegion > 0) {
566  
        var savedRegion = uniq_returnIfNew(concepts, SavedRegion,
567  
          +image,
568  
          snpSettings := snpSelector.settings.cloneMe(),
569  
          regionIndex := iSelectedRegion);
570  
571  
        // it's new, add values
572  
        if (savedRegion != null) {
573  
          print("Saved new region!");
574  
          var bitMatrix = toScanlineBitMatrix(itr.regions.regionBitMatrix(iSelectedRegion));
575  
          cset(savedRegion, +bitMatrix);
576  
        }
577  
      }
578  
      
579  
      regionUpdate();
580  
    }
581  
582  
    // load new image
583  
    JComponent studyImagePanel() { 
584  
      if (image == null) null;
585  
      originalImage = loadImage2(image.path);
586  
      if (originalImage == null) ret jcenteredlabel("Image not found");
587  
588  
      //isOriginal.setImage(originalImage);
589  
      isOriginalWithRegions.setImage(originalImage);
590  
591  
      iSelectedRegion = 0;
592  
      itr = new Gazelle22_ImageToRegions(functionTimings, originalImage, snpSelector.settings);
593  
      runSnP();
594  
595  
      regionCRUD = new SimpleCRUD_v2<SavedRegion>(concepts, SavedRegion);
596  
      regionCRUD.addFilter(+image);
597  
      regionCRUD
598  
        .showSearchBar(false)
599  
        .showAddButton(false)
600  
        .showEditButton(false)
601  
        .iconButtons(true);
602  
        
603  
      regionCRUD.itemToMap_inner2 = region -> {
604  
        var examples = conceptsWhere(concepts, Example, item := region);
605  
        
606  
        ret litorderedmap(
607  
          "Pixels" := region.bitMatrix == null ? "-" : n2(region.bitMatrix.pixelCount()),
608  
          //"Shape" := "TODO",
609  
          "Labels" := joinWithComma(map(examples, e -> e.label)),
610  
611  
          // TODO: scale using snpsettings
612  
          "Position" := region.bitMatrix == null ? "-" : region.bitMatrix.boundingBoxOfTrueBits());
613  
      };
614  
615  
      var regionCRUDComponent = regionCRUD.visualize();
616  
      regionCRUD.onSelectionChanged(l0 updateExampleCRUD);
617  
618  
      ret hsplit(
619  
        jtabs(
620  
          //"Image" := jscroll_centered_borderless(isOriginal),
621  
          "Image + regions" := jscroll_centered_borderless(isOriginalWithRegions),
622  
          "Posterized" := jscroll_centered_borderless(isPosterized),
623  
        ),
624  
        northAndCenterWithMargin(
625  
          analysisPanel,
626  
          hsplit(
627  
            jCenteredSection("Saved regions", regionCRUDComponent),
628  
            scpExampleCRUD)
629  
          ));
630  
    }
631  
632  
    void runSnP {
633  
      if (itr == null) ret;
634  
      itr.run();
635  
      regionUpdate();
636  
    }
637  
638  
    void regionUpdate {
639  
      if (itr == null) ret;
640  
641  
      var pixels = itr.posterized.getRGBPixels();
642  
      
643  
      // hovering region marked green
644  
      g22_highlightRegion(pixels, isPosterized, itr, showRegionsAsOutline);
645  
646  
      // selected region marked blue
647  
      itr.regions.markRegionInPixelArray(pixels, iSelectedRegion, 0xFFADD8E6);
648  
649  
      var highlighted = bufferedImage(pixels, itr.posterized.getWidth(), itr.posterized.getHeight());
650  
651  
      isPosterized.setImage(highlighted);
652  
      isPosterized.performAutoZoom(); // seems to be necessary for some reason
653  
654  
      updateAnalysis();
655  
    }
656  
657  
    void updateAnalysis {
658  
      /*new LS lines;
659  
      lines.add(nRegions(itr.regions.regionCount()));
660  
      lines.add("Selected region: " + iSelectedRegion);
661  
      S text = lines_rtrim(lines);
662  
      analysisPanel.setComponent(jLabel(text)));*/
663  
    }
664  
665  
    void updateExampleCRUD {
666  
      var region = regionCRUD.selected();
667  
      if (region == null) ret with scpExampleCRUD.set(null);
668  
      
669  
      exampleCRUD = new SimpleCRUD_v2<Example>(concepts, Example);
670  
      exampleCRUD.entityName = -> "label for region";
671  
      exampleCRUD.addFilter(item := region);
672  
      exampleCRUD.showSearchBar(false);
673  
      exampleCRUD.iconButtons(true);
674  
      scpExampleCRUD.set(jCenteredSection("Labels for region",
675  
        exampleCRUD.visualize()));
676  
    }
677  
678  
    void importImage {
679  
      new JFileChooser fc;
680  
      if (fc.showOpenDialog(cbImage) == JFileChooser.APPROVE_OPTION) {
681  
        File file = fc.getSelectedFile().getAbsoluteFile();
682  
        if (!isImageFile(file)) ret with infoMessage("Not an image file");
683  
        var img = addToGallery(file);
684  
        waitUntil(250, 5.0, -> comboBoxContainsItem(cbImage, img));
685  
        setSelectedItem(cbImage, img);
686  
      }
687  
    }
688  
689  
    visual
690  
      jRaisedSection(northAndCenterWithMargins(
691  
        centerAndEast(withLabel("Study", cbImage),
692  
          hstack(
693  
            jlabel(" in "),
694  
            snpSelector.visualize(),
695  
            horizontalStrut(10),
696  
            jPopDownButton_noText(
697  
              "Import image...", rThreadEnter importImage,
698  
            ),
699  
            )),
700  
        scp));
701  
  } // end of StudyPanel
702  
703  
  void initUIURLs {
704  
    uiURLs.put("Main Tabs", ->
705  
      horizontalLayout ? withMargin(mainTabs) : withSideMargin(mainTabs));
706  
      
707  
    // add main tabs to UI URLs
708  
    for (S tab : tabNames(mainTabs)) {
709  
      reMutable tab = dropTrailingBracketedCount(tab);
710  
      uiURLs.put(tab, -> {
711  
        int i = indexOfTabNameWithoutTrailingCount(mainTabs, tab);
712  
        if (i < 0) ret jcenteredlabel("Hmm. Tab not found");
713  
        selectTab(mainTabs, i);
714  
        ret mainTabs;
715  
      });
716  
    }
717  
718  
    uiURLs.put("Screen Cam FPS", -> jFullCenter(
719  
      vstackWithSpacing(
720  
        jCenteredLabel("FPS target (frames per second) for screen cam:"),
721  
        jFullCenter(dm_spinner fpsTarget(1, 60)),
722  
        jCenteredLabel("(You can lower this value if you have a slower computer)"))));
723  
724  
    uiURLs.put("Timings", -> {
725  
      JTextArea taTimings = jTextArea_noUndo();
726  
      awtEveryAndNow(taTimings, .5, r {
727  
        setText(taTimings, renderFunctionTimings())
728  
      });
729  
      ret withRightAlignedButtons(taTimings,
730  
        Reset := r resetTimings);
731  
    });
732  
733  
    uiURLs.put("Test Screen" := -> testScreenPanel());
734  
735  
    //uiURLs.put("Operators" := -> operatorsPanel());
736  
737  
    uiURLs.put("Left Arrow Script" := -> leftArrowScriptPanel());
738  
739  
    uiURLs.put("Settings" := -> settingsPanel());
740  
741  
    uiURLs.put("System Info" := -> systemInfoPanel());
742  
743  
    uiURLs.put("Web Cam" := -> webCamPanel());
744  
745  
    uiURLs.put("Labels" := -> wrapCRUD(labelCRUD));
746  
747  
    uiURLs.put(WithToolTip("Screen Cam + Linear Script", "Run a simple (linear) Gazelle V script")
748  
      := -> withBottomMargin(scriptRunner.scriptAndResultPanel()));
749  
      
750  
    uiURLs.put(WithToolTip("Left Arrow Script", "Run a \"left-arrow script\"")
751  
      := -> withBottomMargin(leftArrowScriptPanel()));
752  
    // add ui urls above this line
753  
  }
754  
755  
  JComponent settingsPanel() {
756  
    var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray")));
757  
    onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray)));
758  
    ret jscroll(makeForm3( 
759  
      "Minimize to tray", toolTip("Remove Gazelle from task bar when minimized (click Gazelle icon in system tray to reactivate)", cbMinimizeToTray),
760  
      "Access web cams", dm_checkBox webCamAccessEnabled(),
761  
    ));
762  
  }
763  
764  
  JComponent systemInfoPanel() {
765  
    var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray")));
766  
    onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray)));
767  
    ret jscrollVertical(makeForm3( 
768  
      "Java Version", jlabel(javaVersion()),
769  
      "Gazelle Jar", jlabel(renderFileInfo(getBytecodePathForClass(this))),
770  
      "Compilation Date", jlabel(or2(loadTextFileResource(classLoader(this), "compilation-date.txt"), "unknown")),
771  
      "Gazelle Count" := toolTip("How many Gazelles are running in the world",
772  
        jLiveValueLabel((LiveValue) dm_callOSOpt lvComputerCount())),
773  
    ));
774  
  }
775  
776  
  JComponent operatorsPanel() {
777  
    ret jcenteredlabel("TODO");
778  
  }
779  
780  
  JLeftArrowScriptIDE leftArrowScriptIDE() {
781  
    new JLeftArrowScriptIDE ide;
782  
    ide.modifyParser = parser -> parser.allowTheWorld(mc(), utils.class);
783  
    ret ide;    
784  
  }
785  
786  
  JComponent leftArrowScriptPanel() {
787  
    var ide = leftArrowScriptIDE();
788  
    ide.lvScript(dm_fieldLiveValue newScript());
789  
    ret ide.visualize();
790  
  }
791  
792  
  JComponent javaPanel() enter {
793  
    var scpResult = singleComponentPanel();
794  
    
795  
    new JMiniJavaIDE ide;
796  
    ide.extraClassMembers = script -> {
797  
      LS tok = javaTok(script);
798  
799  
      if (contains(tok, "draw")) ret [[
800  
        import java.awt.*;
801  
        import java.awt.image.*;
802  
        
803  
        interface SimpleRenderable {
804  
          void renderOn(Graphics2D g);
805  
        }
806  
        
807  
        static BufferedImage draw(int w, int h, SimpleRenderable r) {
808  
          BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
809  
          Graphics2D g = img.createGraphics();
810  
          g.setColor(Color.white);
811  
          g.fillRect(0, 0, w, h);
812  
          g.setColor(Color.black);
813  
          r.renderOn(g);
814  
          return img;
815  
        }
816  
      ]];
817  
        
818  
      ret "";
819  
    };
820  
821  
    ide.callCompiledObject = o -> {
822  
      O result = ide.callCompiledObject_base(o);
823  
      if (result cast BufferedImage)
824  
        scpResult.set(jscroll_centered_borderless(stdImageSurface(result)));
825  
      ret result;
826  
    };
827  
    
828  
    ide.lvScript(dm_fieldLiveValue javaCode());
829  
    ret jhsplit(
830  
      jCenteredSection("Image will show here", scpResult),
831  
      ide.visualize());
832  
  }
833  
834  
  JComponent webCamPanel() {
835  
    if (cbWebCam == null) {
836  
      var cams = listWebCams();
837  
      cbWebCam = jTypedComboBox(cams,
838  
        findWebCamByName(cams, webCamName));
839  
    }
840  
841  
    if (scpWebCamImage == null) scpWebCamImage = singleComponentPanel();
842  
    
843  
    ret northAndCenterWithMargins(
844  
      centerAndEastWithMargin(
845  
        withLabel("Cam", cbWebCam),
846  
        jline(
847  
          jbutton("Start", rThreadEnter startWebCam),
848  
          jbutton("Stop", rThreadEnter stopWebCam)
849  
        )),
850  
      scpWebCamImage);
851  
  }
852  
853  
  void stopWebCam {
854  
    if (webCamPanel != null) {
855  
      webCamPanel.stop();
856  
      webCamPanel = null;
857  
      scpWebCamImage?.clear();
858  
      backgroundProcessesUI.remove("Web Cam");
859  
    }
860  
  }
861  
862  
  void startWebCam {
863  
    temp tempInfoBox("Starting Web Cam");
864  
    stopWebCam();
865  
    var cam = getSelectedItem_typed(cbWebCam);
866  
    setField(webCamName := cam?.getName());
867  
    if (cam != null) {
868  
      scpWebCamImage.set(webCamPanel = new WebcamPanel(cam, true));
869  
      backgroundProcessesUI.add("Web Cam");
870  
    }
871  
  }
872  
  
873  
  void forgetMissingImages {
874  
    int n = l(deleteConcepts(GalleryImage, img -> !img.imageExists()));
875  
    infoBox(n == 0 ? "Nothing to forget" : "Forgot " + nImages(n));
876  
  }
877  
} // end of module
878  
879  
concept Label > ConceptWithGlobalID {
880  
  S name;
881  
  //new RefL examples;
882  
  
883  
  toString { ret /*"Label " +*/ name; }
884  
}
885  
886  
concept GalleryImage {
887  
  File path;
888  
889  
  toString { ret /*"[" + id + "] " +*/ fileName(path); }
890  
891  
  bool imageExists() { ret fileExists(path); }
892  
}
893  
894  
concept SavedRegion {
895  
  new Ref image; // e.g. a GalleryImage
896  
  SnPSettings snpSettings;
897  
  int regionIndex; // region number relative to snpSettings
898  
  //Rect bounds; // get it from bitMatrix instead
899  
  ScanlineBitMatrix bitMatrix;
900  
  //new RefL<Label> labels;
901  
}
902  
903  
concept Example {
904  
  new Ref<Label> label;
905  
  new Ref item; // e.g. a SavedRegion
906  
  double confidence = 1;
907  
}
908  
909  
concept IfThenTheory {
910  
  new Ref if_;
911  
  new Ref then;
912  
}
913  
914  
sclass WatchTarget {}
915  
916  
// screenNr: 1 = screen 1 etc
917  
srecord WatchScreen(int screenNr) > WatchTarget {
918  
  toString { ret "Screen " + screenNr; }
919  
}
920  
921  
srecord WatchMouse(int width, int height) > WatchTarget {
922  
  WatchMouse() {
923  
    height = 256;
924  
    width = iround(height*16.0/9);
925  
  }
926  
  
927  
  toString { ret "Mouse"; }
928  
}
929  
930  
srecord WatchWebCam(int camNr) > WatchTarget {
931  
  toString { ret "Webcam " + camNr; }
932  
}
933  
934  
!include once #1034034 // Gazelle 22 Function Include for Scripts

Author comment

Began life as a copy of #1033862

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1034151
Snippet name: Gazelle Screen Cam / Gazelle 22 Module [backup]
Eternal ID of this version: #1034151/1
Text MD5: 1babdf853e6fc6e4bc50dd29748e8cd9
Author: stefan
Category: javax / gazelle v
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-01-24 17:16:48
Source code size: 29721 bytes / 934 lines
Pitched / IR pitched: No / No
Views / Downloads: 65 / 75
Referenced in: [show references]