added auto save and save button

This commit is contained in:
ori agranat
2019-10-29 23:58:06 +02:00
parent a72336270b
commit 1e02f114e1
21 changed files with 545 additions and 474 deletions

View File

@@ -1,95 +1,94 @@
<template>
<v-app>
<v-app-bar app dense clipped-left dark>
<img class="imgClass" src="./assets/logo.png">
<v-toolbar-title id="title">Chameleon Vision</v-toolbar-title>
<div class="flex-grow-1"></div>
<v-toolbar-items>
<v-tabs dark height="48" slider-color="#4baf62">
<v-tab to="vision">Vision</v-tab>
<v-tab to="settings">Settings</v-tab>
</v-tabs>
</v-toolbar-items>
</v-app-bar>
<v-content>
<v-container fluid fill-height>
<v-layout>
<v-flex>
<router-view></router-view>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
<v-app>
<v-app-bar app dense clipped-left dark>
<img class="imgClass" src="./assets/logo.png">
<v-toolbar-title id="title">Chameleon Vision</v-toolbar-title>
<div class="flex-grow-1"></div>
<v-toolbar-items>
<v-tabs dark height="48" slider-color="#4baf62">
<v-tab to="vision">Vision</v-tab>
<v-tab to="settings">Settings</v-tab>
</v-tabs>
</v-toolbar-items>
</v-app-bar>
<v-content>
<v-container fluid fill-height>
<v-layout>
<v-flex>
<router-view/>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
</template>
<script>
export default {
name: 'App',
export default {
name: 'App',
components: {
components: {},
methods: {
handleMessage(key, value) {
if (this.$store.state.hasOwnProperty(key)) {
this.$store.commit(key, value);
} else if (this.$store.state.pipeline.hasOwnProperty(key)) {
this.$store.commit('setPipeValues', {[key]: value});
} else {
switch (key) {
},
methods:{
handleMessage(key,value){
if(this.$store.state.hasOwnProperty(key)){
this.$store.commit(key,value);
} else if(this.$store.state.pipeline.hasOwnProperty(key)){
this.$store.commit('setPipeValues',{[key]:value});
}
else{
switch(key){
default:{
console.log(key + " : " + value);
}
default: {
console.log(key + " : " + value);
}
}
}
}
},
data: () => ({}),
created() {
this.$options.sockets.onmessage = async (data) => {
try {
var buffer = await data.data.arrayBuffer();
let message = this.$msgPack.decode(buffer);
for (let prop in message) {
if (message.hasOwnProperty(prop)) {
this.handleMessage(prop, message[prop]);
}
}
} catch (error) {
console.error('error: ' + data.data + " , " + error);
}
}
}
}
}
},
data: () => ({
}),
created(){
this.$options.sockets.onmessage = async (data) =>{
try{
var buffer = await data.data.arrayBuffer();
let message = this.$msgPack.decode(buffer);
for(let prop in message){
if(message.hasOwnProperty(prop)){
this.handleMessage(prop, message[prop]);
}
}
}
catch(error){
console.error('error: ' + data.data+ " , "+ error);
}
}
}
};
};
</script>
<style>
html{
overflow-y: hidden !important;
}
.imgClass{
width: auto;
height: 45px;
vertical-align: middle;
padding-right: 5px;
}
.tabClass{
color: #4baf62;
}
.container{
background-color: #212121;
padding: 0!important;
}
#title{
color:#4baf62;
}
span{
color: white;
}
html {
overflow-y: hidden !important;
}
.imgClass {
width: auto;
height: 45px;
vertical-align: middle;
padding-right: 5px;
}
.tabClass {
color: #4baf62;
}
.container {
background-color: #212121;
padding: 0 !important;
}
#title {
color: #4baf62;
}
span {
color: white;
}
</style>

View File

