Skip to content

Commit 289a3b0

Browse files
committed
Add settings dialog with inference server setup, add torch serve model-names fetching service via REST client, update scss, close progress-dialogs on service success.
1 parent dec2a6a commit 289a3b0

File tree

15 files changed

+790
-199
lines changed

15 files changed

+790
-199
lines changed

src/main/java/com/github/mfl28/boundingboxeditor/controller/Controller.java

Lines changed: 105 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,21 @@
1919
package com.github.mfl28.boundingboxeditor.controller;
2020

2121
import com.github.mfl28.boundingboxeditor.model.Model;
22-
import com.github.mfl28.boundingboxeditor.model.data.*;
22+
import com.github.mfl28.boundingboxeditor.model.data.ImageAnnotation;
23+
import com.github.mfl28.boundingboxeditor.model.data.ImageMetaData;
24+
import com.github.mfl28.boundingboxeditor.model.data.IoMetaData;
25+
import com.github.mfl28.boundingboxeditor.model.data.ObjectCategory;
2326
import com.github.mfl28.boundingboxeditor.model.io.*;
24-
import com.github.mfl28.boundingboxeditor.model.io.results.BoundingBoxPredictionResult;
25-
import com.github.mfl28.boundingboxeditor.model.io.results.IOResult;
26-
import com.github.mfl28.boundingboxeditor.model.io.results.ImageAnnotationImportResult;
27-
import com.github.mfl28.boundingboxeditor.model.io.results.ImageMetaDataLoadingResult;
28-
import com.github.mfl28.boundingboxeditor.model.io.services.BoundingBoxPredictorService;
29-
import com.github.mfl28.boundingboxeditor.model.io.services.ImageAnnotationExportService;
30-
import com.github.mfl28.boundingboxeditor.model.io.services.ImageAnnotationImportService;
31-
import com.github.mfl28.boundingboxeditor.model.io.services.ImageMetaDataLoadingService;
27+
import com.github.mfl28.boundingboxeditor.model.io.results.*;
28+
import com.github.mfl28.boundingboxeditor.model.io.services.*;
3229
import com.github.mfl28.boundingboxeditor.ui.*;
30+
import com.github.mfl28.boundingboxeditor.ui.settings.SettingsDialogView;
3331
import com.github.mfl28.boundingboxeditor.ui.statusevents.BoundingBoxPredictionSuccessfulEvent;
3432
import com.github.mfl28.boundingboxeditor.ui.statusevents.ImageAnnotationsImportingSuccessfulEvent;
3533
import com.github.mfl28.boundingboxeditor.ui.statusevents.ImageAnnotationsSavingSuccessfulEvent;
3634
import com.github.mfl28.boundingboxeditor.ui.statusevents.ImageFilesLoadingSuccessfulEvent;
3735
import com.github.mfl28.boundingboxeditor.utils.ColorUtils;
36+
import com.github.mfl28.boundingboxeditor.utils.UiUtils;
3837
import javafx.application.Platform;
3938
import javafx.beans.property.BooleanProperty;
4039
import javafx.beans.property.SimpleBooleanProperty;
@@ -44,6 +43,7 @@
4443
import javafx.concurrent.WorkerStateEvent;
4544
import javafx.scene.Cursor;
4645
import javafx.scene.control.ButtonBar;
46+
import javafx.scene.control.ButtonType;
4747
import javafx.scene.control.TableColumn;
4848
import javafx.scene.image.Image;
4949
import javafx.scene.input.*;
@@ -139,6 +139,7 @@ public class Controller {
139139
private final ImageAnnotationImportService annotationImportService = new ImageAnnotationImportService();
140140
private final ImageMetaDataLoadingService imageMetaDataLoadingService = new ImageMetaDataLoadingService();
141141
private final BoundingBoxPredictorService boundingBoxPredictorService = new BoundingBoxPredictorService();
142+
private final ModelNameFetchService modelNameFetchService = new ModelNameFetchService();
142143
private final Stage stage;
143144
private final MainView view = new MainView();
144145
private final Model model = new Model();
@@ -176,12 +177,17 @@ public Controller(final Stage mainStage) {
176177
connectServicesToView();
177178
}
178179

179-
private void connectServicesToView() {
180-
view.connectAnnotationImportService(annotationImportService);
181-
view.connectAnnotationExportService(annotationExportService);
182-
view.connectImageMetaDataLoadingService(imageMetaDataLoadingService);
183-
view.connectBoundingBoxPredictorService(boundingBoxPredictorService);
184-
view.setUpProgressDialogs();
180+
public void onRegisterSettingsAction() {
181+
final SettingsDialogView settingsDialog = view.getSettingsDialog();
182+
settingsDialog.getInferenceSettings()
183+
.setDisplayedSettingsFromConfig(model.getBoundingBoxPredictorClientConfig());
184+
// TODO: update predictor config
185+
settingsDialog.showAndWait();
186+
}
187+
188+
public void onRegisterSettingsApplyAction() {
189+
view.getSettingsDialog().getInferenceSettings()
190+
.applyDisplayedSettingsToConfig(model.getBoundingBoxPredictorClientConfig());
185191
}
186192

187193
/**
@@ -277,6 +283,14 @@ public void onRegisterImportAnnotationsAction(ImageAnnotationLoadStrategy.Type l
277283
}
278284
}
279285

286+
public void onRegisterModelNameFetchingAction() {
287+
modelNameFetchService.reset();
288+
final BoundingBoxPredictorClientConfig clientConfig = new BoundingBoxPredictorClientConfig();
289+
view.getSettingsDialog().getInferenceSettings().applyDisplayedSettingsToConfig(clientConfig);
290+
modelNameFetchService.setClientConfig(clientConfig);
291+
modelNameFetchService.restart();
292+
}
293+
280294
/**
281295
* Initiates the import of annotations.
282296
*
@@ -571,35 +585,6 @@ public Model getModel() {
571585
return model;
572586
}
573587

574-
private void onBoundingBoxPredictionSucceeded(WorkerStateEvent event) {
575-
final BoundingBoxPredictionResult predictionResult = boundingBoxPredictorService.getValue();
576-
577-
if(predictionResult.getNrSuccessfullyProcessedItems() != 0) {
578-
model.updateFromImageAnnotationData(predictionResult.getImageAnnotationData());
579-
view.getStatusBar().setStatusEvent(new BoundingBoxPredictionSuccessfulEvent(predictionResult));
580-
}
581-
582-
updateViewFileExplorerFileInfoElements();
583-
584-
final ImageAnnotation annotation = model.getCurrentImageAnnotation();
585-
586-
if(annotation != null) {
587-
view.getObjectTree().reset();
588-
view.getCurrentBoundingShapes().removeListener(boundingShapeCountPerCategoryListener);
589-
view.loadBoundingShapeViewsFromAnnotation(annotation);
590-
view.getCurrentBoundingShapes().addListener(boundingShapeCountPerCategoryListener);
591-
view.getObjectCategoryTable().refresh();
592-
view.getObjectTree().refresh();
593-
}
594-
595-
if(!predictionResult.getErrorTableEntries().isEmpty()) {
596-
MainView.displayIOResultErrorInfoAlert(predictionResult);
597-
} else if(predictionResult.getNrSuccessfullyProcessedItems() == 0) {
598-
MainView.displayErrorAlert("Bounding Box Prediction Error",
599-
"Could not predict any bounding boxes.");
600-
}
601-
}
602-
603588
IoMetaData getIoMetaData() {
604589
return ioMetaData;
605590
}
@@ -635,6 +620,44 @@ void initiateAnnotationExport(File destination, ImageAnnotationSaveStrategy.Type
635620
initiateAnnotationExport(destination, exportFormat, null);
636621
}
637622

623+
private void connectServicesToView() {
624+
view.connectAnnotationImportService(annotationImportService);
625+
view.connectAnnotationExportService(annotationExportService);
626+
view.connectImageMetaDataLoadingService(imageMetaDataLoadingService);
627+
view.connectBoundingBoxPredictorService(boundingBoxPredictorService);
628+
view.connectModelNameFetchingService(modelNameFetchService);
629+
view.setUpProgressDialogs();
630+
}
631+
632+
private void onBoundingBoxPredictionSucceeded(WorkerStateEvent event) {
633+
final BoundingBoxPredictionResult predictionResult = boundingBoxPredictorService.getValue();
634+
635+
if(predictionResult.getNrSuccessfullyProcessedItems() != 0) {
636+
model.updateFromImageAnnotationData(predictionResult.getImageAnnotationData());
637+
view.getStatusBar().setStatusEvent(new BoundingBoxPredictionSuccessfulEvent(predictionResult));
638+
}
639+
640+
updateViewFileExplorerFileInfoElements();
641+
642+
final ImageAnnotation annotation = model.getCurrentImageAnnotation();
643+
644+
if(annotation != null) {
645+
view.getObjectTree().reset();
646+
view.getCurrentBoundingShapes().removeListener(boundingShapeCountPerCategoryListener);
647+
view.loadBoundingShapeViewsFromAnnotation(annotation);
648+
view.getCurrentBoundingShapes().addListener(boundingShapeCountPerCategoryListener);
649+
view.getObjectCategoryTable().refresh();
650+
view.getObjectTree().refresh();
651+
}
652+
653+
if(!predictionResult.getErrorTableEntries().isEmpty()) {
654+
MainView.displayIOResultErrorInfoAlert(predictionResult);
655+
} else if(predictionResult.getNrSuccessfullyProcessedItems() == 0) {
656+
MainView.displayErrorAlert("Bounding Box Prediction Error",
657+
"Could not predict any bounding boxes.");
658+
}
659+
}
660+
638661
private void startAnnotationImportService(File source, ImageAnnotationLoadStrategy.Type importFormat) {
639662
annotationImportService.reset();
640663
annotationImportService.setSource(source);
@@ -659,9 +682,8 @@ private void startBoundingBoxPredictionService(File imageFile) {
659682
boundingBoxPredictorService.setImageMetaData(model.getImageFileNameToMetaDataMap().get(imageFile.getName()));
660683
boundingBoxPredictorService.setBoundingBoxPredictorConfig(model.getBoundingBoxPredictorConfig());
661684

662-
model.getBoundingBoxPredictorClientConfig().setInferenceModelName("fastrcnn");
663-
664-
boundingBoxPredictorService.setPredictorClient(BoundingBoxPredictorClient.create(model.getBoundingBoxPredictorClientConfig()));
685+
boundingBoxPredictorService
686+
.setPredictorClient(BoundingBoxPredictorClient.create(model.getBoundingBoxPredictorClientConfig()));
665687

666688
boundingBoxPredictorService.restart();
667689
}
@@ -678,6 +700,32 @@ private void setUpServices() {
678700

679701
boundingBoxPredictorService.setOnSucceeded(this::onBoundingBoxPredictionSucceeded);
680702
boundingBoxPredictorService.setOnFailed(this::onIoServiceFailed);
703+
704+
modelNameFetchService.setOnSucceeded(this::onModelNameFetchingSucceeded);
705+
// TODO: custom handling?
706+
modelNameFetchService.setOnFailed(this::onIoServiceFailed);
707+
}
708+
709+
private void onModelNameFetchingSucceeded(WorkerStateEvent workerStateEvent) {
710+
final ModelNameFetchResult result = modelNameFetchService.getValue();
711+
712+
final List<String> modelNames = result.getModelNames();
713+
714+
UiUtils.closeProgressDialog(view.getModelNameFetchingProgressDialog());
715+
716+
if(!modelNames.isEmpty()) {
717+
final Optional<String> modelChoice = MainView.displayChoiceDialogAndGetResult(modelNames.get(0),
718+
modelNames,
719+
"Model choice",
720+
"Choose the model" +
721+
" used for performing predictions.",
722+
"Model: ");
723+
modelChoice
724+
.ifPresent(s -> view.getSettingsDialog().getInferenceSettings().getSelectedModelLabel().setText(s));
725+
726+
} else {
727+
MainView.displayErrorAlert("Model Name Fetching Error", "The server did not report any models.");
728+
}
681729
}
682730

683731
private void onImageMetaDataLoadingSucceeded(WorkerStateEvent workerStateEvent) {
@@ -688,13 +736,16 @@ private void onImageMetaDataLoadingSucceeded(WorkerStateEvent workerStateEvent)
688736
}
689737

690738
if(!ioResult.getErrorTableEntries().isEmpty()) {
739+
UiUtils.closeProgressDialog(view.getImageMetaDataLoadingProgressDialog());
691740
MainView.displayIOResultErrorInfoAlert(ioResult);
692741
} else if(ioResult.getNrSuccessfullyProcessedItems() == 0) {
742+
UiUtils.closeProgressDialog(view.getImageMetaDataLoadingProgressDialog());
693743
MainView.displayErrorAlert(IMAGE_IMPORT_ERROR_ALERT_TITLE, IMAGE_IMPORT_ERROR_ALERT_CONTENT);
694744
}
695745

696746
if(imageMetaDataLoadingService.isReload() && ioResult.getNrSuccessfullyProcessedItems() == 0) {
697-
Controller.this.askToSaveExistingAnnotationDataAndClearModelAndView();
747+
UiUtils.closeProgressDialog(view.getImageMetaDataLoadingProgressDialog());
748+
askToSaveExistingAnnotationDataAndClearModelAndView();
698749
}
699750
}
700751

@@ -704,6 +755,7 @@ private boolean handleSuccessfullyProcessedItemsPresent() {
704755
boolean keepExistingCategories = false;
705756

706757
if(model.containsCategories()) {
758+
UiUtils.closeProgressDialog(view.getImageMetaDataLoadingProgressDialog());
707759
ButtonBar.ButtonData answer = imageMetaDataLoadingService.isReload() ?
708760
MainView.displayYesNoDialogAndGetResult(OPEN_IMAGE_FOLDER_OPTION_DIALOG_TITLE,
709761
KEEP_EXISTING_CATEGORIES_DIALOG_TEXT) :
@@ -718,6 +770,7 @@ private boolean handleSuccessfullyProcessedItemsPresent() {
718770
}
719771

720772
if(!model.isSaved()) {
773+
UiUtils.closeProgressDialog(view.getImageMetaDataLoadingProgressDialog());
721774
// First ask if user wants to save the existing annotations.
722775
ButtonBar.ButtonData answer = imageMetaDataLoadingService.isReload() ?
723776
MainView.displayYesNoDialogAndGetResult(RELOAD_IMAGE_FOLDER_OPTION_DIALOG_TITLE,
@@ -733,8 +786,7 @@ private boolean handleSuccessfullyProcessedItemsPresent() {
733786
finalKeepExistingCategories));
734787
} else {
735788
initiateAnnotationSavingWithFormatChoiceAndRunOnSaveSuccess(
736-
() -> onValidFilesPresentHandler(
737-
finalKeepExistingCategories));
789+
() -> onValidFilesPresentHandler(finalKeepExistingCategories));
738790
}
739791
} else if(answer == ButtonBar.ButtonData.NO || imageMetaDataLoadingService.isReload()) {
740792
onValidFilesPresentHandler(keepExistingCategories);
@@ -794,8 +846,10 @@ private void onAnnotationImportSucceeded(WorkerStateEvent workerStateEvent) {
794846
}
795847

796848
if(!loadResult.getErrorTableEntries().isEmpty()) {
849+
UiUtils.closeProgressDialog(view.getAnnotationImportProgressDialog());
797850
MainView.displayIOResultErrorInfoAlert(loadResult);
798851
} else if(loadResult.getNrSuccessfullyProcessedItems() == 0) {
852+
UiUtils.closeProgressDialog(view.getAnnotationImportProgressDialog());
799853
MainView.displayErrorAlert(ANNOTATION_IMPORT_ERROR_TITLE,
800854
ANNOTATION_IMPORT_ERROR_NO_VALID_FILES_CONTENT);
801855
return;
@@ -821,6 +875,7 @@ private void onAnnotationExportSucceeded(WorkerStateEvent event) {
821875
}
822876

823877
if(!saveResult.getErrorTableEntries().isEmpty()) {
878+
UiUtils.closeProgressDialog(view.getAnnotationExportProgressDialog());
824879
MainView.displayIOResultErrorInfoAlert(saveResult);
825880
} else {
826881
model.setSaved(true);

src/main/java/com/github/mfl28/boundingboxeditor/model/io/BoundingBoxPredictorClientConfig.java

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,70 @@
11
package com.github.mfl28.boundingboxeditor.model.io;
22

3-
import javafx.beans.property.ObjectProperty;
4-
import javafx.beans.property.SimpleObjectProperty;
5-
import javafx.beans.property.SimpleStringProperty;
6-
import javafx.beans.property.StringProperty;
3+
import javafx.beans.property.*;
74

85
public class BoundingBoxPredictorClientConfig {
96
private final ObjectProperty<BoundingBoxPredictorClient.ServiceType> serviceName = new SimpleObjectProperty<>(
107
BoundingBoxPredictorClient.ServiceType.TORCH_SERVE);
11-
private final StringProperty inferenceAddress = new SimpleStringProperty("http://localhost:8080");
12-
private final StringProperty managementAddress = new SimpleStringProperty("http://localhost:8081");
8+
private final StringProperty inferenceUrl = new SimpleStringProperty("http://localhost");
9+
private final IntegerProperty inferencePort = new SimpleIntegerProperty(8080);
10+
private final StringProperty managementUrl = new SimpleStringProperty("http://localhost");
11+
private final IntegerProperty managementPort = new SimpleIntegerProperty(8081);
1312
private final StringProperty inferenceModelName = new SimpleStringProperty();
1413

1514
public String getInferenceAddress() {
16-
return inferenceAddress.get();
15+
return inferenceUrl.get() + ":" + inferencePort.get();
1716
}
1817

19-
public StringProperty inferenceAddressProperty() {
20-
return inferenceAddress;
18+
public String getManagementAddress() {
19+
return managementUrl.get() + ":" + managementPort.get();
2120
}
2221

23-
public void setInferenceAddress(String inferenceAddress) {
24-
this.inferenceAddress.set(inferenceAddress);
22+
public int getInferencePort() {
23+
return inferencePort.get();
2524
}
2625

27-
public String getManagementAddress() {
28-
return managementAddress.get();
26+
public IntegerProperty inferencePortProperty() {
27+
return inferencePort;
28+
}
29+
30+
public void setInferencePort(int inferencePort) {
31+
this.inferencePort.set(inferencePort);
32+
}
33+
34+
public int getManagementPort() {
35+
return managementPort.get();
36+
}
37+
38+
public IntegerProperty managementPortProperty() {
39+
return managementPort;
40+
}
41+
42+
public void setManagementPort(int managementPort) {
43+
this.managementPort.set(managementPort);
44+
}
45+
46+
public String getInferenceUrl() {
47+
return inferenceUrl.get();
48+
}
49+
50+
public StringProperty inferenceUrlProperty() {
51+
return inferenceUrl;
52+
}
53+
54+
public void setInferenceUrl(String inferenceUrl) {
55+
this.inferenceUrl.set(inferenceUrl);
56+
}
57+
58+
public String getManagementUrl() {
59+
return managementUrl.get();
2960
}
3061

31-
public StringProperty managementAddressProperty() {
32-
return managementAddress;
62+
public StringProperty managementUrlProperty() {
63+
return managementUrl;
3364
}
3465

35-
public void setManagementAddress(String managementAddress) {
36-
this.managementAddress.set(managementAddress);
66+
public void setManagementUrl(String managementUrl) {
67+
this.managementUrl.set(managementUrl);
3768
}
3869

3970
public String getInferenceModelName() {

src/main/java/com/github/mfl28/boundingboxeditor/model/io/TorchServeRestClient.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ public static class ModelEntry {
103103
private String modelName;
104104
private String modelUrl;
105105

106+
public String getModelName() {
107+
return modelName;
108+
}
109+
110+
public String getModelUrl() {
111+
return modelUrl;
112+
}
106113

107114
@Override
108115
public String toString() {

src/main/java/com/github/mfl28/boundingboxeditor/model/io/results/IOResult.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public List<IOErrorInfoEntry> getErrorTableEntries() {
9292
return errorTableEntries;
9393
}
9494

95-
public enum OperationType {ANNOTATION_IMPORT, ANNOTATION_SAVING, IMAGE_METADATA_LOADING, BOUNDING_BOX_PREDICTION}
95+
public enum OperationType {ANNOTATION_IMPORT, ANNOTATION_SAVING, IMAGE_METADATA_LOADING, BOUNDING_BOX_PREDICTION,
96+
MODEL_NAME_FETCHING}
9697

9798
}

0 commit comments

Comments
 (0)