Browse Source

Update demo pages

pull/1899/head
Hironsan 3 years ago
parent
commit
2adf194d19
6 changed files with 343 additions and 61 deletions
  1. 61
      frontend/components/tasks/image/RegionList.vue
  2. 3
      frontend/package.json
  3. 135
      frontend/pages/demo/object-detection/index.vue
  4. 137
      frontend/pages/demo/segmentation/index.vue
  5. 3
      frontend/plugins/vue-konva.js
  6. 65
      frontend/yarn.lock

61
frontend/components/tasks/image/RegionList.vue

@ -0,0 +1,61 @@
<template>
<v-card>
<v-list dense>
<v-list-item-group v-model="model">
<v-list-item
v-for="(item, i) in regions"
:key="`item-${i}`"
:value="item"
active-class="text--accent-4"
@mouseenter="$emit('hover-region', item.id)"
@mouseleave="$emit('unhover-region', item.id)"
>
<template #default="{}">
<v-list-item-content>
<v-list-item-title>
<v-chip :color="item.color" text-color="white" small v-text="item.category" />
</v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-checkbox
:input-value="item.visibility"
:on-icon="mdiEyeOutline"
:off-icon="mdiEyeOffOutline"
@change="$emit('change-visibility', item.id, $event)"
/>
</v-list-item-action>
</template>
</v-list-item>
</v-list-item-group>
</v-list>
</v-card>
</template>
<script>
import { mdiEyeOutline, mdiEyeOffOutline } from '@mdi/js'
export default {
props: {
regions: {
type: Array,
default: () => []
}
},
data() {
return {
mdiEyeOutline,
mdiEyeOffOutline,
model: null,
headers: [
{
text: 'Category',
align: 'start',
value: 'category'
},
{ text: 'Visibility', value: 'visibility' }
]
}
}
}
</script>

3
frontend/package.json

@ -46,9 +46,10 @@
"vue": "^2.6.14",
"vue-chartjs": "^3.5.1",
"vue-filepond": "^6.0.3",
"vue-image-annotator": "^0.1.17",
"vue-image-annotator": "0.1.34",
"vue-shortkey": "^3.1.7",
"vue-template-compiler": "^2.6.14",
"vue-virtual-scroller": "^1.0.10",
"vue-youtube": "^1.4.0",
"vuetify": "^2.*",
"wavesurfer.js": "^5.1.0",

135
frontend/pages/demo/object-detection/index.vue

