From dbb1316cdf4213828adbd4c03f815968314fb692 Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Wed, 28 Feb 2024 17:24:49 -0700 Subject: [PATCH 1/4] Access video in detect page Signed-off-by: Justin Georgi --- src/pages/detect.vue | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/pages/detect.vue b/src/pages/detect.vue index a0f7adb..5a7794b 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -7,7 +7,11 @@
- + +
+ + Capture +
- + @@ -321,7 +325,9 @@ uploadUid: null, uploadDirty: false, modelLocation: '', - modelLoading: false + modelLoading: false, + videoAvailable: false, + cameraStream: null } }, setup() { @@ -573,8 +579,24 @@ f7.dialog.alert(`Error loading image: ${e.message}`) }) }, - videoStream() { + async videoStream() { //TODO + 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 null }, async submitData () { -- 2.49.1 From 9f47f560624f4155b9ad59b56737ba77e40b7b9f Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Sun, 3 Mar 2024 08:57:46 -0700 Subject: [PATCH 2/4] Capture video frame for detection Signed-off-by: Justin Georgi --- src/pages/detect.vue | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pages/detect.vue b/src/pages/detect.vue index 5a7794b..10bd31e 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -10,7 +10,7 @@
- Capture + Capture
@@ -545,7 +545,10 @@ }, getImage (searchImage) { let loadImage = new Promise(resolve => { - if (this.isCordova && this.imageLoadMode == "camera") { + if (this.videoAvailable) { + this.videoAvailable = false + resolve(searchImage) + } else if (this.isCordova && this.imageLoadMode == "camera") { resolve('data:image/jpg;base64,' + searchImage) } else { const searchImage = this.$refs.image_chooser.files[0] @@ -599,6 +602,16 @@ this.cameraStream = stream return null }, + 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 }) -- 2.49.1 From b9d1b5c5ff03147359b85b7c06cba8889e4e4c8c Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Sun, 3 Mar 2024 16:32:46 -0700 Subject: [PATCH 3/4] Stop video when frame selected Signed-off-by: Justin Georgi --- src/pages/detect.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/detect.vue b/src/pages/detect.vue index 10bd31e..f9bdb37 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -546,6 +546,7 @@ getImage (searchImage) { let loadImage = new Promise(resolve => { if (this.videoAvailable) { + this.cameraStream.getTracks().forEach( t => t.stop()) this.videoAvailable = false resolve(searchImage) } else if (this.isCordova && this.imageLoadMode == "camera") { -- 2.49.1 From 77e33b1c53a3fe0db71d47ff5f5d518112c95390 Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Mon, 4 Mar 2024 16:57:17 -0700 Subject: [PATCH 4/4] Replace camera load with in-page camera access Signed-off-by: Justin Georgi --- src/pages/detect.vue | 54 +++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/pages/detect.vue b/src/pages/detect.vue index f9bdb37..5bce9ad 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -51,7 +51,7 @@ - + @@ -326,6 +326,7 @@ uploadDirty: false, modelLocation: '', modelLoading: false, + videoDeviceAvailable: false, videoAvailable: false, cameraStream: null } @@ -486,18 +487,36 @@ this.detectorLabels.forEach( s => s.detect = false ) } }, - selectImage (mode) { + async selectImage (mode) { this.imageLoadMode = mode - if (mode == "camera") { - this.$refs.image_chooser.setAttribute("capture","environment") - } else { - this.$refs.image_chooser.removeAttribute("capture") - } if (this.isCordova && mode == "camera") { navigator.camera.getPicture(this.getImage, this.onFail, { quality: 50, destinationType: Camera.DestinationType.DATA_URL, correctOrientation: true }); - } else { - var loadResult = this.$refs.image_chooser.click() + 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 + } + } + var loadResult = this.$refs.image_chooser.click() }, onFail (message) { alert(`Camera fail: ${message}`) @@ -585,23 +604,6 @@ }, async videoStream() { //TODO - 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 null }, captureVidFrame() { const vidViewer = this.$refs.vid_viewer -- 2.49.1