Browse Source

Improved Coding Style and Small Addition to Inference

The coding style was slightly improved to satisfy pylint.
Also, the button to perform inference on a custom bounding box can now only be clicked if no prediction is running.
j-bl 3 years ago
parent
commit
59f949815f

+ 0 - 2
models/moth_scanner/scanner/__init__.py

@@ -24,7 +24,6 @@ class Scanner(Interface):
         pass
 
     def execute(self, storage: MediaStorage, file: MediaFile):
-
         im = self.read_image(file.path)
         im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
         bw_im = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
@@ -42,7 +41,6 @@ class Scanner(Interface):
             file.add_bounding_box(x0, y0, bbox.w, bbox.h, label=label)
 
     def pure_inference(self, storage: MediaStorage, file: MediaFile, bounding_boxes: List[MediaBoundingBox]):
-
         im = self.read_image(file.path)
         im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
         bw_im = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)

+ 6 - 5
pycs/frontend/endpoints/pipelines/PredictModel.py

@@ -127,18 +127,19 @@ class PredictModel(View):
     @staticmethod
     def load_and_pure_inference(pipelines: PipelineCache,
                          notifications: NotificationList,
-                         nm: NotificationManager,
-                         project_id: int, file_filter: List[int], result_filter: dict[int, List[Result]]):
+                         notification_manager: NotificationManager,
+                         project_id: int, file_filter: List[int],
+                         result_filter: dict[int, List[Result]]):
         """
         load the pipeline and call the execute function
 
         :param database: database object
         :param pipelines: pipeline cache
         :param notifications: notification object
-        :param nm: notification manager
+        :param notification_manager: notification manager
         :param project_id: project id
         :param file_filter: list of file ids
-        :param result_filter: dict of file id and list of results (bounding boxes) to classify
+        :param result_filter: dict of file id and list of results to classify
         :return:
         """
         pipeline = None
@@ -171,7 +172,7 @@ class PredictModel(View):
                 for i, result in enumerate(result_filter[file_id]):
                     result.label_id = bbox_labels[i].identifier
                     result.set_origin('user', commit=True)
-                    notifications.add(nm.edit_result, result)
+                    notifications.add(notification_manager.edit_result, result)
 
                 # yield progress
                 yield index / length, notifications

+ 57 - 1
webui/src/components/media/cropped-image.vue

@@ -32,6 +32,29 @@
 export default {
   name: "cropped-image",
   props: ['labels', 'file', 'box'],
+  created: function () {
+    // get data
+    this.getJobs();
+
+    // subscribe to changes
+    this.$root.socket.on('connect', this.getJobs);
+    this.$root.socket.on('create-job', this.addJob);
+    this.$root.socket.on('remove-job', this.removeJob);
+    this.$root.socket.on('edit-job', this.editJob);
+  },
+  destroyed: function () {
+    this.$root.socket.off('connect', this.getJobs);
+    this.$root.socket.off('create-job', this.addJob);
+    this.$root.socket.off('remove-job', this.removeJob);
+    this.$root.socket.off('edit-job', this.editJob);
+  },
+  data: function () {
+    return {
+      jobs: [],
+      labelSelector: false,
+      model: null
+    }
+  },
   computed: {
     src: function () {
       if (!this.box)
@@ -57,9 +80,43 @@ export default {
           return label.name;
 
       return 'Not found';
+    },
+    isPredictionRunning: function () {
+      return this.jobs.filter(j => !j.finished && j.type === 'Model Interaction').length > 0;
     }
   },
   methods: {
+    getJobs: function () {
+      this.$root.socket.get('/jobs')
+          .then(response => response.json())
+          .then(jobs => {
+            this.jobs = [];
+            jobs.forEach(this.addJob)
+          });
+    },
+    addJob: function (job) {
+      for (let j of this.jobs)
+        if (j.identifier === job.identifier)
+          return;
+
+      this.jobs.push(job);
+    },
+    removeJob: function (job) {
+      for (let i = 0; i < this.jobs.length; i++) {
+        if (this.jobs[i].identifier === job.identifier) {
+          this.jobs.splice(i, 1);
+          return;
+        }
+      }
+    },
+    editJob: function (job) {
+      for (let i = 0; i < this.jobs.length; i++) {
+        if (this.jobs[i].identifier === job.identifier) {
+          this.$set(this.jobs, i, job);
+          return;
+        }
+      }
+    },
     predict_cropped_image: function () {
       // This shouldn't happen, since the icon is only shown if a bounding box
       // was selected.
@@ -68,7 +125,6 @@ export default {
 
       if (!this.isPredictionRunning) {
         // TODO then / error
-        // this should become this.box.identifier...
         this.$root.socket.post(`/data/${this.file.identifier}/${this.box.identifier}/predict_bounding_box`, {
           predict: true
         });