@ -4,21 +4,52 @@
<v-row justify="center">
<v-col cols="12" md="9">
<v-card>
<v-card-title>
<v-chip-group v-model="selectedLabelIndex" column>
<v-chip
v-for="item in labels"
:key="item.id"
:color="item.backgroundColor"
filter
:text-color="$contrastColor(item.backgroundColor)"
>
{{ item.text }}
<v-avatar
v-if="item.suffixKey"
right
color="white"
class="black--text font-weight-bold"
>
{{ item.suffixKey }}
</v-avatar>
</v-chip>
</v-chip-group>
</v-card-title>
<v-divider />
<v-bounding-box
:rectangles="rectangles"
:rectangles="filteredRectangles"
:highlight-id="highlightId"
:image-url="imageUrl"
:labels="labels"
:labels="bboxLabels"
:selected-label="selectedLabel"
:scale="scale"
@add-rectangle="addRectangle"
@update-rectangle="updateRectangle"
@delete-rectangle="deleteRectangle"
@update-scale="updateScale"
@select-rectangle="selectRectangle"
/>
</v-card>
</v-col>
<v-col cols="12" md="3">
<list-metadata :metadata="meta" />
<region-list
class="mt-4"
:regions="regionList"
@change-visibility="changeVisibility"
@hover-region="hoverRegion"
@unhover-region="unhoverRegion"
/>
</v-col>
</v-row>
</v-container>
@ -28,11 +59,13 @@
<script>
import { VBoundingBox } from 'vue-image-annotator'
import ListMetadata from '@/components/tasks/metadata/ListMetadata'
import RegionList from '@/components/tasks/image/RegionList.vue'
export default {
components: {
ListMetadata,
VBoundingBox
VBoundingBox,
RegionList
},
layout: 'demo',
@ -51,41 +84,81 @@ export default {
}
],
labels: [
{
id: 0,
name: 'pig',
color: '#ff0000'
},
{
id: 1,
name: 'cat',
color: '#00ff00'
text: 'Cat',
prefixKey: null,
suffixKey: 'c',
backgroundColor: '#7c20e0',
textColor: '#ffffff'
},
{
id: 2,
name: 'dog',
color: '#0000ff'
text: 'Dog',
prefixKey: null,
suffixKey: 'd',
backgroundColor: '#fbb028',
textColor: '#000000'
}
],
meta: { wikiPageId: 2 },
selectedLabel: undefined,
selectedPolygon: undefined,
scale: 1
selectedLabelIndex: undefined,
selectedRectangle: undefined,
scale: 1,
visibilities: {},
highlightId: null
}
},
methods: {
selectLabel(index) {
this.selectedLabel = this.labels[index]
computed: {
bboxLabels() {
return this.labels.map((label) => {
return {
id: label.id,
name: label.text,
color: label.backgroundColor
}
})
},
selectedLabel() {
if (this.selectedLabelIndex !== undefined) {
return this.labels[this.selectedLabelIndex]
} else {
return undefined
}
},
resetLabel() {
this.selectedLabel = undefined
regionList() {
return this.rectangles.map((rectangle) => {
return {
id: rectangle.id,
category: this.labels.find((label) => rectangle.label === label.id).text,
color: this.labels.find((label) => rectangle.label === label.id).backgroundColor,
visibility: rectangle.id in this.visibilities ? this.visibilities[rectangle.id] : true
}
})
},
filteredRectangles() {
return this.rectangles.filter((rectangle) => this.visibilities[rectangle.id] !== false)
}
},
watch: {
selectedLabel(newLabel) {
if (newLabel !== undefined && !!this.selectedRectangle) {
this.selectedRectangle.label = newLabel.id
this.updateRectangle(this.selectedRectangle)
}
}
},
methods: {
addRectangle(rectangle) {
console.log('addRectangle', rectangle)
this.rectangles.push(rectangle)
this.visibilities[rectangle.id] = true
},
updateRectangle(rectangle) {
@ -99,6 +172,28 @@ export default {
deleteRectangle(rectangleId) {
console.log('deleteRectangle', rectangleId)
this.rectangles = this.rectangles.filter((r) => r.id !== rectangleId)
delete this.visibilities[rectangleId]
},
changeVisibility(regionId, visibility) {
console.log('changeVisibility', regionId, visibility)
this.$set(this.visibilities, regionId, visibility)
this.visibilities = Object.assign({}, this.visibilities)
},
hoverRegion(regionId) {
console.log('hoverRegion', regionId)
this.highlightId = regionId
},
unhoverRegion(regionId) {
console.log('unhoverRegion', regionId)
this.highlightId = null
},
selectRectangle(rectangleId) {
this.selectedRectangle = this.rectangles.find((r) => r.id === rectangleId)
this.selectedLabelIndex = this.labels.findIndex((l) => l.id === this.selectedRectangle.label)
},
zoomOut() {

137
frontend/pages/demo/segmentation/index.vue

@ -4,15 +4,38 @@
<v-row justify="center">
<v-col cols="12" md="9">
<v-card>
<v-card-title>
<v-chip-group v-model="selectedLabelIndex" column>
<v-chip
v-for="item in labels"
:key="item.id"
:color="item.backgroundColor"
filter
:text-color="$contrastColor(item.backgroundColor)"
>
{{ item.text }}
<v-avatar
v-if="item.suffixKey"
right
color="white"
class="black--text font-weight-bold"
>
{{ item.suffixKey }}
</v-avatar>
</v-chip>
</v-chip-group>
</v-card-title>
<v-divider />
<v-segmentation
:highlight-id="highlightId"
:image-url="imageUrl"
:labels="labels"
:polygons="polygons"
:labels="bboxLabels"
:polygons="filteredRegions"
:selected-label="selectedLabel"
:scale="scale"
@add-polygon="addPolygon"
@delete-polygon="deletePolygon"
@select-polygon="selectPolygon"
@select-polygon="selectRegion"
@update-polygon="updatePolygon"
@update-scale="updateScale"
/>
@ -20,6 +43,13 @@
</v-col>
<v-col cols="12" md="3">
<list-metadata :metadata="meta" />
<region-list
class="mt-4"
:regions="regionList"
@change-visibility="changeVisibility"
@hover-region="hoverRegion"
@unhover-region="unhoverRegion"
/>
</v-col>
</v-row>
</v-container>
@ -29,11 +59,13 @@
<script>
import { VSegmentation } from 'vue-image-annotator'
import ListMetadata from '@/components/tasks/metadata/ListMetadata'
import RegionList from '@/components/tasks/image/RegionList.vue'
export default {
components: {
ListMetadata,
VSegmentation
VSegmentation,
RegionList
},
layout: 'demo',
@ -50,38 +82,77 @@ export default {
],
task: 'bounding box',
labels: [
{
id: 0,
name: 'pig',
color: '#ff0000'
},
{
id: 1,
name: 'cat',
color: '#00ff00'
text: 'Cat',
prefixKey: null,
suffixKey: 'c',
backgroundColor: '#7c20e0',
textColor: '#ffffff'
},
{
id: 2,
name: 'dog',
color: '#0000ff'
text: 'Dog',
prefixKey: null,
suffixKey: 'd',
backgroundColor: '#fbb028',
textColor: '#000000'
}
],
meta: { wikiPageId: 2 },
selectedLabel: undefined,
selectedLabelIndex: undefined,
selectedPolygon: undefined,
scale: 1
scale: 1,
visibilities: {},
highlightId: null
}
},
methods: {
selectLabel(index) {
this.selectedLabel = this.labels[index]
computed: {
bboxLabels() {
return this.labels.map((label) => {
return {
id: label.id,
name: label.text,
color: label.backgroundColor
}
})
},
resetLabel() {
this.selectedLabel = undefined
selectedLabel() {
if (this.selectedLabelIndex !== undefined) {
return this.labels[this.selectedLabelIndex]
} else {
return undefined
}
},
regionList() {
return this.polygons.map((polygon) => {
return {
id: polygon.id,
category: this.labels.find((label) => polygon.label === label.id).text,
color: this.labels.find((label) => polygon.label === label.id).backgroundColor,
visibility: polygon.id in this.visibilities ? this.visibilities[polygon.id] : true
}
})
},
filteredRegions() {
return this.polygons.filter((polygon) => this.visibilities[polygon.id] !== false)
}
},
watch: {
selectedLabel(newLabel) {
if (newLabel !== undefined && !!this.selectedPolygon) {
this.selectedPolygon.label = newLabel.id
this.updatePolygon(this.selectedPolygon)
}
}
},
methods: {
addPolygon(polygon) {
this.polygons.push(polygon)
},
@ -90,11 +161,6 @@ export default {
this.polygons = this.polygons.filter((p) => p.id !== polygonId)
},
selectPolygon(id) {
console.log('selectPolygon', id)
this.selectedPolygon = this.polygons.find((p) => p.id === id)
},
updatePolygon(polygon) {
console.log('updatePolygon', polygon)
const index = this.polygons.findIndex((p) => p.id === polygon.id)
@ -104,6 +170,27 @@ export default {
}
},
changeVisibility(regionId, visibility) {
console.log('changeVisibility', regionId, visibility)
this.$set(this.visibilities, regionId, visibility)
this.visibilities = Object.assign({}, this.visibilities)
},
hoverRegion(regionId) {
console.log('hoverRegion', regionId)
this.highlightId = regionId
},
unhoverRegion(regionId) {
console.log('unhoverRegion', regionId)
this.highlightId = null
},
selectRegion(regionId) {
this.selectedPolygon = this.polygons.find((r) => r.id === regionId)
this.selectedLabelIndex = this.labels.findIndex((l) => l.id === this.selectedPolygon.label)
},
zoomOut() {
this.scale -= 0.1
},

3
frontend/plugins/vue-konva.js

@ -1,7 +1,4 @@
import Vue from 'vue'
import VueKonva from 'vue-konva'
// add any custom shortkey config settings here
Vue.use(VueKonva)
export default VueKonva

65
frontend/yarn.lock

@ -421,6 +421,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17"
integrity sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==
"@babel/parser@^7.18.4":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.6.tgz#845338edecad65ebffef058d3be851f1d28a63bc"
integrity sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7":
version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050"
@ -2777,6 +2782,15 @@
"@vue/babel-plugin-transform-vue-jsx" "^1.2.1"
camelcase "^5.0.0"
"@vue/compiler-sfc@2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-2.7.0.tgz#1c203e85290688e10ed3e70b151b9a2f8acab9c1"
integrity sha512-hPOI15RsXO1G8aK6FNF93ld9C/D4e/uAJBE59K8NnL8giuKqeVksvamgu4jKhCJ9f9bbUpj5BuSV3sufIx2hmw==
dependencies:
"@babel/parser" "^7.18.4"
postcss "^8.4.14"
source-map "^0.6.1"
"@vue/component-compiler-utils@^3.1.0":
version "3.3.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz#f9f5fb53464b0c37b2c8d2f3fbfe44df60f61dc9"
@ -4455,12 +4469,7 @@ core-js@^3.15.*, core-js@^3.6.4:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.15.2.tgz#740660d2ff55ef34ce664d7e2455119c5bdd3d61"
integrity sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==
core-js@^3.6.5:
version "3.21.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94"
integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==
core-js@^3.8.3:
core-js@^3.6.5, core-js@^3.8.3:
version "3.23.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.23.3.tgz#3b977612b15da6da0c9cc4aec487e8d24f371112"
integrity sha512-oAKwkj9xcWNBAvGbT//WiCdOMpb9XQG92/Fe3ABFM/R16BsHgePG00mFOgKf7IsCtfj8tA1kHtf/VwErhriz5Q==
@ -4794,6 +4803,11 @@ cssstyle@^2.3.0:
dependencies:
cssom "~0.3.6"
csstype@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
cuint@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
@ -8539,6 +8553,11 @@ nanoid@^3.1.23:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.32.tgz#8f96069e6239cc0a9ae8c0d3b41a3b4933a88c0a"
integrity sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw==
nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -9971,6 +9990,15 @@ postcss@7.x.x, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17,
picocolors "^0.2.1"
source-map "^0.6.1"
postcss@^8.4.14:
version "8.4.14"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
source-map-js "^1.0.2"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@ -10761,7 +10789,7 @@ schema-utils@^3.0.0:
scrollparent@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/scrollparent/-/scrollparent-2.0.1.tgz#715d5b9cc57760fb22bdccc3befb5bfe06b1a317"
integrity sha1-cV1bnMV3YPsivczDvvtb/gaxoxc=
integrity sha512-HSdN78VMvFCSGCkh0oYX/tY4R3P1DW61f8+TeZZ4j2VLgfwvw0bpRSOv4PCVKisktIwbzHCfZsx+rLbbDBqIBA==
scule@^0.2.1:
version "0.2.1"
@ -11012,6 +11040,11 @@ source-list-map@^2.0.0:
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@ -12172,10 +12205,10 @@ vue-i18n@^8.25.0:
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.26.8.tgz#afe936adbf96ff0e9808e04845b8f41cc21c666f"
integrity sha512-BN2OXolO15AKS95yNF8oOtARibaO6RxyKkAYNV4XpOmL7S4eVZYMIDtyvDv+XGZaiUmBJSH9mdNqzexvGMnK2A==
vue-image-annotator@^0.1.17:
version "0.1.21"
resolved "https://registry.yarnpkg.com/vue-image-annotator/-/vue-image-annotator-0.1.21.tgz#18c356d81fec9add66c5a0226820d891a752b3b5"
integrity sha512-9ZC/wcMWkZC/2bJn5TkeVCZvUCv7hWklC2Y7bhDib6bQQdoulAqVGgkucawLtJhXZCVOgO8UzGP17pghb/DIuw==
vue-image-annotator@0.1.34:
version "0.1.34"
resolved "https://registry.yarnpkg.com/vue-image-annotator/-/vue-image-annotator-0.1.34.tgz#464f8dbe467c8725b8285fb18d2861d7fc694642"
integrity sha512-9vqnWzFyWe1FBZWDEPjP2Z1bC8ePjBEYGKC+kyRA43hnIPMZieVJLOZmszJhryaKiq/IIlxPGUP/3hlKh3qkVg==
dependencies:
"@flatten-js/core" "^1.3.4"
core-js "^3.8.3"
@ -12304,7 +12337,15 @@ vue-youtube@^1.4.0:
get-youtube-id "^1.0.0"
youtube-player "^5.4.0"
vue@^2.6.11, vue@^2.6.12, vue@^2.6.14:
vue@^2.6.11:
version "2.7.0"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.7.0.tgz#9542552e0460563feff11727949f8964e2501bed"
integrity sha512-su25f1hocH+QNkVEqk+Oj7B+mkDIWU70l0YY7nYSJFEs3Z64njXxo65RUXnWH46ooEhKmEWyLdW6HcYn8coNrg==
dependencies:
"@vue/compiler-sfc" "2.7.0"
csstype "^3.1.0"
vue@^2.6.12, vue@^2.6.14:
version "2.6.14"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==

Loading…
Cancel
Save