diff --git a/src/pages/camera-mixin.js b/src/pages/camera-mixin.js new file mode 100644 index 0000000..a40539a --- /dev/null +++ b/src/pages/camera-mixin.js @@ -0,0 +1,45 @@ +export default { + methods: { + async openCamera() { + var cameraLoaded = false + const devicesList = await navigator.mediaDevices.enumerateDevices() + this.videoDeviceAvailable = devicesList.some( d => d.kind == "videoinput") + if (this.videoDeviceAvailable) { + navigator.mediaDevices.getUserMedia({video: true}) + var vidConstraint = { + video: { + width: { + ideal: 1920 + }, + height: { + ideal: 1080 + }, + facingMode: 'environment' + }, + audio: false + } + const stream = await navigator.mediaDevices.getUserMedia(vidConstraint); + cameraLoaded = true + this.cameraStream = stream + } + return cameraLoaded + }, + closeCamera () { + this.cameraStream.getTracks().forEach( t => t.stop()) + this.videoAvailable = false + }, + captureVidFrame() { + const vidViewer = this.$refs.vid_viewer + vidViewer.pause() + let tempCVS = document.createElement('canvas') + tempCVS.height = vidViewer.videoHeight || parseInt(vidViewer.style.height) + tempCVS.width = vidViewer.videoWidth || parseInt(vidViewer.style.width) + const tempCtx = tempCVS.getContext('2d') + tempCtx.drawImage(vidViewer, 0, 0) + this.getImage(tempCVS.toDataURL()) + }, + async videoStream() { + //TODO + } + } +} \ No newline at end of file diff --git a/src/pages/detect.vue b/src/pages/detect.vue index 7ea0251..d46a385 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -109,13 +109,13 @@ import SvgIcon from '../components/svg-icon.vue' import submitMixin from './submit-mixin' - import localDetectMixin from './local-detect' - import remoteDetectMixin from './remote-detect' + import detectionMixin from './detection-mixin' + import cameraMixin from './camera-mixin' import thoraxClasses from '../models/thorax/classes.json' export default { - mixins: [submitMixin, localDetectMixin, remoteDetectMixin], + mixins: [submitMixin, detectionMixin, cameraMixin], props: { f7route: Object, }, @@ -160,9 +160,9 @@ this.detectorName = 'thorax' this.classesList = thoraxClasses /* VITE setting */ - //this.modelLocation = '../models/thorax/model.json' + this.modelLocation = '../models/thorax/model.json' /* PWA Build setting */ - this.modelLocation = './models/thorax/model.json' + //this.modelLocation = './models/thorax/model.json' this.modelLocationCordova = 'https://localhost/models/thorax/model.json' break; case 'abdomen': @@ -260,29 +260,10 @@ return } if (mode == "camera") { - const devicesList = await navigator.mediaDevices.enumerateDevices() - this.videoDeviceAvailable = devicesList.some( d => d.kind == "videoinput") - if (this.videoDeviceAvailable) { - navigator.mediaDevices.getUserMedia({video: true}) - var vidConstraint = { - video: { - width: { - ideal: 1920 - }, - height: { - ideal: 1080 - }, - facingMode: 'environment' - }, - audio: false - } - const stream = await navigator.mediaDevices.getUserMedia(vidConstraint); - this.videoAvailable = true - this.cameraStream = stream - return - } + this.videoAvailable = await this.openCamera() + if (this.videoAvailable) { return } } - var loadResult = this.$refs.image_chooser.click() + this.$refs.image_chooser.click() }, onFail (message) { alert(`Camera fail: ${message}`) @@ -331,8 +312,7 @@ getImage (searchImage) { let loadImage = new Promise(resolve => { if (this.videoAvailable) { - this.cameraStream.getTracks().forEach( t => t.stop()) - this.videoAvailable = false + this.closeCamera() this.detecting = true resolve(searchImage) } else if (this.isCordova && this.imageLoadMode == "camera") { @@ -370,19 +350,6 @@ f7.dialog.alert(`Error loading image: ${e.message}`) }) }, - async videoStream() { - //TODO - }, - captureVidFrame() { - const vidViewer = this.$refs.vid_viewer - vidViewer.pause() - let tempCVS = document.createElement('canvas') - tempCVS.height = vidViewer.videoHeight || parseInt(vidViewer.style.height) - tempCVS.width = vidViewer.videoWidth || parseInt(vidViewer.style.width) - const tempCtx = tempCVS.getContext('2d') - tempCtx.drawImage(vidViewer, 0, 0) - this.getImage(tempCVS.toDataURL()) - }, async submitData () { var uploadData = this.showResults .filter( d => { return d.aboveThreshold && d.isSearched && !d.isDeleted }) diff --git a/src/pages/local-detect.js b/src/pages/detection-mixin.js similarity index 54% rename from src/pages/local-detect.js rename to src/pages/detection-mixin.js index f9967d7..ba6c642 100644 --- a/src/pages/local-detect.js +++ b/src/pages/detection-mixin.js @@ -1,4 +1,5 @@ import * as tf from '@tensorflow/tfjs' +import { f7 } from 'framework7-vue' var model = null @@ -77,6 +78,70 @@ export default { console.timeEnd('post-process') return output + }, + getRemoteLabels() { + var self = this + var modelURL = `http://${this.serverSettings.address}:${this.serverSettings.port}/detectors` + var xhr = new XMLHttpRequest() + xhr.open("GET", modelURL) + xhr.setRequestHeader('Content-Type', 'application/json') + xhr.timeout = 10000 + xhr.ontimeout = this.remoteTimeout + xhr.onload = function () { + if (this.status !== 200) { + console.log(xhr.response) + const errorResponse = JSON.parse(xhr.response) + f7.dialog.alert(`ALVINN has encountered an error: ${errorResponse.error}`) + return + } + var detectors = JSON.parse(xhr.response).detectors + var findLabel = detectors + .find( d => { return d.name == self.detectorName } )?.labels + .filter( l => { return l != "" } ).sort() + .map( l => { return {'name': l, 'detect': true} } ) + self.detectorLabels = findLabel || [] + } + xhr.onerror = function (e) { + f7.dialog.alert('ALVINN has encountered an unknown server error') + return + } + + xhr.send() + }, + remoteDetect() { + var self = this + var modelURL = `http://${this.serverSettings.address}:${this.serverSettings.port}/detect` + var xhr = new XMLHttpRequest() + xhr.open("POST", modelURL) + xhr.timeout = 10000 + xhr.ontimeout = this.remoteTimeout + xhr.setRequestHeader('Content-Type', 'application/json') + xhr.onload = function () { + self.detecting = false + if (this.status !== 200) { + console.log(xhr.response) + const errorResponse = JSON.parse(xhr.response) + f7.dialog.alert(`ALVINN has encountered an error: ${errorResponse.error}`) + return; + } + self.resultData = JSON.parse(xhr.response) + self.uploadDirty = true + } + + var doodsData = { + "detector_name": this.detectorName, + "detect": { + "*": 1 + }, + "data": this.imageView.src.split(',')[1] + } + + xhr.send(JSON.stringify(doodsData)) + }, + remoteTimeout () { + this.detecting = false + f7.dialog.alert('No connection to remote ALVINN instance. Please check app settings.') } + } } \ No newline at end of file diff --git a/src/pages/remote-detect.js b/src/pages/remote-detect.js deleted file mode 100644 index f8282fa..0000000 --- a/src/pages/remote-detect.js +++ /dev/null @@ -1,63 +0,0 @@ -export default { - methods: { - getRemoteLabels() { - var self = this - var modelURL = `http://${this.serverSettings.address}:${this.serverSettings.port}/detectors` - var xhr = new XMLHttpRequest() - xhr.open("GET", modelURL) - xhr.setRequestHeader('Content-Type', 'application/json') - xhr.timeout = 10000 - xhr.ontimeout = this.remoteTimeout - xhr.onload = function () { - if (this.status !== 200) { - console.log(xhr.response) - const errorResponse = JSON.parse(xhr.response) - f7.dialog.alert(`ALVINN has encountered an error: ${errorResponse.error}`) - return - } - var detectors = JSON.parse(xhr.response).detectors - var findLabel = detectors - .find( d => { return d.name == self.detectorName } )?.labels - .filter( l => { return l != "" } ).sort() - .map( l => { return {'name': l, 'detect': true} } ) - self.detectorLabels = findLabel || [] - } - - xhr.send() - }, - remoteDetect() { - var self = this - var modelURL = `http://${this.serverSettings.address}:${this.serverSettings.port}/detect` - var xhr = new XMLHttpRequest() - xhr.open("POST", modelURL) - xhr.timeout = 10000 - xhr.ontimeout = this.remoteTimeout - xhr.setRequestHeader('Content-Type', 'application/json') - xhr.onload = function () { - self.detecting = false - if (this.status !== 200) { - console.log(xhr.response) - const errorResponse = JSON.parse(xhr.response) - f7.dialog.alert(`ALVINN has encountered an error: ${errorResponse.error}`) - return; - } - self.resultData = JSON.parse(xhr.response) - self.uploadDirty = true - } - - var doodsData = { - "detector_name": this.detectorName, - "detect": { - "*": 1 - }, - "data": this.imageView.src.split(',')[1] - } - - xhr.send(JSON.stringify(doodsData)) - }, - remoteTimeout () { - this.detecting = false - f7.dialog.alert('No connection to remote ALVINN instance. Please check app settings.') - } - } -} \ No newline at end of file