瀏覽代碼

Merge branch '87-bounding-box-filter-by-type' into 'master'

Resolve "bounding box filter by type"

Closes #87

See merge request troebs/pycs!82
Eric Tröbs 4 年之前
父節點
當前提交
e561973d6e

+ 4 - 0
webui/src/assets/icons/people.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
+    <path fill-rule="evenodd"
+          d="M5.5 3.5a2 2 0 100 4 2 2 0 000-4zM2 5.5a3.5 3.5 0 115.898 2.549 5.507 5.507 0 013.034 4.084.75.75 0 11-1.482.235 4.001 4.001 0 00-7.9 0 .75.75 0 01-1.482-.236A5.507 5.507 0 013.102 8.05 3.49 3.49 0 012 5.5zM11 4a.75.75 0 100 1.5 1.5 1.5 0 01.666 2.844.75.75 0 00-.416.672v.352a.75.75 0 00.574.73c1.2.289 2.162 1.2 2.522 2.372a.75.75 0 101.434-.44 5.01 5.01 0 00-2.56-3.012A3 3 0 0011 4z"></path>
+</svg>

+ 3 - 2
webui/src/components/media/annotated-image.vue

@@ -51,7 +51,7 @@ import VideoControl from "@/components/media/video-control";
 export default {
   name: "annotated-image",
   components: {VideoControl, AnnotationBox},
-  props: ['data', 'project', 'socket'],
+  props: ['data', 'project', 'socket', 'filter'],
   mounted: function () {
     window.addEventListener("resize", this.resizeEvent);
     this.resizeEvent();
@@ -109,7 +109,8 @@ export default {
     predictions: function () {
       const predictions = Object.keys(this.data.predictionResults)
           .map(k => this.data.predictionResults[k])
-          .filter(k => 'x' in k);
+          .filter(k => 'x' in k)
+          .filter(k => !this.filter || k.origin === this.filter);
 
       if (this.data.type === 'video')
         return predictions.filter(k => k.frame === this.video.frame);

+ 16 - 9
webui/src/components/media/annotated-media-view.vue

@@ -3,7 +3,8 @@
     <div class="media">
       <annotated-image :data="currentMedia"
                        :project="currentProject"
-                       :socket="socket"/>
+                       :socket="socket"
+                       :filter="filterValue"/>
     </div>
 
     <div class="control">
@@ -14,7 +15,9 @@
                      @control="showMediaSelector = $event"
                      :project="currentProject"
                      :data="currentMedia"
-                     :socket="socket"/>
+                     :socket="socket"
+                     :filter="filterValue"
+                     @filter="filter"/>
     </div>
 
     <div class="selector" v-if="showMediaSelector">
@@ -39,20 +42,21 @@ export default {
   data: function () {
     return {
       current: 0,
-      showMediaSelector: true
+      showMediaSelector: true,
+      filterValue: ''
     };
   },
   computed: {
     hasPrevious: function () {
       return this.current > 0;
     },
-    hasNext: function() {
+    hasNext: function () {
       return this.current < this.media.length - 1;
     },
-    media: function() {
+    media: function () {
       return Object.keys(this.currentProject.data).map(key => this.currentProject.data[key]);
     },
-    currentMedia: function() {
+    currentMedia: function () {
       if (this.current < this.media.length)
         return this.media[this.current];
       else
@@ -60,18 +64,21 @@ export default {
     }
   },
   methods: {
-    previous: function() {
+    previous: function () {
       if (this.hasPrevious)
         this.current -= 1;
     },
-    next: function() {
+    next: function () {
       if (this.hasNext)
         this.current += 1;
     },
-    predict: function() {
+    predict: function () {
       this.socket.post('/projects/' + this.currentProject.id, {
         'predict': [this.currentMedia.id]
       });
+    },
+    filter: function (value) {
+      this.filterValue = value;
     }
   }
 }

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

@@ -54,6 +54,21 @@
         {{ label.name }}
       </option>
     </select>
+
+    <button-input type="transparent" v-if="project.model.supports.includes('bounding-boxes') || project.model.supports.includes('labeled-bounding-boxes')">
+      <img alt="label" src="@/assets/icons/people.svg"
+           @touchstart.stop @mousedown.stop
+           @click.stop="showFilterSelection = true">
+    </button-input>
+
+    <select v-if="showFilterSelection"
+            @touchstart.stop @mousedown.stop
+            @change="filterSelf"
+            @focusout="showFilterSelection = false">
+      <option :selected="this.filter === ''" value="">None</option>
+      <option :selected="this.filter === 'user'" value="user">User</option>
+      <option :selected="this.filter === 'pipeline'" value="pipeline">Pipeline</option>
+    </select>
   </div>
 
 </template>
@@ -65,10 +80,11 @@ import ButtonRow from "@/components/base/button-row";
 export default {
   name: "media-control",
   components: {ButtonRow, ButtonInput},
-  props: ['hasPrevious', 'hasNext', 'control', 'data', 'project', 'socket'],
+  props: ['hasPrevious', 'hasNext', 'control', 'data', 'project', 'socket', 'filter'],
   data: function () {
     return {
-      showLabelSelection: false
+      showLabelSelection: false,
+      showFilterSelection: false,
     }
   },
   computed: {
@@ -108,6 +124,9 @@ export default {
       });
       this.showLabelSelection = false;
     },
+    filterSelf: function (event) {
+      this.$emit('filter', event.target.value);
+    },
     reset: function () {
       this.socket.post(this.mediaUrl, {
         reset: true