@@ -49,6 +49,7 @@
sendSlope(m, b, valid) {
this.handleInput('m', m);
this.handleInput('b', b);
this.$emit('update');
},
clearSlope() {
this.sendSlope(1, 0, false);

View File

@@ -15,12 +15,14 @@
export default {
name: "SingleCalibration",
props: ['rawPoint'],
methods:{
clearPoint(){
this.handleInput('point',[0,0]);
methods: {
clearPoint() {
this.handleInput('point', [0, 0]);
this.$emit('update');
},
takePoint(){
this.handleInput('point',this.rawPoint);
takePoint() {
this.handleInput('point', this.rawPoint);
this.$emit('update');
}
}
}

View File

@@ -2,7 +2,7 @@
<div>
<v-tooltip :right="right" :bottom="!right" nudge-right="10">
<template v-slot:activator="{ on }">
<v-icon :class="hoverClass" @click="handleClick" v-on="on" :color="color">{{text}}</v-icon>
<v-icon :class="hoverClass" @click="handleClick" v-on="on" :color="color">{{text}}</v-icon>
</template>
<span>{{tooltip}}</span>
</v-tooltip>
@@ -12,20 +12,18 @@
<script>
export default {
name: 'Icon',
props:['color','tooltip','text','right','hover'],
props: ['color', 'tooltip', 'text', 'right', 'hover'],
data() {
return {
}
return {}
},
methods:{
handleClick(){
methods: {
handleClick() {
this.$emit('click');
}
},
computed:{
hoverClass(){
if(this.hover !== undefined){
computed: {
hoverClass() {
if (this.hover !== undefined) {
return "hover";
}
}
@@ -35,7 +33,7 @@
</script>
<style scoped>
.hover:hover{
color: white !important;
}
.hover:hover {
color: white !important;
}
</style>

View File

@@ -5,7 +5,8 @@
<span>{{name}}</span>
</v-col>
<v-col :cols="9">
<v-text-field @keydown="handleKeyboard" dark v-model="localValue" dense :disabled="disabled" :error-messages="errorMessage"></v-text-field>
<v-text-field @keydown="handleKeyboard" dark v-model="localValue" dense :disabled="disabled"
:error-messages="errorMessage"/>
</v-col>
</v-row>
</div>
@@ -14,26 +15,24 @@
<script>
export default {
name: 'Input',
props:['name','value','disabled','errorMessage'],
props: ['name', 'value', 'disabled', 'errorMessage'],
data() {
return {
}
return {}
},
methods:{
handleKeyboard(event){
if(event.key == "Enter"){
methods: {
handleKeyboard(event) {
if (event.key == "Enter") {
this.$emit("Enter");
}
}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
this.$emit('input',value);
set(value) {
this.$emit('input', value);
}
}
}
@@ -41,5 +40,5 @@
</script>
<style lang="" scoped>
</style>

View File

@@ -5,7 +5,8 @@
<span>{{name}}</span>
</v-col>
<v-col>
<v-text-field dark v-model="localValue" class="mt-0 pt-0" hide-details single-line type="number" style="width: 70px"></v-text-field>
<v-text-field dark v-model="localValue" class="mt-0 pt-0" hide-details single-line type="number"
style="width: 70px"/>
</v-col>
</v-row>
</div>
@@ -14,18 +15,16 @@
<script>
export default {
name: 'NumberInput',
props:['name','value'],
props: ['name', 'value'],
data() {
return {
}
return {}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
set(value) {
this.$emit('input', parseInt(value));
}
}
@@ -34,5 +33,5 @@
</script>
<style lang="" scoped>
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<v-radio-group row v-model="localValue" dark :mandatory="true">
<v-radio color="#4baf62" v-for="(name,index) in list" :label="name" v-bind:key="index" :value="index"></v-radio>
<v-radio color="#4baf62" v-for="(name,index) in list" :label="name" v-bind:key="index" :value="index"/>
</v-radio-group>
</div>
</template>
@@ -9,19 +9,17 @@
<script>
export default {
name: 'Radio',
props:['value','list'],
props: ['value', 'list'],
data() {
return {
}
return {}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
this.$emit('input',value);
set(value) {
this.$emit('input', value);
}
}
}
@@ -29,5 +27,5 @@
</script>
<style lang="" scoped>
</style>

View File

@@ -5,13 +5,18 @@
<span>{{name}}</span>
</v-col>
<v-col :cols="10">
<v-range-slider :value="localValue" @input="handleInput" :max="max" :min="min" hide-details class="align-center" dark color="#4baf62" :step="step">
<template v-slot:prepend>
<v-text-field :value="localValue[0]" :max="max" :min="min" @input="handleChange" @focus="prependFocused = true" @blur="prependFocused = false" class="mt-0 pt-0" hide-details single-line type="number" style="width: 50px" :step="step"></v-text-field>
<v-range-slider :value="localValue" @input="handleInput" :max="max" :min="min" hide-details
class="align-center" dark color="#4baf62" :step="step">
<template v-slot:prepend>
<v-text-field :value="localValue[0]" :max="max" :min="min" @input="handleChange"
@focus="prependFocused = true" @blur="prependFocused = false" class="mt-0 pt-0"
hide-details single-line type="number" style="width: 50px" :step="step"/>
</template>
<template v-slot:append>
<v-text-field :value="localValue[1]" :max="max" :min="min" @input="handleChange" @focus="appendFocused = true" @blur="appendFocused = false" class="mt-0 pt-0" hide-details single-line type="number" style="width: 50px" :step="step"></v-text-field>
<v-text-field :value="localValue[1]" :max="max" :min="min" @input="handleChange"
@focus="appendFocused = true" @blur="appendFocused = false" class="mt-0 pt-0"
hide-details single-line type="number" style="width: 50px" :step="step"/>
</template>
</v-range-slider>
</v-col>
@@ -22,43 +27,43 @@
<script>
export default {
name: 'RangeSlider',
props:['name','min','max','value','step'],
props: ['name', 'min', 'max', 'value', 'step'],
data() {
return {
prependFocused:false,
appendFocused:false
prependFocused: false,
appendFocused: false
}
},
methods:{
handleChange(val){
methods: {
handleChange(val) {
let i = 0;
if(this.prependFocused === false && this.appendFocused === true){
if (this.prependFocused === false && this.appendFocused === true) {
i = 1;
}
if(this.prependFocused || this.appendFocused){
this.$set(this.localValue,i,val);
if (this.prependFocused || this.appendFocused) {
this.$set(this.localValue, i, val);
}
},
handleInput(val){
if(!this.prependFocused || !this.appendFocused){
this.localValue = val;
handleInput(val) {
if (!this.prependFocused || !this.appendFocused) {
this.localValue = val;
}
}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
this.$emit('input',value)
set(value) {
this.$emit('input', value)
}
}
}
}
}
</script>
<style lang="" scoped>
</style>

View File

@@ -5,7 +5,8 @@
<span>{{name}}</span>
</v-col>
<v-col :cols="9">
<v-select v-model="localValue" :items="indexList" item-text="name" item-value="index" dark color="#4baf62" item-color="green" :disabled="disabled"></v-select>
<v-select v-model="localValue" :items="indexList" item-text="name" item-value="index" dark
color="#4baf62" item-color="green" :disabled="disabled"/>
</v-col>
</v-row>
</div>
@@ -14,26 +15,26 @@
<script>
export default {
name: 'Select',
props:['list','name','value','disabled'],
props: ['list', 'name', 'value', 'disabled'],
data() {
return {
}
return {}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
this.$emit('input',value)
set(value) {
this.$emit('input', value)
}
},
indexList(){
indexList() {
let list = []
for(let i=0 ; i<this.list.length; i++){
for (let i = 0; i < this.list.length; i++) {
list.push({
name:this.list[i],
index:i});
name: this.list[i],
index: i
});
}
return list;
}

View File

@@ -5,11 +5,15 @@
<span>{{name}}</span>
</v-col>
<v-col :cols="10">
<v-slider :value="localValue" @input="handleInput" dark class="align-center" :max="max" :min="min" hide-details color="#4baf62" :step="step">
<template v-slot:append>
<v-text-field dark :max="max" :min="min" :value="localValue" @input="handleChange" @focus="isFocused = true" @blur="isFocused = false" class="mt-0 pt-0" hide-details single-line type="number" style="width: 50px" :step="step"></v-text-field>
</template>
</v-slider>
<v-slider :value="localValue" @start="isClicked = true" @end="isClicked = false" @change="handleclick"
@input="handleInput" dark class="align-center" :max="max" :min="min" hide-details
color="#4baf62" :step="step">
<template v-slot:append>
<v-text-field dark :max="max" :min="min" :value="localValue" @input="handleChange"
@focus="isFocused = true" @blur="isFocused = false" class="mt-0 pt-0" hide-details
single-line type="number" style="width: 50px" :step="step"/>
</template>
</v-slider>
</v-col>
</v-row>
</div>
@@ -18,31 +22,37 @@
<script>
export default {
name: 'Slider',
props:['min','max','name','value','step'],
props: ['min', 'max', 'name', 'value', 'step'],
data() {
return {
isFocused:false
isFocused: false,
isClicked: false
}
},
methods:{
handleChange(val){
if(this.isFocused){
methods: {
handleChange(val) {
if (this.isFocused) {
this.localValue = parseFloat(val);
}
},
handleInput(val){
if(!this.isFocused){
this.localValue = val;
handleInput(val) {
if (!this.isFocused && this.isClicked) {
this.localValue = val;
}
},
handleclick(val) {
if (!this.isFocused) {
this.localValue = val;
}
}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
this.$emit('input',value)
set(value) {
this.$emit('input', value)
}
}
}
@@ -50,5 +60,5 @@
</script>
<style lang="" scoped>
</style>

View File

@@ -5,7 +5,7 @@
<span>{{name}}</span>
</v-col>
<v-col>
<v-switch v-model="localValue" color="#4baf62"></v-switch>
<v-switch v-model="localValue" color="#4baf62"/>
</v-col>
</v-row>
</div>
@@ -14,19 +14,17 @@
<script>
export default {
name: 'CVSwitch',
props:['name','value'],
props: ['name', 'value'],
data() {
return {
}
return {}
},
computed:{
localValue:{
get(){
computed: {
localValue: {
get() {
return this.value;
},
set(value){
this.$emit('input',value)
set(value) {
this.$emit('input', value)
}
}
}
@@ -34,5 +32,5 @@
</script>
<style lang="" scoped>
</style>

View File

@@ -8,19 +8,19 @@ import msgPack from 'msgpack5';
Vue.config.productionTip = false;
// Vue.use(VueNativeSock,'ws://' + location.host + '/websocket',{format: 'json'});
Vue.use(VueNativeSock,'ws://'+location.hostname+':8888/websocket');
Vue.use(VueNativeSock, 'ws://' + location.hostname + ':8888/websocket');
Vue.prototype.$msgPack = msgPack(true)
Vue.mixin({
methods:{
handleInput(key,value){
let msg = this.$msgPack.encode({[key]:value})
this.$socket.send(msg);
methods: {
handleInput(key, value) {
let msg = this.$msgPack.encode({[key]: value})
this.$socket.send(msg);
}
}
}
})
new Vue({
router,
store,
vuetify,
render: h => h(App)
router,
store,
vuetify,
render: h => h(App)
}).$mount('#app')

View File

@@ -1,13 +1,11 @@
import '@mdi/font/css/materialdesignicons.css';
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
Vue.use(Vuetify);
export default new Vuetify({
icons: {
}
icons: {}
});

View File

@@ -26,64 +26,75 @@
@input="handleInput('currentPipeline',currentPipelineIndex)"/>
<CVinput v-else name="Pipeline" v-model="newPipelineName" @Enter="savePipelineNameChange"/>
</v-col>
<v-col :cols="1" class="colsClass">
<v-menu v-if="isPipelineEdit === false" offset-y dark auto>
<template v-slot:activator="{ on }">
<v-icon color="white" v-on="on">menu</v-icon>
</template>
<v-list dense>
<v-list-item @click="toPipelineNameChange">
<v-list-item-title>
<CVicon color="#c5c5c5" :right="true" text="edit" tooltip="Edit pipeline name"/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="handleInput('command','addNewPipeline')">
<v-list-item-title>
<CVicon color="#c5c5c5" :right="true" text="add" tooltip="Add new pipeline"/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="deleteCurrentPipeline">
<v-list-item-title>
<CVicon color="red darken-2" :right="true" text="delete"
tooltip="Delete pipeline"/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="openDuplicateDialog">
<v-list-item-title>
<CVicon color="#c5c5c5" :right="true" text="mdi-content-copy"
tooltip="Duplicate pipeline"/>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<div v-else>
<CVicon color="#c5c5c5" style="display: inline-block;" hover text="save"
@click="savePipelineNameChange" tooltip="Save Pipeline Name"/>
<CVicon color="error" style="display: inline-block;" hover text="close"
@click="discardPipelineNameChange" tooltip="Discard Changes"/>
</div>
<v-col :cols="1" class="colsClass" md="3">
<v-menu v-if="isPipelineEdit === false" offset-y dark auto>
<template v-slot:activator="{ on }">
<v-icon color="white" v-on="on">menu</v-icon>
</template>
<v-list dense>
<v-list-item @click="toPipelineNameChange">
<v-list-item-title>
<CVicon color="#c5c5c5" :right="true" text="edit" tooltip="Edit pipeline name"/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="handleInput('command','addNewPipeline')">
<v-list-item-title>
<CVicon color="#c5c5c5" :right="true" text="add" tooltip="Add new pipeline"/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="deleteCurrentPipeline">
<v-list-item-title>
<CVicon color="red darken-2" :right="true" text="delete"
tooltip="Delete pipeline"/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="openDuplicateDialog">
<v-list-item-title>
<CVicon color="#c5c5c5" :right="true" text="mdi-content-copy"
tooltip="Duplicate pipeline"/>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<div v-else>
<CVicon color="#c5c5c5" style="display: inline-block;" hover text="save"
@click="savePipelineNameChange" tooltip="Save Pipeline Name"/>
<CVicon color="error" style="display: inline-block;" hover text="close"
@click="discardPipelineNameChange" tooltip="Discard Changes"/>
</div>
</v-col>
<v-btn style="position: absolute; top:5px;right: 0;" tile color="#4baf62"
@click="handleInput('command','save')">
<v-icon>save</v-icon>
Save
</v-btn>
</v-row>
</div>
<v-row>
<!-- vision tabs -->
<v-col cols="6" class="colsClass">
<v-tabs fixed-tabs background-color="#212121" dark height="48" slider-color="#4baf62" v-model="selectedTab">
<v-tabs fixed-tabs background-color="#212121" dark height="48" slider-color="#4baf62"
v-model="selectedTab">
<v-tab>Input</v-tab>
<v-tab>Threshold</v-tab>
<v-tab>Contours</v-tab>
<v-tab>Output</v-tab>
</v-tabs>
<div style="padding-left:30px">
<!-- vision component -->
<component v-model="pipeline" :is="selectedComponent"/>
<keep-alive>
<!-- vision component -->
<component v-model="pipeline" :is="selectedComponent" @update="startTimer"/>
</keep-alive>
</div>
</v-col>
<v-col cols="6" class="colsClass">
<div>
<!-- camera image tabs -->
<v-tabs background-color="#212121" dark height="48" slider-color="#4baf62" centered style="padding-bottom:10px" v-model="isBinaryNumber" @change="handleInput('isBinary',pipeline.isBinary)">
<v-tabs background-color="#212121" dark height="48" slider-color="#4baf62" centered
style="padding-bottom:10px" v-model="isBinaryNumber"
@change="handleInput('isBinary',pipeline.isBinary)">
<v-tab>Normal</v-tab>
<v-tab>Threshold</v-tab>
</v-tabs>
@@ -95,11 +106,11 @@
</div>
</div>
</v-col>
</v-row>
<!-- pipeline duplicate dialog -->
<v-dialog dark v-model="duplicateDialog" width="500" height="357" >
<v-card dark>
<v-card-title class="headline" primary-title>Duplicate Pipeline</v-card-title>
</v-row>
<!-- pipeline duplicate dialog -->
<v-dialog dark v-model="duplicateDialog" width="500" height="357">
<v-card dark>
<v-card-title class="headline" primary-title>Duplicate Pipeline</v-card-title>
<v-card-text>
<CVselect name="Pipeline" :list="pipelineList" v-model="pipelineDuplicate.pipeline"/>
<v-checkbox v-if="cameraList.length > 1" dark :label="'To another camera'" v-model="anotherCamera"/>
@@ -113,27 +124,34 @@
<v-btn color="#4baf62" text @click="duplicatePipeline">Duplicate</v-btn>
<v-btn color="error" text @click="closeDuplicateDialog">Cancels</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<!-- snack bar -->
<v-snackbar :timeout="3000" v-model="snackbar" top color="error">
</v-card>
</v-dialog>
<!-- snack bar -->
<v-snackbar :timeout="3000" v-model="snackbar" top color="error">
<span style="color:#000">Can not remove the only pipeline!</span>
<v-btn color="black" text @click="snackbar = false">Close</v-btn>
</v-snackbar>
</v-snackbar>
<v-snackbar :timeout="1000" v-model="saveSnackbar" top color="#4baf62">
<div style="text-align: center;width: 100%;">
<h4>Saved All changes</h4>
</div>
</v-snackbar>
</div>
</template>
<script>
import InputTab from './CameraViewes/InputTab'
import ThresholdTab from './CameraViewes/ThresholdTab'
import ContoursTab from './CameraViewes/ContoursTab'
import OutputTab from './CameraViewes/OutputTab'
import CVselect from '../components/cv-select'
import CVicon from '../components/cv-icon'
import CVinput from '../components/cv-input'
import InputTab from './CameraViewes/InputTab'
import ThresholdTab from './CameraViewes/ThresholdTab'
import ContoursTab from './CameraViewes/ContoursTab'
import OutputTab from './CameraViewes/OutputTab'
import CVselect from '../components/cv-select'
import CVicon from '../components/cv-icon'
import CVinput from '../components/cv-input'
export default {
name: 'CameraTab',
components:{
components: {
InputTab,
ThresholdTab,
ContoursTab,
@@ -142,107 +160,116 @@ import CVinput from '../components/cv-input'
CVicon,
CVinput
},
methods:{
test(value){
console.log(value)
},
toCameraNameChange(){
methods: {
toCameraNameChange() {
this.newCameraName = this.cameraList[this.currentCameraIndex];
this.isCameraNameEdit = true;
},
saveCameraNameChange(){
if(this.cameraNameError === ""){
this.handleInput("changeCameraName",this.newCameraName);
this.discardCameraNameChange();
saveCameraNameChange() {
if (this.cameraNameError === "") {
this.handleInput("changeCameraName", this.newCameraName);
this.discardCameraNameChange();
}
},
discardCameraNameChange(){
discardCameraNameChange() {
this.isCameraNameEdit = false;
this.newCameraName = "";
},
toPipelineNameChange(){
toPipelineNameChange() {
this.newPipelineName = this.pipelineList[this.currentPipelineIndex];
this.isPipelineEdit = true;
},
savePipelineNameChange(){
this.handleInput("changePipelineName",this.newPipelineName);
savePipelineNameChange() {
this.handleInput("changePipelineName", this.newPipelineName);
this.discardPipelineNameChange();
},
discardPipelineNameChange(){
discardPipelineNameChange() {
this.isPipelineEdit = false;
this.newPipelineName = "";
},
duplicatePipeline(){
if(!this.anotherCamera){
duplicatePipeline() {
if (!this.anotherCamera) {
this.pipelineDuplicate.camera = -1
}
this.handleInput("duplicatePipeline",this.pipelineDuplicate);
this.handleInput("duplicatePipeline", this.pipelineDuplicate);
this.closeDuplicateDialog();
},
openDuplicateDialog(){
openDuplicateDialog() {
this.pipelineDuplicate = {
pipeline:this.currentPipelineIndex,
camera:-1
pipeline: this.currentPipelineIndex,
camera: -1
}
this.duplicateDialog = true;
},
closeDuplicateDialog(){
closeDuplicateDialog() {
this.duplicateDialog = false;
this.pipelineDuplicate = {
pipeline:undefined,
camera:-1
pipeline: undefined,
camera: -1
}
},
deleteCurrentPipeline(){
deleteCurrentPipeline() {
if (this.pipelineList.length > 1) {
this.handleInput('command','deleteCurrentPipeline');
this.handleInput('command', 'deleteCurrentPipeline');
} else {
this.snackbar = true;
}
},
saveSettings() {
clearInterval(this.timer);
this.saveSnackbar = true;
},
startTimer() {
if (this.timer !== undefined) {
clearInterval(this.timer);
}
this.timer = setInterval(this.saveSettings, 4000);
}
},
data() {
return {
selectedTab:0,
selectedTab: 1,
// camera edit variables
isCameraNameEdit:false,
newCameraName:"",
cameraNameError:"",
isCameraNameEdit: false,
newCameraName: "",
cameraNameError: "",
// pipeline edit variables
isPipelineEdit:false,
newPipelineName:"",
duplicateDialog:false,
anotherCamera:false,
pipelineDuplicate:{
pipeline:undefined,
camera:-1
isPipelineEdit: false,
newPipelineName: "",
duplicateDialog: false,
anotherCamera: false,
pipelineDuplicate: {
pipeline: undefined,
camera: -1
},
snackbar:false
snackbar: false,
saveSnackbar: false,
timer: undefined
}
},
computed:{
checkCameraName(){
if(this.newCameraName !== this.cameraList[this.currentCameraIndex]){
for(let cam in this.cameraList){
if(this.newCameraName === this.cameraList[cam]){
computed: {
checkCameraName() {
if (this.newCameraName !== this.cameraList[this.currentCameraIndex]) {
for (let cam in this.cameraList) {
if (this.newCameraName === this.cameraList[cam]) {
return "Camera by that name already Exists"
}
}
}
return ""
},
isBinaryNumber:{
get(){
return this.pipeline.isBinary ? 1:0
isBinaryNumber: {
get() {
return this.pipeline.isBinary ? 1 : 0
},
set(value){
set(value) {
this.pipeline.isBinary = !!value;
}
},
selectedComponent:{
get(){
switch(this.selectedTab){
selectedComponent: {
get() {
switch (this.selectedTab) {
case 0:
return "InputTab";
case 1:
@@ -255,51 +282,51 @@ import CVinput from '../components/cv-input'
return "";
}
},
point:{
get:function(){
point: {
get: function () {
let p = this.$store.state.point.calculated;
let fps = this.$store.state.point.fps;
if(p !== undefined){
if (p !== undefined) {
return ("Pitch: " + parseFloat(p['pitch']).toFixed(2) + " Yaw: " + parseFloat(p['yaw']).toFixed(2) + " FPS: " + fps.toFixed(2))
} else{
} else {
return undefined;
}
}
},
currentCameraIndex:{
get(){
currentCameraIndex: {
get() {
return this.$store.state.currentCameraIndex;
},
set(value){
this.$store.commit('currentCameraIndex',value);
set(value) {
this.$store.commit('currentCameraIndex', value);
}
},
currentPipelineIndex:{
get(){
currentPipelineIndex: {
get() {
return this.$store.state.currentPipelineIndex;
},
set(value){
this.$store.commit('currentPipelineIndex',value);
set(value) {
this.$store.commit('currentPipelineIndex', value);
}
},
cameraList:{
get(){
cameraList: {
get() {
return this.$store.state.cameraList;
}
},
pipelineList:{
get(){
pipelineList: {
get() {
return this.$store.state.pipelineList;
}
},
pipeline:{
get(){
pipeline: {
get() {
return this.$store.state.pipeline;
}
},
streamAddress: {
get: function(){
return "http://"+location.hostname + ":"+ this.$store.state.port +"/stream.mjpg";
get: function () {
return "http://" + location.hostname + ":" + this.$store.state.port + "/stream.mjpg";
}
},
}
@@ -307,19 +334,22 @@ import CVinput from '../components/cv-input'
</script>
<style scoped>
.colsClass{
.colsClass {
padding: 0 !important;
}
.videoClass{
.videoClass {
text-align: center;
}
.videoClass img{
.videoClass img {
height: auto !important;
width: 70%;
vertical-align: middle;
}
#Point{
#Point {
padding-top: 5px;
text-align: center;
color: #f4f4f4;

View File

@@ -1,35 +1,47 @@
<template>
<div>
<CVrangeSlider v-model="value.area" name="Area" :min="0" :max="100" :step="0.1" @input="handleInput('area',value.area)"></CVrangeSlider>
<CVrangeSlider v-model="value.ratio" name="Ratio (W/H)" :min="0" :max="100" :step="0.1" @input="handleInput('ratio',value.ratio)"></CVrangeSlider>
<CVrangeSlider v-model="value.extent" name="Extent" :min="0" :max="100" @input="handleInput('extent',value.extent)"></CVrangeSlider>
<CVslider name="Speckle Rejection" :min="0" :max="100" v-model="value.speckle" @input="handleInput('speckle',value.speckle)"></CVslider>
<CVselect name="Target Group" :list="['Single','Dual']" v-model="value.targetGroup" @input="handleInput('targetGroup',value.targetGroup)"></CVselect>
<CVselect name="Target Intersection" :list="['None','Up','Down','Left','Right']" :disabled="isDisabled" v-model="value.targetIntersection" @input="handleInput('targetIntersection',value.targetIntersection)"></CVselect>
<CVrangeSlider v-model="value.area" name="Area" :min="0" :max="100" :step="0.1"
@input="handleData('area')"/>
<CVrangeSlider v-model="value.ratio" name="Ratio (W/H)" :min="0" :max="100" :step="0.1"
@input="handleData('ratio')"/>
<CVrangeSlider v-model="value.extent" name="Extent" :min="0" :max="100"
@input="handleData('extent')"/>
<CVslider name="Speckle Rejection" :min="0" :max="100" v-model="value.speckle"
@input="handleData('speckle')"/>
<CVselect name="Target Group" :list="['Single','Dual']" v-model="value.targetGroup"
@input="handleData('targetGroup')"/>
<CVselect name="Target Intersection" :list="['None','Up','Down','Left','Right']" :disabled="isDisabled"
v-model="value.targetIntersection" @input="handleData('targetIntersection')"/>
</div>
</template>
<script>
import CVrangeSlider from '../../components/cv-range-slider'
import CVselect from '../../components/cv-select'
import CVslider from '../../components/cv-slider'
import CVrangeSlider from '../../components/cv-range-slider'
import CVselect from '../../components/cv-select'
import CVslider from '../../components/cv-slider'
export default {
name: 'Contours',
props:['value'],
components:{
props: ['value'],
components: {
CVrangeSlider,
CVselect,
CVslider
},
data() {
return {
methods: {
handleData(val) {
this.handleInput(val, this.value[val])
this.$emit('update')
}
},
computed:{
isDisabled(){
if(this.value.targetGroup === 0){
data() {
return {}
},
computed: {
isDisabled() {
if (this.value.targetGroup === 0) {
return true;
}
return false;
@@ -39,5 +51,5 @@ import CVslider from '../../components/cv-slider'
</script>
<style lang="" scoped>
</style>

View File

@@ -1,34 +1,39 @@
<template>
<div>
<CVslider name="Exposure" v-model="value.exposure" :min="0" :max="100" @input="handleInput('exposure',value.exposure)"></CVslider>
<CVslider name="Brightness" v-model="value.brightness" :min="0" :max="100" @input="handleInput('brightness',value.brightness)"></CVslider>
<CVselect name="Orientation" v-model="value.orientation" :list="['Normal','Inverted']" @input="handleInput('orientation',value.orientation)"></CVselect>
<CVslider name="Exposure" v-model="value.exposure" :min="0" :max="100" @input="handleData('exposure')"/>
<CVslider name="Brightness" v-model="value.brightness" :min="0" :max="100" @input="handleData('brightness')"/>
<CVselect name="Orientation" v-model="value.orientation" :list="['Normal','Inverted']"
@input="handleData('orientation')"/>
</div>
</template>
<script>
import CVslider from '../../components/cv-slider'
import CVselect from '../../components/cv-select'
import CVslider from '../../components/cv-slider'
import CVselect from '../../components/cv-select'
export default {
name: 'Input',
props:['value'],
components:{
props: ['value'],
components: {
CVslider,
CVselect,
},
data() {
return {
t:0,
a:1
methods: {
handleData(val) {
this.handleInput(val, this.value[val])
this.$emit('update')
}
},
methods:{
data() {
return {
t: 0,
a: 1
}
},
computed:{}
computed: {}
}
</script>
<style scoped>
</style>

View File

@@ -2,12 +2,12 @@
<div>
<CVselect name="SortMode" v-model="value.sortMode"
:list="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Closest']"
@input="handleInput('sortMode',value.sortMode)"/>
@input="handleData('sortMode')"/>
<span>Calibrate:</span>
<v-divider dark color="white"/>
<CVselect name="Calibration Mode" v-model="value.calibrationMode" :list="['None','Single point','Dual point']"
@input="handleInput('calibrationMode',value.calibrationMode)"/>
<component :raw-point="rawPoint" :is="selectedComponent"/>
@input="handleData('calibrationMode')"/>
<component :raw-point="rawPoint" :is="selectedComponent" @update="doUpdate"/>
<v-snackbar :timeout="3000" v-model="snackbar" top color="error">
<span style="color:#000">Points are too close</span>
<v-btn color="black" text @click="snackbar = false">Close</v-btn>
@@ -16,19 +16,27 @@
</template>
<script>
import CVselect from '../../components/cv-select'
import DualCalibration from "../../components/OutputTab/DualCalibration";
import SingleCalibration from "../../components/OutputTab/SingleCalibration";
import CVselect from '../../components/cv-select'
import DualCalibration from "../../components/OutputTab/DualCalibration";
import SingleCalibration from "../../components/OutputTab/SingleCalibration";
export default {
name: 'Output',
props:['value'],
components:{
props: ['value'],
components: {
CVselect,
SingleCalibration,
DualCalibration,
},
methods:{
methods: {
handleData(val) {
this.handleInput(val, this.value[val])
this.$emit('update')
},
doUpdate() {
this.$emit('update')
}
},
data() {
@@ -36,9 +44,9 @@ import SingleCalibration from "../../components/OutputTab/SingleCalibration";
snackbar: false,
}
},
computed:{
selectedComponent:{
get(){
computed: {
selectedComponent: {
get() {
switch (this.value.calibrationMode) {
case 0:
return "";
@@ -50,8 +58,8 @@ import SingleCalibration from "../../components/OutputTab/SingleCalibration";
return ""
}
},
rawPoint:{
get(){
rawPoint: {
get() {
return this.$store.state.point.rawPoint;
}
}

View File

@@ -1,10 +1,11 @@
<template>
<div>
<CVrangeSlider v-model="value.hue" name="Hue" :min="0" :max="180" @input="handleInput('hue',value.hue)"></CVrangeSlider>
<CVrangeSlider v-model="value.saturation" name="Saturation" :min="0" :max="255" @input="handleInput('saturation',value.saturation)"></CVrangeSlider>
<CVrangeSlider v-model="value.value" name="Value" :min="0" :max="255" @input="handleInput('value',value.value)"></CVrangeSlider>
<CVswitch v-model="value.erode" name="Erode" @input="handleInput('erode',value.erode)"></CVswitch>
<CVswitch v-model="value.dilate" name="Dilate" @input="handleInput('dilate',value.dilate)"></CVswitch>
<CVrangeSlider v-model="value.hue" name="Hue" :min="0" :max="180" @input="handleData('hue')"/>
<CVrangeSlider v-model="value.saturation" name="Saturation" :min="0" :max="255"
@input="handleData('saturation')"/>
<CVrangeSlider v-model="value.value" name="Value" :min="0" :max="255" @input="handleData('value')"/>
<CVswitch v-model="value.erode" name="Erode" @input="handleData('erode')"/>
<CVswitch v-model="value.dilate" name="Dilate" @input="handleData('dilate')"/>
</div>
</template>
@@ -25,6 +26,10 @@ import CVswitch from '../../components/cv-switch'
computed:{
},
methods:{
handleData(val){
this.handleInput(val,this.value[val])
this.$emit('update')
}
}
}
</script>

View File

@@ -2,12 +2,13 @@
<div>
<v-row>
<v-col cols="6" class="colsClass">
<v-tabs fixed-tabs background-color="#212121" dark height="50" slider-color="#4baf62" v-model="selectedTab">
<v-tabs fixed-tabs background-color="#212121" dark height="50" slider-color="#4baf62"
v-model="selectedTab">
<v-tab to="">General</v-tab>
<v-tab to="">Cameras</v-tab>
</v-tabs>
<div style="padding-left:30px">
<component :is="selectedComponent"></component>
<component :is="selectedComponent"/>
</div>
</v-col>
<v-col v-show="selectedTab === 1" class="colsClass">
@@ -15,28 +16,28 @@
<img :src="steamAdress">
</div>
</v-col>
</v-row>
</v-row>
</div>
</template>
<script>
import General from './SettingsViewes/General'
import Cameras from './SettingsViewes/Cameras'
import General from './SettingsViewes/General'
import Cameras from './SettingsViewes/Cameras'
export default {
name: 'SettingsTab',
components:{
components: {
General,
Cameras,
},
data() {
return {
selectedTab:0,
selectedTab: 0,
}
},
computed:{
selectedComponent(){
switch(this.selectedTab){
computed: {
selectedComponent() {
switch (this.selectedTab) {
case 0:
return "General";
case 1:
@@ -44,8 +45,8 @@ import Cameras from './SettingsViewes/Cameras'
}
},
steamAdress: {
get: function(){
return "http://"+location.hostname + ":"+ this.$store.state.port +"/stream.mjpg";
get: function () {
return "http://" + location.hostname + ":" + this.$store.state.port + "/stream.mjpg";
}
},
}
@@ -53,16 +54,18 @@ import Cameras from './SettingsViewes/Cameras'
</script>
<style scoped>
.videoClass{
.videoClass {
text-align: center;
}
.videoClass img{
.videoClass img {
padding-top: 10px;
height: auto !important;
width: 75%;
vertical-align: middle;
}
.colsClass{
.colsClass {
padding: 0 !important;
}
</style>

View File

@@ -1,69 +1,69 @@
<template>
<div>
<CVselect name="Camera" :list="cameraList" v-model="currentCameraIndex"></CVselect>
<CVselect name="Resolution" v-model="cameraSettings.resolution" :list="resolutionList"></CVselect>
<CVselect name="Stream Resolution" v-model="cameraSettings.streamDivisor" :list="['1:1','1:2','1:4','1:6']"></CVselect>
<CVnumberinput name="Diagonal FOV" v-model="cameraSettings.fov" ></CVnumberinput>
<CVselect name="Camera" :list="cameraList" v-model="currentCameraIndex"/>
<CVselect name="Resolution" v-model="cameraSettings.resolution" :list="resolutionList"/>
<CVselect name="Stream Resolution" v-model="cameraSettings.streamDivisor"
:list="['1:1','1:2','1:4','1:6']"/>
<CVnumberinput name="Diagonal FOV" v-model="cameraSettings.fov"/>
<v-btn style="margin-top:10px" small color="#4baf62" @click="sendCameraSettings">Save Camera Settings</v-btn>
</div>
</template>
<script>
import CVselect from '../../components/cv-select'
import CVnumberinput from '../../components/cv-number-input'
import CVselect from '../../components/cv-select'
import CVnumberinput from '../../components/cv-number-input'
export default {
name: 'CameraSettings',
components:{
components: {
CVselect,
CVnumberinput
},
data() {
return {
}
return {}
},
methods:{
sendCameraSettings(){
this.handleInput('cameraSettings',this.cameraSettings);
methods: {
sendCameraSettings() {
this.handleInput('cameraSettings', this.cameraSettings);
},
},
computed:{
currentCameraIndex:{
get(){
},
computed: {
currentCameraIndex: {
get() {
return this.$store.state.currentCameraIndex;
},
set(value){
this.$store.commit('currentCameraIndex',value);
set(value) {
this.$store.commit('currentCameraIndex', value);
}
},
cameraList:{
get(){
cameraList: {
get() {
return this.$store.state.cameraList;
},
set(value){
this.$store.commit('cameraList',value);
set(value) {
this.$store.commit('cameraList', value);
}
},
resolutionList:{
get(){
resolutionList: {
get() {
return this.$store.state.resolutionList;
}
},
cameraSettings:{
get(){
cameraSettings: {
get() {
return this.$store.state.cameraSettings;
},
set(value){
this.$store.commit('cameraSettings',value);
set(value) {
this.$store.commit('cameraSettings', value);
}
},
}
}
</script>
<style lang="" scoped>
</style>

View File

@@ -1,46 +1,46 @@
<template>
<div>
<CVnumberinput v-model="settings.teamNumber" name="Team Number"></CVnumberinput>
<CVradio v-model="settings.connectionType" :list="['DHCP','Static']"></CVradio>
<v-divider color="white"></v-divider>
<CVinput name="IP" v-model="settings.ip" :disabled="isDisabled"></CVinput>
<CVinput name="NetMask" v-model="settings.netmask" :disabled="isDisabled"></CVinput>
<CVinput name="Gateway" v-model="settings.gateway" :disabled="isDisabled"></CVinput>
<v-divider color="white"></v-divider>
<CVinput name="Hostname" v-model="settings.hostname"></CVinput>
<CVnumberinput v-model="settings.teamNumber" name="Team Number"/>
<CVradio v-model="settings.connectionType" :list="['DHCP','Static']"/>
<v-divider color="white"/>
<CVinput name="IP" v-model="settings.ip" :disabled="isDisabled"/>
<CVinput name="NetMask" v-model="settings.netmask" :disabled="isDisabled"/>
<CVinput name="Gateway" v-model="settings.gateway" :disabled="isDisabled"/>
<v-divider color="white"/>
<CVinput name="Hostname" v-model="settings.hostname"/>
<v-btn style="margin-top:10px" small color="#4baf62" @click="sendGeneralSettings">Save General Settings</v-btn>
</div>
</template>
<script>
import CVnumberinput from '../../components/cv-number-input'
import CVradio from '../../components/cv-radio'
import CVinput from '../../components/cv-input'
import CVnumberinput from '../../components/cv-number-input'
import CVradio from '../../components/cv-radio'
import CVinput from '../../components/cv-input'
export default {
name: 'General',
components:{
components: {
CVnumberinput,
CVradio,
CVinput
},
data() {
return {
return {}
},
methods: {
sendGeneralSettings() {
this.handleInput('generalSettings', this.settings);
}
},
methods:{
sendGeneralSettings(){
this.handleInput('generalSettings',this.settings);
}
},
computed:{
isDisabled(){
if(this.settings.connectionType === 0){
computed: {
isDisabled() {
if (this.settings.connectionType === 0) {
return true;
}
return false;
},
settings:{
get(){
settings: {
get() {
return this.$store.state.settings;
}
}
@@ -49,5 +49,5 @@ import CVinput from '../../components/cv-input'
</script>
<style lang="" scoped>
</style>