diff --git a/src/components/svg-icon.vue b/src/components/svg-icon.vue index 5e64430..e3b27ff 100644 --- a/src/components/svg-icon.vue +++ b/src/components/svg-icon.vue @@ -17,6 +17,8 @@ + + @@ -44,7 +46,9 @@ 'limbs', 'head', 'photo_sample', - 'reset_slide' + 'reset_slide', + 'zoom_to', + 'reset_zoom' ] return iconList.includes(value) } diff --git a/src/pages/detect.vue b/src/pages/detect.vue index 243077d..06882f6 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -9,15 +9,28 @@ +
Capture
- +
- - - - + + + + + + + {{ showResults.length - numResults }} @@ -93,23 +109,6 @@ - - - - - - - - - - - - - - - - - @@ -139,11 +138,12 @@ import submitMixin from './submit-mixin' import detectionMixin from './detection-mixin' import cameraMixin from './camera-mixin' + import touchMixin from './touch-mixin' import detectionWorker from '@/assets/detect-worker.js?worker&inline' export default { - mixins: [submitMixin, detectionMixin, cameraMixin], + mixins: [submitMixin, detectionMixin, cameraMixin, touchMixin], props: { f7route: Object, }, @@ -160,6 +160,7 @@ classesList: [], imageLoaded: false, imageView: new Image(), + imCvsLocation: {}, imageLoadMode: "environment", detecting: false, detectPanel: false, @@ -181,7 +182,12 @@ cameraStream: null, infoLinkPos: {}, detectWorker: null, - vidWorker: null + vidWorker: null, + canvasMoving: false, + canvasOffset: {x: 0, y: 0}, + canvasZoom: 1, + structureZoomed: false, + debugInfo: null } }, setup() { @@ -334,6 +340,9 @@ self.reloadModel = false loadSuccess() } + f7.utils.nextFrame(() => { + this.selectChip("redraw") + }) } } @@ -375,6 +384,9 @@ f7.dialog.alert(`ALVINN structure finding error: ${e.message}`) }) } + f7.utils.nextFrame(() => { + this.selectChip("redraw") + }) }, selectAll (ev) { if (ev.target.checked) { @@ -446,10 +458,8 @@ let boxTop = boxCoords.cvsTop let boxWidth = boxCoords.cvsRight - boxCoords.cvsLeft let boxHeight = boxCoords.cvsBottom - boxCoords.cvsTop - this.infoLinkPos.x = boxCoords.cvsLeft - this.infoLinkPos.y = boxCoords.cvsTop - let boxMin = Math.min(boxHeight, boxWidth) - this.infoLinkPos.adj = (boxMin >= 50) ? 0 : Math.min(10, 50 - boxMin) + this.infoLinkPos.x = Math.min(Math.max(boxCoords.cvsLeft * this.canvasZoom + this.canvasOffset.x, 0),imCanvas.width) + this.infoLinkPos.y = Math.min(Math.max(boxCoords.cvsTop * this.canvasZoom + this.canvasOffset.y, 0), imCanvas.height) imageCtx.strokeRect(boxLeft, boxTop, boxWidth, boxHeight) this.selectedChip = iChip @@ -473,9 +483,20 @@ imCanvas.width = imCanvas.clientWidth imCanvas.height = imCanvas.clientHeight imageCtx.clearRect(0,0,imCanvas.width,imCanvas.height) + imageCtx.translate(this.canvasOffset.x,this.canvasOffset.y) + imageCtx.scale(this.canvasZoom,this.canvasZoom) imageCtx.globalAlpha = 1 imageCtx.strokeStyle = 'yellow' - imageCtx.lineWidth = 3 + imageCtx.lineWidth = 3 / this.canvasZoom + if (this.imageLoaded) { + let imageLoc = this.box2cvs({top: 0,left: 0,right: 1,bottom: 1}) + this.imCvsLocation.top = imageLoc[0].cvsTop + this.imCvsLocation.left = imageLoc[0].cvsLeft + this.imCvsLocation.width = imageLoc[0].cvsRight - imageLoc[0].cvsLeft + this.imCvsLocation.height = imageLoc[0].cvsBottom - imageLoc[0].cvsTop + imageCtx.drawImage(this.imageView, 0, 0, this.imageView.width, this.imageView.height, this.imCvsLocation.left, this.imCvsLocation.top, this.imCvsLocation.width, this.imCvsLocation.height) + } + this.structureZoomed = false return [imCanvas, imageCtx] }, getImage (searchImage) { @@ -516,8 +537,18 @@ this.imageView.src = imgData return(this.imageView.decode()) }).then( () => { - const [imCanvas, _] = this.resetView() - imCanvas.style['background-image'] = `url(${this.imageView.src})` + this.canvasOffset = {x: 0, y: 0} + this.canvasZoom = 1 + const imCanvas = this.$refs.image_cvs + imCanvas.width = imCanvas.clientWidth + imCanvas.height = imCanvas.clientHeight + const imageCtx = imCanvas.getContext("2d") + let imageLoc = this.box2cvs({top: 0,left: 0,right: 1,bottom: 1}) + this.imCvsLocation.top = imageLoc[0].cvsTop + this.imCvsLocation.left = imageLoc[0].cvsLeft + this.imCvsLocation.width = imageLoc[0].cvsRight - imageLoc[0].cvsLeft + this.imCvsLocation.height = imageLoc[0].cvsBottom - imageLoc[0].cvsTop + imageCtx.drawImage(this.imageView, 0, 0, this.imageView.width, this.imageView.height, this.imCvsLocation.left, this.imCvsLocation.top, this.imCvsLocation.width, this.imCvsLocation.height) f7.utils.nextFrame(() => { this.setData() }) @@ -538,10 +569,12 @@ }, structureClick(e) { const boxCoords = this.box2cvs(this.showResults) - var findBox = boxCoords.findIndex( (r, i) => { return r.cvsLeft <= e.offsetX && - r.cvsRight >= e.offsetX && - r.cvsTop <= e.offsetY && - r.cvsBottom >= e.offsetY && + let clickX = (e.offsetX - this.canvasOffset.x) / this.canvasZoom + let clickY = (e.offsetY - this.canvasOffset.y) / this.canvasZoom + var findBox = boxCoords.findIndex( (r, i) => { return r.cvsLeft <= clickX && + r.cvsRight >= clickX && + r.cvsTop <= clickY && + r.cvsBottom >= clickY && this.resultData.detections[i].resultIndex > this.selectedChip && this.resultData.detections[i].aboveThreshold && this.resultData.detections[i].isSearched && @@ -552,7 +585,7 @@ box2cvs(boxInput) { if (!boxInput || boxInput.length == 0) return [] const boxList = boxInput.length ? boxInput : [boxInput] - const [imCanvas, imageCtx] = this.resetView() + const imCanvas = this.$refs.image_cvs var imgWidth var imgHeight const imgAspect = this.imageView.width / this.imageView.height @@ -573,6 +606,57 @@ } }) return cvsCoords + }, + toggleSettings() { + this.showDetectSettings = !this.showDetectSettings + f7.utils.nextFrame(() => { + this.selectChip("redraw") + }) + }, + startMove() { + this.canvasMoving = true + }, + endMove() { + this.canvasMoving = false + }, + makeMove(event) { + if (this.canvasMoving) { + this.canvasOffset.x += event.movementX + this.canvasOffset.y += event.movementY + this.selectChip("redraw") + } + }, + spinWheel(event) { + let zoomFactor + if (event.wheelDelta > 0) { + zoomFactor = 1.05 + } else if (event.wheelDelta < 0) { + zoomFactor = 1 / 1.05 + } + this.canvasZoom *= zoomFactor + this.canvasOffset.x = event.offsetX * (1 - zoomFactor) + this.canvasOffset.x * zoomFactor + this.canvasOffset.y = event.offsetY * (1 - zoomFactor) + this.canvasOffset.y * zoomFactor + this.selectChip("redraw") + }, + resetZoom() { + this.canvasZoom = 1 + this.canvasOffset.x = 0 + this.canvasOffset.y = 0 + this.selectChip("redraw") + }, + zoomToSelected() { + const imCanvas = this.$refs.image_cvs + const boxCoords = this.box2cvs(this.resultData.detections[this.selectedChip])[0] + const boxWidth = boxCoords.cvsRight - boxCoords.cvsLeft + const boxHeight = boxCoords.cvsBottom - boxCoords.cvsTop + const boxMidX = (boxCoords.cvsRight + boxCoords.cvsLeft ) / 2 + const boxMidY = (boxCoords.cvsBottom + boxCoords.cvsTop ) / 2 + const zoomFactor = Math.min(imCanvas.width / boxWidth * .9, imCanvas.height / boxHeight * .9, 8) + this.canvasZoom = zoomFactor + this.canvasOffset.x = -(boxMidX * zoomFactor) + imCanvas.width / 2 + this.canvasOffset.y = -(boxMidY * zoomFactor) + imCanvas.height / 2 + this.selectChip("redraw") + this.structureZoomed = true } } } diff --git a/src/pages/touch-mixin.js b/src/pages/touch-mixin.js new file mode 100644 index 0000000..4c4981c --- /dev/null +++ b/src/pages/touch-mixin.js @@ -0,0 +1,53 @@ +export default { + data () { + return { + touchPrevious: {} + } + }, + methods: { + startTouch(event) { + if (event.touches.length == 1) { + this.touchPrevious = {x: event.touches[0].clientX, y: event.touches[0].clientY} + } + if (event.touches.length == 2) { + let midX = (event.touches.item(0).clientX + event.touches.item(1).clientX) / 2 + let midY = (event.touches.item(0).clientY + event.touches.item(1).clientY) / 2 + this.touchPrevious = {distance: this.touchDistance(event.touches), x: midX, y: midY} + } + }, + endTouch(event) { + if (event.touches.length == 1) { + this.touchPrevious = {x: event.touches[0].clientX, y: event.touches[0].clientY} + } else { + //this.debugInfo = null + } + }, + moveTouch(event) { + switch (event.touches.length) { + case 1: + console.log(event) + this.canvasOffset.x += event.touches[0].clientX - this.touchPrevious.x + this.canvasOffset.y += event.touches[0].clientY - this.touchPrevious.y + this.touchPrevious = {x: event.touches[0].clientX, y: event.touches[0].clientY} + break; + case 2: + let newDistance = this.touchDistance(event.touches) + let midX = (event.touches.item(0).clientX + event.touches.item(1).clientX) / 2 + let midY = (event.touches.item(0).clientY + event.touches.item(1).clientY) / 2 + let scale = newDistance / this.touchPrevious.distance + let scaleChange = this.canvasZoom * (scale - 1) + this.canvasZoom *= scale + this.canvasOffset.x += -((midX - 16) * scaleChange) + (midX - this.touchPrevious.x) + this.canvasOffset.y += -((midY - 96) * scaleChange) + (midY - this.touchPrevious.y) + this.touchPrevious = {distance: newDistance, x: midX, y: midY} + break; + } + this.selectChip("redraw") + }, + touchDistance(touches) { + let touch1 = touches.item(0) + let touch2 = touches.item(1) + return Math.sqrt((touch1.clientX - touch2.clientX) ** 2 + (touch1.clientY - touch2.clientY) ** 2) + } + } +} \ No newline at end of file