Browse Source

Resolve "model abilities"

Eric Tröbs 4 years ago
parent
commit
a5809f4b12

+ 2 - 0
app.py

@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+
 from pycs.ApplicationStatus import ApplicationStatus
 from pycs.ApplicationStatus import ApplicationStatus
 from pycs.frontend.WebServer import WebServer
 from pycs.frontend.WebServer import WebServer
 from pycs.models.ModelManager import ModelManager
 from pycs.models.ModelManager import ModelManager

+ 4 - 4
pycs/pipeline/Pipeline.py

@@ -10,16 +10,16 @@ class Pipeline:
         :param root_folder: relative path to model folder
         :param root_folder: relative path to model folder
         :param distribution: object parsed from distribution.json
         :param distribution: object parsed from distribution.json
         """
         """
-        pass
+        raise NotImplementedError
 
 
     def close(self):
     def close(self):
         """
         """
         is called everytime a pipeline is not needed anymore and should be used
         is called everytime a pipeline is not needed anymore and should be used
-        to close and clean native resources
+        to free native resources
 
 
         :return:
         :return:
         """
         """
-        pass
+        raise NotImplementedError
 
 
     def execute(self, job: Job) -> Result:
     def execute(self, job: Job) -> Result:
         """
         """
@@ -28,4 +28,4 @@ class Pipeline:
         :param job: that should be executed
         :param job: that should be executed
         :return:
         :return:
         """
         """
-        pass
+        raise NotImplementedError

+ 15 - 10
webui/src/components/media/annotated-image.vue

@@ -7,6 +7,7 @@
 
 
     <annotation-box v-if="current"
     <annotation-box v-if="current"
                     :image="image"
                     :image="image"
+                    :supports="model.supports"
                     :position="current"/>
                     :position="current"/>
 
 
     <annotation-box v-for="(result, index) in predictions"
     <annotation-box v-for="(result, index) in predictions"
@@ -18,6 +19,7 @@
                     :socket="socket"
                     :socket="socket"
                     :box-url="mediaUrl + '/' + result.id"
                     :box-url="mediaUrl + '/' + result.id"
                     :labels="project.labels"
                     :labels="project.labels"
+                    :supports="model.supports"
                     @move="move"
                     @move="move"
                     @resize="resize"/>
                     @resize="resize"/>
   </div>
   </div>
