Selaa lähdekoodia

Capture image from AR

master
kj1352 4 vuotta sitten
vanhempi
commit
6d688ef88d
6 muutettua tiedostoa jossa 181 lisäystä ja 20 poistoa
  1. +34
    -0
      package-lock.json
  2. +8
    -0
      package.json
  3. +17
    -5
      src/app/ar-fan-cam/ar-fan-cam.page.html
  4. +66
    -5
      src/app/ar-fan-cam/ar-fan-cam.page.scss
  5. +46
    -9
      src/app/ar-fan-cam/ar-fan-cam.page.ts
  6. +10
    -1
      src/app/fan-zone/fan-zone.page.ts

+ 34
- 0
package-lock.json Näytä tiedosto

@@ -2343,6 +2343,12 @@
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
},
"@types/dom-mediacapture-record": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/dom-mediacapture-record/-/dom-mediacapture-record-1.0.7.tgz",
"integrity": "sha512-ddDIRTO1ajtbxaNo2o7fPJggpN54PZf1ZUJKOjto2ENMJE/9GKUvaw3ZRuQzlS/p0E+PnIcssxfoqYJ4yiXSBw==",
"dev": true
},
"@types/glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -4909,6 +4915,21 @@
"timsort": "^0.3.0"
}
},
"css-line-break": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.1.1.tgz",
"integrity": "sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==",
"requires": {
"base64-arraybuffer": "^0.2.0"
},
"dependencies": {
"base64-arraybuffer": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz",
"integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ=="
}
}
},
"css-loader": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.3.tgz",
@@ -5556,6 +5577,11 @@
"resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz",
"integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q=="
},
"dom-to-image": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/dom-to-image/-/dom-to-image-2.6.0.tgz",
"integrity": "sha1-ilA2CAiMh7HCL5A0rgMuGJiVWGc="
},
"domain-browser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
@@ -7207,6 +7233,14 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
"html2canvas": {
"version": "1.0.0-rc.7",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.7.tgz",
"integrity": "sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==",
"requires": {
"css-line-break": "1.1.1"
}
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",


+ 8
- 0
package.json Näytä tiedosto

@@ -11,6 +11,11 @@
"lint": "ng lint",
"e2e": "ng e2e"
},
"browser": {
"fs": false,
"os": false,
"path": false
},
"private": true,
"dependencies": {
"@angular/common": "~10.0.0",
@@ -28,10 +33,12 @@
"@ionic-native/status-bar": "^5.0.0",
"@ionic/angular": "^5.0.0",
"cordova-res": "^0.15.2",
"dom-to-image": "^2.6.0",
"face-api.js": "^0.22.2",
"faker": "^5.1.0",
"firebase": "^8.2.6",
"hammerjs": "^2.0.8",
"html2canvas": "^1.0.0-rc.7",
"moment": "^2.29.1",
"rxjs": "~6.5.5",
"sharp": "^0.27.0",
@@ -47,6 +54,7 @@
"@angular/compiler-cli": "~10.0.0",
"@angular/language-service": "~10.0.0",
"@ionic/angular-toolkit": "^2.3.0",
"@types/dom-mediacapture-record": "^1.0.7",
"@types/jasmine": "~3.5.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",


+ 17
- 5
src/app/ar-fan-cam/ar-fan-cam.page.html Näytä tiedosto

@@ -1,9 +1,21 @@
<ion-content>
<div class="container">
<button class="back-button" (click)="back()"> <ion-icon name="close-outline"></ion-icon> </button>

<div class="container" #container id="container">
<img class="glass-image" [ngStyle]="glassProperties" src="/assets/ar-accessories/glass.png" alt=""/>
<video id="playback-video" #videoElement autoPlay></video>
<button *ngIf="areNeuralNetsLoaded" (click)="getCameraStream()">Get access</button>
<button *ngIf="areNeuralNetsLoaded" (click)="stopCameraStream()">Stop stream</button>
<button *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()">{{ isDetecting ? 'Stop detection' : 'Detect and draw' }}</button>}
<video id="playback-video" width="{{ width }}" height="{{ height }}" #videoElement autoPlay></video>
</div>

<img [src]="temp" *ngIf="temp" #temp class="test-img" width="100px" height="100px" alt="">

<div class="action-buttons">
<!-- <button *ngIf="areNeuralNetsLoaded" (click)="stopCameraStream()">Stop stream</button> -->
<!-- <button *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()">{{ isDetecting ? 'Stop detection' : 'Detect and draw' }}</button> -->

<button class="camera-button" (click)="capture()"> <ion-icon name="camera"></ion-icon> </button>

<button class="skin-button" *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()"
[ngClass]="{'active' : isDetecting }"> <ion-icon name="glasses"></ion-icon> </button>
</div>
</ion-content>

+ 66
- 5
src/app/ar-fan-cam/ar-fan-cam.page.scss Näytä tiedosto

@@ -1,5 +1,32 @@
@import '../colors';

.test-img {
position: fixed;
z-index: 1;
left: 50%;
top: 50%;
}

.back-button {
position: fixed;
top: 10px;
right: 10px;
width: 40px;
height: 40px;
background: rgba(white, 0.5);
border: 0px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 3;

ion-icon {
color: white;
font-size: 20px;
}
}

.container {
position: relative;
}
@@ -13,11 +40,6 @@

#playback-video, #result-canvas, #three-container {
display: block;
width: 100vw;
height: 75vw;

max-width: 600px;
max-height: 450px;
}

