Warning : session_start(): open(/var/lib/php/sessions/sess_0p3c19qb9lhvo3b9jfuc0k30rc, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning : session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
// Note: It's ok again to use db_mainConcepts()
!include early #1033884 // Compact Module Include Gazelle V [dev version]
module GazelleScreenCam {
!include early #1025212 // +Enabled without visualization
int pixelRows = 128, colors = 8;
S script = "64p 8c gradientImage";
S testScreenScript;
S newScript;
S screenCamScript;
bool animate = true;
bool horizontalLayout; // flat layout
int fpsTarget = 20;
WatchTarget watchTarget;
transient ImageSurface isPosterized, isRegions, isTestScreen;
transient new ScreenCamStream imageStream;
transient Gazelle22_ImageToRegions imageToRegions_finished;
transient new DoubleFPSCounter fpsCounter;
transient int fps;
//transient ScreenSelectorRadioButtons screenSelector;
transient WatchTargetSelector watchTargetSelector;
transient new RollingAverage remainingMSPerFrame;
transient int remainingMS;
transient new FunctionTimings functionTimings;
transient ReliableSingleThread rstRunScript = dm_rst(me(), r _runScript);
transient JGazelleVScriptRunner scriptRunner;
transient JGazelleVScriptRunner testScreenScriptRunner;
transient Animation animation;
transient UIURLSystem uiURLs;
// set by host
transient Concepts concepts;
S uiURL = "Main Tabs";
transient FileWatchService fileWatcher;
transient SimpleCRUD_v2 labelCRUD;
transient SimpleCRUD_v2 imageCRUD;
transient JGallery gallery;
transient JComponent galleryComponent;
transient FlexibleRateTimer screenCamTimer;
transient SingleComponentPanel scpMain;
transient JTabbedPane tabs;
transient bool showRegionsAsOutline = true;
transient JComponent watchScreenPane;
transient S screenCamRecognitionOutput;
start {
dm_onFieldChange horizontalLayout(
//r dm_revisualize // deh buggy
r dm_reload
);
// non-standalone mode (doesn't work yet)
if (concepts == null) {
printWithMS("Starting DB");
db();
concepts = db_mainConcepts();
} else
assertSame(concepts, db_mainConcepts());
// make indexes
indexConceptField(concepts, GalleryImage, "path");
indexConceptField(concepts, Example, "item");
// update count in tab when tab isn't selected
onConceptChanges(concepts, -> {
labelCRUD?.updateEnclosingTabTitle();
//imageCRUD?.updateEnclosingTabTitle();
updateEnclosingTabTitleWithCount(galleryComponent, countConcepts(GalleryImage));
});
uiURLs = new UIURLSystem(me(), dm_fieldLiveValue uiURL());
scriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue script(me()));
testScreenScriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue testScreenScript(me()));
printWithMS("Making image stream");
imageStream.onNewElement(img -> {
fpsCounter.inc();
setField(fps := iround(fpsCounter!));
// perform analysis on screen cam image
// new G22_ImageAnalysis screenCamImageAnalysis;
assertTrue("meta", getMetaSrc(img) instanceof ScreenShotMeta);
Gazelle22_ImageToRegions itr = new(functionTimings, img, new SnPSettings(pixelRows, colors));
itr.run();
imageToRegions_finished = itr;
// run "linear" script on image if any
if (shouldRunScript()) rstRunScript.go();
// make textual result of analysis
S text = nRegions(itr.regions.regionCount());
setField(screenCamRecognitionOutput := text);
// display image after analysis so we can highlight a region
g22_renderPosterizedHighlightedImage(isPosterized, itr, showRegionsAsOutline);
});
printWithMS("Starting screen cam");
ownResource(screenCamTimer = new FlexibleRateTimer(fpsTarget, rEnter {
if (!enabled) ret;
watchTargetSelector?.updateScreenCount();
Timestamp deadline = tsNowPlusMS(1000/fpsTarget);
if (watchTarget cast WatchScreen)
imageStream.useScreen(watchTarget.screenNr-1);
else if (watchTarget cast WatchMouse)
imageStream.area(mouseArea(watchTarget.width, watchTarget.height));
imageStream.step();
long remaining = deadline.minus(tsNow());
remainingMSPerFrame.add(remaining);
setField(remainingMS := iround(remainingMSPerFrame!));
}));
screenCamTimer.start();
dm_onFieldChange fpsTarget(-> screenCamTimer.setFrequencyImmediately(fpsTarget));
printWithMS("Starting dir watcher");
startDirWatcher();
printWithMS("Gathering images from disk");
for (f : allImageFiles(galleryDir()))
addToGallery(f);
printWithMS("Got dem images");
// OSHI adds 4.5 MB to the jar...
//doAfter(5.0, r { print("Process size: ", toM_str(oshi_currentProcessResidentSize_noZGCFix())) });
}
void startDirWatcher {
fileWatcher = new FileWatchService;
fileWatcher.addRecursiveListener(picturesDir(), file -> {
if (!isImageFile(file)) ret;
addToGallery(file);
});
}
ImageSurface stdImageSurface() {
var is = pixelatedImageSurface().setAutoZoomToDisplay(true).repaintInThread(false);
new ImageSurface_PositionToolTip(is);
ret is;
}
visualize {
gallery = new JGallery;
galleryComponent = gallery.visualize();
new AWTOnConceptChanges(concepts, galleryComponent, -> {
gallery.setImageFiles(map(list(GalleryImage), i -> i.path));
}).install();
/*screenSelector = new ScreenSelectorRadioButtons(dm_fieldLiveValue screenNr());
screenSelector.compactLayout(true);
screenSelector.hideIfOnlyOne(true);
screenSelector.screenLabel("");*/
isPosterized = stdImageSurface();
//isRegions = stdImageSurface();
isTestScreen = stdImageSurface();
// when test screen is visible, do the animation
awtEvery(isTestScreen, 1000/20, r stepAnimation);
//print("Labels: " + list(concepts, Label));
labelCRUD = new SimpleCRUD_v2(concepts, Label);
labelCRUD.hideFields("globalID");
labelCRUD.addCountToEnclosingTab(true);
labelCRUD.itemToMap_inner2 = l
-> litorderedmap(
"Name" := l.name,
"# Examples" := n2(countConcepts(concepts, Example, label := l)));
imageCRUD = new SimpleCRUD_v2(concepts, GalleryImage);
imageCRUD.addCountToEnclosingTab(true);
imageCRUD.itemToMap_inner2 = img
-> litorderedmap(
"File" := fileName(img.path),
"Folder" := dirPath(img.path));
// main visual
var studyPanel = new StudyPanel;
watchTargetSelector = new WatchTargetSelector;
watchScreenPane = borderlessScrollPane(jHigherScrollPane(
jfullcenter(vstack(
withLeftAndRightMargin(hstack(
dm_rcheckBox enabled("Watch"),
watchTargetSelector.visualize(),
jlabel(" in "),
withLabelToTheRight("colors @ ", dm_spinner colors(2, 256)),
withLabelToTheRight("p", dm_powersOfTwoSpinner pixelRows(512)),
)),
verticalStrut(2),
withSideMargins(centerAndEastWithMargin(
dm_fieldLabel screenCamRecognitionOutput(),
dm_transientCalculatedToolTip speedInfo_long(rightAlignLabel(dm_transientCalculatedLabel speedInfo()))
)),
))));
tabs = scrollingTabs(jTopOrLeftTabs(horizontalLayout,
"Screen Cam" := jOnDemand screenCamPanel(),
"Screen Cam + Script" := jOnDemand screenCamPlusScriptPanel(),
WithToolTip("Study", "Here you can analyze gallery images")
:= withTopAndBottomMargin(studyPanel.visualize()),
WithToolTip("Simple Script", "Run a simple (linear) Gazelle V script")
:= withBottomMargin(scriptRunner.scriptAndResultPanel()),
WithToolTip("Full Script", "Run a \"left-arrow script\"")
:= withBottomMargin(newScriptPanel()),
WithToolTip("Gallery", "Gallery view with preview images")
:= withBottomMargin(galleryComponent),
WithToolTip("Gallery 2", "Gallery view with more functions (delete etc)")
:= wrapCRUD(imageCRUD),
WithToolTip("Labels", "Manage labels (image markers)")
:= wrapCRUD(labelCRUD),
));
var cbEnabled = toolTip("Switch screen cam on or off", dm_checkBox enabled(""));
var lblScreenCam = setToolTip("Show scaled down and color-reduced screen image",
jlabel("Screen Cam"));
tabComponentClickFixer(lblScreenCam);
var screenCamTab = hstackWithSpacing(cbEnabled, lblScreenCam);
replaceTabTitleComponent(tabs, "Screen Cam", screenCamTab);
// for tab titles
labelCRUD.update();
imageCRUD.update();
initUIURLs();
var urlBar = uiURLs.urlBar();
setToolTip(uiURLs.comboBox, "UI navigation system (partially populated)");
scpMain = singleComponentPanel();
uiURLs.scp(scpMain);
uiURLs.showUIURL(uiURL);
var vis = northAndCenter(
withSideAndTopMargin(urlBar),
//centerAndSouthOrEast(horizontalLayout,
/*withBottomMargin*/(scpMain),
/* watchScreenPane
)*/
);
setHorizontalMarginForAllButtons(vis, 4);
ret vis;
}
JComponent screenCamPanel() {
ret centerAndSouthOrEast(horizontalLayout,
withTools(isPosterized),
watchScreenPane);
}
JComponent screenCamPlusScriptPanel() enter {
print("screenCamPlusScriptPanel");
//ret watchScreenPane;
try {
ret centerAndSouthOrEast(horizontalLayout,
//withTools(
jhsplit(
isPosterized,
leftArrowScriptIDE()
.lvScript(dm_fieldLiveValue screenCamScript())
.visualize())
//, isPosterized)
, watchScreenPane);
} on fail e { print(e); }
}
S speedInfo() {
ret "FPS " + fps + " idle " + remainingMS + " ms";
}
S speedInfo_long() {
ret "Screen cam running at " + nFrames(fps) + "/second. " + n2(remainingMS) + " ms remaining per frame in first core"
+ " (of targeted " + fpsTarget + " FPS)";
}
bool useErrorHandling() { false; }
S renderFunctionTimings() {
ret lines(ciSorted(map(functionTimings!, (f, avg) ->
firstToUpper(f) + ": " + n2(iround(nsToMicroseconds(avg!))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")")));
}
transient long _runScript_idx;
void _runScript() {
scriptRunner.parseAndRunOn(imageToRegions_finished.ii);
}
bool shouldRunScript() {
ret isShowing(scriptRunner.scpScriptResult);
}
void stepAnimation {
if (!animate) ret;
if (animation == null) {
animation = new AnimatedLine;
animation.start();
}
animation.nextFrame();
var img = whiteImage(animation.w, animation.h);
animation.setGraphics(createGraphics(img));
animation.paint();
isTestScreen?.setImage(img);
var ii = bwIntegralImage_withMeta(img);
testScreenScriptRunner.parseAndRunOn(ii);
}
JComponent testScreenPanel() {
ret centerAndSouthWithMargin(
hsplit(
northAndCenterWithMargin(centerAndEastWithMargin(
jlabel("Input"), dm_fieldCheckBox animate()),
jscroll_centered_borderless(isTestScreen)),
northAndCenterWithMargin(centerAndEastWithMargin(
jlabel("Output"), testScreenScriptRunner.lblScore),
testScreenScriptRunner.scpScriptResult)
),
testScreenScriptRunner.scriptInputField()
);
}
L popDownItems() {
ret ll(jCheckBoxMenuItem_dyn("Horizontal Layout",
-> horizontalLayout,
b -> setField(horizontalLayout := b)));
}
void unvisualize {} // don't zero transient component fields
void resetTimings { functionTimings.reset(); }
// add tool side bar to image surface
JComponent withTools(
JComponent component default jscroll_centered_borderless(is),
ImageSurface is) {
ret centerAndEastWithMargin(component,
vstack(
verticalStrut(5),
jimageButtonScaledToWidth(16, #1103054, "Save screenshot in gallery", rThread saveScreenshotToGallery),
/*jPopDownButton_noText(
jCheckBoxMenuItem_dyn("Live scripting", -> liveScripting, b -> setLiveScripting(b)
),*/
)
);
}
class WatchTargetSelector {
JComboBox cb = jComboBox();
int screenCount;
visualize {
updateList();
//print("Selecting watchTarget: " + watchTarget);
selectItem(cb, watchTarget);
main onChange(cb, watchTarget -> {
setField(+watchTarget);
//print("Chose watchTarget: " + GazelleScreenCam.this.watchTarget);
});
ret cb;
}
void updateScreenCount() {
if (screenCount != screenCount())
updateList();
}
void updateList() swing {
setComboBoxItems(cb, makeWatchTargets());
}
L makeWatchTargets() {
ret flattenToList(
countIteratorAsList_incl(1, screenCount = screenCount(), i -> WatchScreen(i)),
new WatchMouse
);
}
}
class SnPSelector {
settable new SnPSettings settings;
event change;
visualize {
var colors = jspinner(settings.colors, 2, 256);
main onChange(colors, -> {
settings.colors = intFromSpinner(colors);
change();
});
var pixelRows = jPowersOfTwoSpinner(512, settings.pixelRows);
main onChange(pixelRows, -> {
settings.pixelRows = intFromSpinner(pixelRows);
change();
});
ret hstack(
colors,
jlabel(" colors @ "),
pixelRows,
jlabel(" p"));
}
}
JComponent wrapCRUD(SimpleCRUD_v2 crud) {
ret crud == null ?: withTopAndBottomMargin(jRaisedSection(withMargin(crud.make_dontStartBots())));
}
File galleryDir() {
ret picturesDir(gazelle22_imagesSubDirName());
}
void saveScreenshotToGallery enter {
var img = imageStream!;
saveImageWithCounter(galleryDir(), "Screenshot", img);
}
GalleryImage addToGallery(File imgFile) {
if (!isImageFile(imgFile)) null;
var img = uniq(concepts, GalleryImage, path := imgFile);
//printVars("addToGallery", +imgFile, +img);
ret img;
}
class StudyPanel {
new SnPSelector snpSelector;
GalleryImage image;
BufferedImage originalImage;
//ImageSurface isOriginal = stdImageSurface();
ImageSurface isOriginalWithRegions = stdImageSurface();
ImageSurface isPosterized = stdImageSurface();
SingleComponentPanel scp = singleComponentPanel();
SingleComponentPanel analysisPanel = singleComponentPanel();
SingleComponentPanel scpExampleCRUD = singleComponentPanel();
ConceptsComboBox cbImage = new(concepts, GalleryImage);
Gazelle22_ImageToRegions itr;
int iSelectedRegion;
SimpleCRUD_v2 regionCRUD;
SimpleCRUD_v2 exampleCRUD;
*() {
//cbImage.sortTheList = l -> sortConceptsByIDDesc(l);
cbImage.sortTheList = l -> sortedByComparator(l, (a, b)
-> cmpAlphanumIC(fileName(a.path), fileName(b.path)));
main onChangeAndNow(cbImage, img -> dm_q(me(), r {
image = img;
scp.setComponent(studyImagePanel());
}));
isPosterized.removeAllTools();
isPosterized.onMousePositionChanged(r_dm_q(me(), l0 regionUpdate));
imageSurfaceOnLeftMouseDown(isPosterized, pt -> dm_q(me(), r { chooseRegionAt(pt) }));
snpSelector.onChange(r_dm_q(me(), l0 runSnP));
}
void chooseRegionAt(Pt p) {
if (itr == null) ret;
iSelectedRegion = itr.regions.regionAt(p);
if (iSelectedRegion > 0) {
var savedRegion = uniq_returnIfNew(concepts, SavedRegion,
+image,
snpSettings := snpSelector.settings.cloneMe(),
regionIndex := iSelectedRegion);
// it's new, add values
if (savedRegion != null) {
print("Saved new region!");
var bitMatrix = toScanlineBitMatrix(itr.regions.regionBitMatrix(iSelectedRegion));
cset(savedRegion, +bitMatrix);
}
}
regionUpdate();
}
// load new image
JComponent studyImagePanel() {
if (image == null) null;
originalImage = loadImage2(image.path);
if (originalImage == null) ret jcenteredlabel("Image not found");
//isOriginal.setImage(originalImage);
isOriginalWithRegions.setImage(originalImage);
iSelectedRegion = 0;
itr = new Gazelle22_ImageToRegions(functionTimings, originalImage, snpSelector.settings);
runSnP();
regionCRUD = new SimpleCRUD_v2(concepts, SavedRegion);
regionCRUD.addFilter(+image);
regionCRUD
.showSearchBar(false)
.showAddButton(false)
.showEditButton(false);
regionCRUD.itemToMap_inner2 = region -> {
var examples = conceptsWhere(concepts, Example, item := region);
ret litorderedmap(
"Pixels" := region.bitMatrix == null ? "-" : n2(region.bitMatrix.pixelCount()),
//"Shape" := "TODO",
"Labels" := joinWithComma(map(examples, e -> e.label)),
// TODO: scale using snpsettings
"Position" := region.bitMatrix == null ? "-" : region.bitMatrix.boundingBoxOfTrueBits());
};
var regionCRUDComponent = regionCRUD.make_dontStartBots();
regionCRUD.onSelectionChanged(l0 updateExampleCRUD);
ret hsplit(
jtabs(
//"Image" := jscroll_centered_borderless(isOriginal),
"Image + regions" := jscroll_centered_borderless(isOriginalWithRegions),
"Posterized" := jscroll_centered_borderless(isPosterized),
),
northAndCenterWithMargin(
analysisPanel,
hsplit(
jCenteredSection("Saved regions", regionCRUDComponent),
scpExampleCRUD)
));
}
void runSnP {
if (itr == null) ret;
itr.run();
regionUpdate();
}
void regionUpdate {
if (itr == null) ret;
var pixels = itr.posterized.getRGBPixels();
// hovering region marked green
g22_highlightRegion(pixels, isPosterized, itr, showRegionsAsOutline);
// selected region marked blue
itr.regions.markRegionInPixelArray(pixels, iSelectedRegion, 0xFFADD8E6);
var highlighted = bufferedImage(pixels, itr.posterized.getWidth(), itr.posterized.getHeight());
isPosterized.setImage(highlighted);
isPosterized.performAutoZoom(); // seems to be necessary for some reason
updateAnalysis();
}
void updateAnalysis {
/*new LS lines;
lines.add(nRegions(itr.regions.regionCount()));
lines.add("Selected region: " + iSelectedRegion);
S text = lines_rtrim(lines);
analysisPanel.setComponent(jLabel(text)));*/
}
void updateExampleCRUD {
var region = regionCRUD.selected();
if (region == null) ret with scpExampleCRUD.set(null);
exampleCRUD = new SimpleCRUD_v2(concepts, Example);
exampleCRUD.entityName = -> "label for region";
exampleCRUD.addFilter(item := region);
exampleCRUD.showSearchBar(false);
scpExampleCRUD.set(jCenteredSection("Labels for region",
exampleCRUD.make_dontStartBots()));
}
void importImage {
new JFileChooser fc;
if (fc.showOpenDialog(cbImage) == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile().getAbsoluteFile();
if (!isImageFile(file)) ret with infoMessage("Not an image file");
var img = addToGallery(file);
waitUntil(250, 5.0, -> comboBoxContainsItem(cbImage, img));
setSelectedItem(cbImage, img);
}
}
visual
jRaisedSection(northAndCenterWithMargins(
centerAndEast(withLabel("Study", cbImage),
hstack(
jlabel(" in "),
snpSelector.visualize(),
horizontalStrut(10),
jPopDownButton_noText(
"Import image...", rThreadEnter importImage,
),
)),
scp));
} // end of StudyPanel
void initUIURLs {
uiURLs.put("Main Tabs", ->
horizontalLayout ? withMargin(tabs) : withSideMargin(tabs));
uiURLs.put("Screen Cam FPS", -> jFullCenter(
vstackWithSpacing(
jCenteredLabel("FPS target (frames per second) for screen cam:"),
jFullCenter(dm_spinner fpsTarget(1, 60)),
jCenteredLabel("(You can lower this value if you have a slower computer)"))));
uiURLs.put("Timings", -> {
JTextArea taTimings = jTextArea_noUndo();
awtEveryAndNow(taTimings, .5, r {
setText(taTimings, renderFunctionTimings())
});
ret withRightAlignedButtons(taTimings,
Reset := r resetTimings);
});
uiURLs.put("Test Screen" := -> testScreenPanel());
uiURLs.put("Operators" := -> operatorsPanel());
//uiURLs.put("New Script" := -> newScriptPanel());
// add more ui urls here
}
JComponent operatorsPanel() {
ret jcenteredlabel("TODO");
}
JLeftArrowScriptIDE leftArrowScriptIDE() {
new JLeftArrowScriptIDE ide;
ide.modifyParser = parser -> parser.allowTheWorld(mc(), utils.class);
ret ide;
}
JComponent newScriptPanel() {
var ide = leftArrowScriptIDE();
ide.lvScript(dm_fieldLiveValue newScript());
ret ide.visualize();
}
} // end of module
concept Label > ConceptWithGlobalID {
S name;
//new RefL examples;
toString { ret /*"Label " +*/ name; }
}
concept GalleryImage {
File path;
toString { ret /*"[" + id + "] " +*/ fileName(path); }
}
concept SavedRegion {
new Ref image; // e.g. a GalleryImage
SnPSettings snpSettings;
int regionIndex; // region number relative to snpSettings
//Rect bounds; // get it from bitMatrix instead
ScanlineBitMatrix bitMatrix;
//new RefL labels;
}
concept Example {
new Ref label;
new Ref item; // e.g. a SavedRegion
double confidence = 1;
}
concept IfThenTheory {
new Ref if_;
new Ref then;
}
sclass WatchTarget {}
// screenNr: 1 = screen 1 etc
srecord WatchScreen(int screenNr) > WatchTarget {
toString { ret "Screen " + screenNr; }
}
srecord WatchMouse(int width, int height) > WatchTarget {
WatchMouse() {
height = 256;
width = iround(height*16.0/9);
}
toString { ret "Mouse"; }
}
/*asclass RegionPaintMode {
}
sclass RegionPaintMode_Normal > RegionPaintMode {
}
sclass RegionPaintMode_Outline > RegionPaintMode {
}*/
!include once #1034034 // Gazelle 22 Function Include for Scripts