@@ -29,7 +31,7 @@ import AnnotationBox from "@/components/media/annotation-box";
 export default {
 export default {
   name: "annotated-image",
   name: "annotated-image",
   components: {AnnotationBox},
   components: {AnnotationBox},
-  props: ['project', 'data', 'socket'],
+  props: ['data', 'project', 'model', 'socket'],
   mounted: function () {
   mounted: function () {
     window.addEventListener("resize", this.resizeEvent);
     window.addEventListener("resize", this.resizeEvent);
 
 
@@ -78,15 +80,18 @@ export default {
           .filter(k => 'x' in k);
           .filter(k => 'x' in k);
     },
     },
     events: function () {
     events: function () {
-      return {
-        'touchstart': this.press,
-        'touchmove': this.track,
-        'touchend': this.release,
-        'mousedown': this.press,
-        'mousemove': this.track,
-        'mouseup': this.release,
-        'dragstart': e => e.stopPropagation()
-      }
+      if (this.model.supports.includes('bounding-boxes') || this.model.supports.includes('labeled-bounding-boxes'))
+        return {
+          'touchstart': this.press,
+          'touchmove': this.track,
+          'touchend': this.release,
+          'mousedown': this.press,
+          'mousemove': this.track,
+          'mouseup': this.release,
+          'dragstart': e => e.stopPropagation()
+        }
+      else
+        return {}
     }
     }
   },
   },
   methods: {
   methods: {

+ 7 - 4
webui/src/components/media/annotated-media-view.vue

@@ -1,7 +1,9 @@
 <template>
 <template>
   <div class="annotated-media-view">
   <div class="annotated-media-view">
     <div class="media">
     <div class="media">
-      <annotated-image :data="currentMedia" :project="currentProject" :socket="socket"/>
+      <annotated-image :data="currentMedia"
+                       :project="currentProject" :model="currentModel"
+                       :socket="socket"/>
     </div>
     </div>
 
 
     <div class="control">
     <div class="control">
@@ -11,6 +13,7 @@
                      :control="showMediaSelector"
                      :control="showMediaSelector"
                      @control="showMediaSelector = $event"
                      @control="showMediaSelector = $event"
                      :project="currentProject"
                      :project="currentProject"
+                     :model="currentModel"
                      :data="currentMedia"
                      :data="currentMedia"
                      :socket="socket"/>
                      :socket="socket"/>
     </div>
     </div>
@@ -33,15 +36,15 @@ import MediaControl from "@/components/media/media-control";
 export default {
 export default {
   name: "annotated-media-view",
   name: "annotated-media-view",
   components: {MediaControl, AnnotatedImage, MediaSelector},
   components: {MediaControl, AnnotatedImage, MediaSelector},
-  props: ['currentProject', 'socket'],
-  data: function() {
+  props: ['currentProject', 'currentModel', 'socket'],
+  data: function () {
     return {
     return {
       current: 0,
       current: 0,
       showMediaSelector: true
       showMediaSelector: true
     };
     };
   },
   },
   computed: {
   computed: {
-    hasPrevious: function() {
+    hasPrevious: function () {
       return this.current > 0;
       return this.current > 0;
     },
     },
     hasNext: function() {
     hasNext: function() {

+ 2 - 2
webui/src/components/media/annotation-box.vue

@@ -50,7 +50,7 @@
 <script>
 <script>
 export default {
 export default {
   name: "annotation-box",
   name: "annotation-box",
-  props: ['type', 'image', 'position', 'socket', 'boxUrl', 'labels'],
+  props: ['type', 'image', 'position', 'socket', 'boxUrl', 'labels', 'supports'],
   data: function () {
   data: function () {
     return {
     return {
       showLabelSelection: false
       showLabelSelection: false
@@ -74,7 +74,7 @@ export default {
       return this.type === 'pipeline';
       return this.type === 'pipeline';
     },
     },
     labelButton: function () {
     labelButton: function () {
-      return this.type !== 'pipeline';
+      return this.supports.includes('labeled-bounding-boxes') && this.type !== 'pipeline';
     },
     },
     labelList: function () {
     labelList: function () {
       return Object.keys(this.labels).map(key => this.labels[key]);
       return Object.keys(this.labels).map(key => this.labels[key]);

+ 2 - 2
webui/src/components/media/media-control.vue

@@ -33,7 +33,7 @@
       &gt;
       &gt;
     </button-input>
     </button-input>
 
 
-    <button-input type="transparent">
+    <button-input type="transparent" v-if="model.supports.includes('labeled-images')">
       <img alt="label" src="@/assets/icons/tag.svg"
       <img alt="label" src="@/assets/icons/tag.svg"
            :class="{tagged: currentLabel}"
            :class="{tagged: currentLabel}"
            @touchstart.stop @mousedown.stop
            @touchstart.stop @mousedown.stop
@@ -64,7 +64,7 @@ import ButtonRow from "@/components/base/button-row";
 export default {
 export default {
   name: "media-control",
   name: "media-control",
   components: {ButtonRow, ButtonInput},
   components: {ButtonRow, ButtonInput},
-  props: ['hasPrevious', 'hasNext', 'control', 'data', 'project', 'socket'],
+  props: ['hasPrevious', 'hasNext', 'control', 'data', 'project', 'model', 'socket'],
   data: function () {
   data: function () {
     return {
     return {
       showLabelSelection: false
       showLabelSelection: false

+ 44 - 7
webui/src/components/projects/project-creation-window.vue

@@ -21,6 +21,17 @@
                     v-model="model">
                     v-model="model">
         Model
         Model
       </select-input>
       </select-input>
+
+      <div class="features">
+        This model supports:
+
+        <ul>
+          <li v-for="(feature, key) in current.supports"
+              v-bind:key="key">
+            {{ feature }}
+          </li>
+        </ul>
+      </div>
     </div>
     </div>
 
 
     <button-row class="footer">
     <button-row class="footer">
@@ -46,7 +57,7 @@ export default {
   name: "project-creation-window",
   name: "project-creation-window",
   components: {ButtonRow, ButtonInput, SelectInput, TextareaInput, TextInput},
   components: {ButtonRow, ButtonInput, SelectInput, TextareaInput, TextInput},
   props: ['status', 'socket'],
   props: ['status', 'socket'],
-  data: function() {
+  data: function () {
     return {
     return {
       name: '',
       name: '',
       nameError: false,
       nameError: false,
@@ -56,24 +67,42 @@ export default {
     }
     }
   },
   },
   computed: {
   computed: {
-    models: function() {
+    models: function () {
+      const supported = {
+        'bounding-boxes': 'bounding boxes',
+        'labeled-bounding-boxes': 'labeled bounding boxes',
+        'labeled-images': 'labeled images',
+      };
       let result = [];
       let result = [];
 
 
       for (let o in this.status.models) {
       for (let o in this.status.models) {
         result.push({
         result.push({
-          'name': this.status.models[o].name,
-          'value': this.status.models[o].id
-        });
+              'id': this.status.models[o].id,
+              'name': this.status.models[o].name,
+              'value': this.status.models[o].id,
+              'supports': this.status.models[o].supports
+                  .map(k => k in supported ? supported[k] : 'unknown feature')
+            }
+        );
       }
       }
 
 
       return result;
       return result;
+    },
+    current: function () {
+      for (let model of this.models) {
+        if (model.id === this.model) {
+          return model;
+        }
+      }
+
+      return false;
     }
     }
   },
   },
-  created: function() {
+  created: function () {
     this.model = this.models[0].value;
     this.model = this.models[0].value;
   },
   },
   methods: {
   methods: {
-    create: function() {
+    create: function () {
       this.nameError = !this.name;
       this.nameError = !this.name;
       this.descriptionError = !this.description;
       this.descriptionError = !this.description;
 
 
@@ -120,6 +149,14 @@ export default {
   height: 4rem;
   height: 4rem;
 }
 }
 
 
+.features {
+  font-size: 80%;
+}
+
+.features ul {
+  margin-top: 0.4rem;
+}
+
 .footer {
 .footer {
   flex-grow: 0;
   flex-grow: 0;
   padding: 2rem;
   padding: 2rem;

+ 10 - 2
webui/src/components/projects/project-data-view-window.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
   <div class="project-data-view-window">
   <div class="project-data-view-window">
-    <annotated-media-view :currentProject="currentProject" :socket="socket"/>
+    <annotated-media-view :currentProject="currentProject" :currentModel="currentModel" :socket="socket"/>
   </div>
   </div>
 </template>
 </template>
 
 
@@ -10,7 +10,15 @@ import AnnotatedMediaView from "@/components/media/annotated-media-view";
 export default {
 export default {
   name: "project-data-view-window",
   name: "project-data-view-window",
   components: {AnnotatedMediaView},
   components: {AnnotatedMediaView},
-  props: ['status', 'socket', 'currentProject']
+  props: ['status', 'socket', 'currentProject'],
+  computed: {
+    currentModel: function () {
+      if (this.currentProject.pipeline['model-distribution'] in this.status.models)
+        return this.status.models[this.currentProject.pipeline['model-distribution']];
+
+      return false;
+    }
+  }
 }
 }
 </script>
 </script>