#result-canvas, #three-container {
@@ -39,4 +61,43 @@

.right-eye {
background-color: red;
}


.action-buttons {
position: fixed;
left: 0;
bottom: 20px;
display: flex;
align-items: center;
width: 100%;

button {
width: 50px;
height: 50px;
background-color: white;
color: $pink;
border-radius: 50%;

ion-icon {
font-size: 25px;
}

&.camera-button {
margin-left: calc(50% - 25px);
transform: scale(1.5);
}

&.skin-button {
transform: scale(1.2);
margin-left: 40px;
background-color: transparent;
border: 2px solid $pink;

&.active {
background-color: $pink;
color: white;
}
}
}
}

+ 46
- 9
src/app/ar-fan-cam/ar-fan-cam.page.ts Näytä tiedosto

@@ -1,5 +1,7 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { detectSingleFace, loadFaceExpressionModel, loadFaceLandmarkModel, loadFaceLandmarkTinyModel, loadFaceRecognitionModel, loadSsdMobilenetv1Model, loadTinyFaceDetectorModel, TinyFaceDetectorOptions } from 'face-api.js';
import domtoimage from 'dom-to-image';
import { Location } from '@angular/common';

@Component({
selector: 'app-ar-fan-cam',
@@ -8,6 +10,7 @@ import { detectSingleFace, loadFaceExpressionModel, loadFaceLandmarkModel, loadF
})
export class ArFanCamPage implements OnInit {
@ViewChild('videoElement', null) videoElement: ElementRef<HTMLVideoElement>;
mediaStream: MediaStream|null = null;

glassProperties: {
@@ -22,7 +25,14 @@ export class ArFanCamPage implements OnInit {
width = 360;
height = 270;

constructor() { }
temp: any;


stream: any;

constructor(
private location: Location
) { }

loadNeuralNetModels = async () => {
await loadTinyFaceDetectorModel('/assets/weights');
@@ -37,25 +47,47 @@ export class ArFanCamPage implements OnInit {
this.areNeuralNetsLoaded = true;
}

back() {
this.location.back();
this.stopCameraStream();
}

getCameraStream = async () => {
const stream = await window.navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'user',
width: this.width,
height: this.height
},
});
this.mediaStream = stream;
this.videoElement.nativeElement.srcObject = stream;
}).then((stream) => {
this.mediaStream = stream;
this.videoElement.nativeElement.srcObject = stream;
}).catch(err => alert(JSON.stringify(err)));
};

stopCameraStream = async () => {
if (this.mediaStream) {
this.mediaStream.getVideoTracks().forEach(track => track.stop());
this.mediaStream.getVideoTracks().forEach(track => {
track.stop();
});
this.mediaStream = null;
this.stream = null;
}
}

async capture() {
let element: HTMLElement = document.querySelector('#container');

await domtoimage.toPng(element).then((dataUrl) => {
this.temp = dataUrl;
console.log(dataUrl);
})
.catch((error) => {
console.error('oops, something went wrong!', error);
});
}

detectAndDrawFace = async () => {
const tinyFaceDetectorOptions = new TinyFaceDetectorOptions();

@@ -87,14 +119,19 @@ export class ArFanCamPage implements OnInit {
}
}

ngOnInit() {
ngOnInit() {
}

ngAfterViewInit() {
this.loadNeuralNetModels();

const feedWidth = window.innerWidth > 600 ? 600 : window.innerWidth;
const feedHeight = feedWidth * 0.75;
const feedWidth = window.innerWidth;
const feedHeight = window.innerHeight;

this.width = feedWidth;
this.height = feedHeight;

this.getCameraStream().then(() => this.detectAndDrawFace(), (err) => console.log(err));
}

}

+ 10
- 1
src/app/fan-zone/fan-zone.page.ts Näytä tiedosto

@@ -87,7 +87,13 @@ export class FanZonePage implements OnInit {
}
ngAfterViewInit() {
this.showSocialLogin = true;
if (localStorage.googleUserData) {
this.googleUserData = JSON.parse(localStorage.googleUserData);
this.showSocialLogin = false;
} else {
this.googleUserData = {};
this.showSocialLogin = true;
}
}

generateEmojiStream() {
@@ -153,6 +159,9 @@ export class FanZonePage implements OnInit {
profileImage: data.user.photoURL,
credentials: data.credential
};

localStorage.googleUserData = JSON.stringify(this.googleUserData);

this.showSocialLogin = false;
}).catch(err => {
alert(err.message);


Ladataan…
Peruuta
Tallenna