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

1046
LINES

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

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 4324K of libraries. Click here for Pure Java version (31276L/171K).

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

No comments. add comment

Snippet ID: #1034316
Snippet name: Gazelle Screen Cam / Gazelle 22 Module [backup]
Eternal ID of this version: #1034316/1
Text MD5: 4efddfa15a929567a92d9156a4ee5669
Transpilation MD5: 87de8611e98d3a315440d5d42be9ef10
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-02-02 00:15:22
Source code size: 33472 bytes / 1046 lines
Pitched / IR pitched: No / No
Views / Downloads: 69 / 175
Referenced in: [show references]