Graduate

Update Opencv.js face detection

1 +function Utils(errorOutputId) { // eslint-disable-line no-unused-vars
2 + let self = this;
3 + this.errorOutput = document.getElementById(errorOutputId);
4 +
5 + const OPENCV_URL = 'opencv.js';
6 + this.loadOpenCv = function(onloadCallback) {
7 + let script = document.createElement('script');
8 + script.setAttribute('async', '');
9 + script.setAttribute('type', 'text/javascript');
10 + script.addEventListener('load', () => {
11 + if (cv.getBuildInformation)
12 + {
13 + console.log(cv.getBuildInformation());
14 + onloadCallback();
15 + }
16 + else
17 + {
18 + // WASM
19 + cv['onRuntimeInitialized']=()=>{
20 + console.log(cv.getBuildInformation());
21 + onloadCallback();
22 + }
23 + }
24 + });
25 + script.addEventListener('error', () => {
26 + self.printError('Failed to load ' + OPENCV_URL);
27 + });
28 + script.src = OPENCV_URL;
29 + let node = document.getElementsByTagName('script')[0];
30 + node.parentNode.insertBefore(script, node);
31 + };
32 +
33 + this.createFileFromUrl = function(path, url, callback) {
34 + let request = new XMLHttpRequest();
35 + request.open('GET', url, true);
36 + request.responseType = 'arraybuffer';
37 + request.onload = function(ev) {
38 + if (request.readyState === 4) {
39 + if (request.status === 200) {
40 + let data = new Uint8Array(request.response);
41 + cv.FS_createDataFile('/', path, data, true, false, false);
42 + callback();
43 + } else {
44 + self.printError('Failed to load ' + url + ' status: ' + request.status);
45 + }
46 + }
47 + };
48 + request.send();
49 + };
50 +
51 + this.loadImageToCanvas = function(url, cavansId) {
52 + let canvas = document.getElementById(cavansId);
53 + let ctx = canvas.getContext('2d');
54 + let img = new Image();
55 + img.crossOrigin = 'anonymous';
56 + img.onload = function() {
57 + canvas.width = img.width;
58 + canvas.height = img.height;
59 + ctx.drawImage(img, 0, 0, img.width, img.height);
60 + };
61 + img.src = url;
62 + };
63 +
64 + this.executeCode = function(textAreaId) {
65 + try {
66 + this.clearError();
67 + let code = document.getElementById(textAreaId).value;
68 + eval(code);
69 + } catch (err) {
70 + this.printError(err);
71 + }
72 + };
73 +
74 + this.clearError = function() {
75 + this.errorOutput.innerHTML = '';
76 + };
77 +
78 + this.printError = function(err) {
79 + if (typeof err === 'undefined') {
80 + err = '';
81 + } else if (typeof err === 'number') {
82 + if (!isNaN(err)) {
83 + if (typeof cv !== 'undefined') {
84 + err = 'Exception: ' + cv.exceptionFromPtr(err).msg;
85 + }
86 + }
87 + } else if (typeof err === 'string') {
88 + let ptr = Number(err.split(' ')[0]);
89 + if (!isNaN(ptr)) {
90 + if (typeof cv !== 'undefined') {
91 + err = 'Exception: ' + cv.exceptionFromPtr(ptr).msg;
92 + }
93 + }
94 + } else if (err instanceof Error) {
95 + err = err.stack.replace(/\n/g, '<br>');
96 + }
97 + this.errorOutput.innerHTML = err;
98 + };
99 +
100 + this.loadCode = function(scriptId, textAreaId) {
101 + let scriptNode = document.getElementById(scriptId);
102 + let textArea = document.getElementById(textAreaId);
103 + if (scriptNode.type !== 'text/code-snippet') {
104 + throw Error('Unknown code snippet type');
105 + }
106 + textArea.value = scriptNode.text.replace(/^\n/, '');
107 + };
108 +
109 + this.addFileInputHandler = function(fileInputId, canvasId) {
110 + let inputElement = document.getElementById(fileInputId);
111 + inputElement.addEventListener('change', (e) => {
112 + let files = e.target.files;
113 + if (files.length > 0) {
114 + let imgUrl = URL.createObjectURL(files[0]);
115 + self.loadImageToCanvas(imgUrl, canvasId);
116 + }
117 + }, false);
118 + };
119 +
120 + function onVideoCanPlay() {
121 + if (self.onCameraStartedCallback) {
122 + self.onCameraStartedCallback(self.stream, self.video);
123 + }
124 + };
125 +
126 + this.startCamera = function(resolution, callback, videoId) {
127 + const constraints = {
128 + 'qvga': {width: {exact: 320}, height: {exact: 240}},
129 + 'vga': {width: {exact: 640}, height: {exact: 480}}};
130 + let video = document.getElementById(videoId);
131 + if (!video) {
132 + video = document.createElement('video');
133 + }
134 +
135 + let videoConstraint = constraints[resolution];
136 + if (!videoConstraint) {
137 + videoConstraint = true;
138 + }
139 +
140 + navigator.mediaDevices.getUserMedia({video: videoConstraint, audio: false})
141 + .then(function(stream) {
142 + video.srcObject = stream;
143 + video.play();
144 + self.video = video;
145 + self.stream = stream;
146 + self.onCameraStartedCallback = callback;
147 + video.addEventListener('canplay', onVideoCanPlay, false);
148 + })
149 + .catch(function(err) {
150 + self.printError('Camera Error: ' + err.name + ' ' + err.message);
151 + });
152 + };
153 +
154 + this.stopCamera = function() {
155 + if (this.video) {
156 + this.video.pause();
157 + this.video.srcObject = null;
158 + this.video.removeEventListener('canplay', onVideoCanPlay);
159 + }
160 + if (this.stream) {
161 + this.stream.getVideoTracks()[0].stop();
162 + }
163 + };
164 +};
...\ No newline at end of file ...\ No newline at end of file
...@@ -8,31 +8,29 @@ ...@@ -8,31 +8,29 @@
8 #container { 8 #container {
9 margin: 0px auto; 9 margin: 0px auto;
10 width: 640px; 10 width: 640px;
11 - height: 480px; 11 + height: 960px;
12 border: 10px #333 solid; 12 border: 10px #333 solid;
13 } 13 }
14 -#videoElement { 14 +#videoInput {
15 + width: 640px;
16 + height: 480px;
17 + background-color: #666;
18 +}
19 +#canvasOutput {
15 width: 640px; 20 width: 640px;
16 height: 480px; 21 height: 480px;
17 background-color: #666; 22 background-color: #666;
18 } 23 }
19 -
20 -
21 </style> 24 </style>
22 -</head>
23 -
24 -<body>
25 -<div id="container">
26 - <video autoplay="true" id="videoElement"> <!-- style="visibility: hidden"-->
27 -
28 - </video>
29 - <canvas id='canvasOutput' width='640' height='480'>
30 -
31 - </canvas>
32 -</div>
33 <script type='text/javascript' src="{{url_for('static', filename='js/opencv.js')}}"></script> 25 <script type='text/javascript' src="{{url_for('static', filename='js/opencv.js')}}"></script>
26 +<script type='text/javascript' src="{{url_for('static', filename='js/utils.js')}}"></script>
34 <script type='text/javascript'> 27 <script type='text/javascript'>
35 -var video = document.querySelector("#videoElement"); 28 +function main()
29 +{
30 +let video = document.getElementById("videoInput");
31 +let canvasOutput = document.getElementById('canvasOutput');
32 +let canvasContext = canvasOutput.getContext('2d');
33 +
36 if (navigator.mediaDevices.getUserMedia){ 34 if (navigator.mediaDevices.getUserMedia){
37 navigator.mediaDevices.getUserMedia({ video: true }) 35 navigator.mediaDevices.getUserMedia({ video: true })
38 .then(function (stream) { 36 .then(function (stream) {
...@@ -41,24 +39,22 @@ if (navigator.mediaDevices.getUserMedia){ ...@@ -41,24 +39,22 @@ if (navigator.mediaDevices.getUserMedia){
41 console.log("Something went wrong!"); 39 console.log("Something went wrong!");
42 }); 40 });
43 } 41 }
44 -</script> 42 +let src = new cv.Mat(video.height, video.width, cv.CV_8UC4);
45 -<script> 43 +let dst = new cv.Mat(video.height, video.width, cv.CV_8UC4);
46 -cv['onRuntimeInitialized']=()=>{ 44 +let gray = new cv.Mat();
47 - let video = document.getElementById('videoElement'); 45 +let cap = new cv.VideoCapture(video);
48 - let src = new cv.Mat(video.height, video.width, cv.CV_8UC4); 46 +let faces = new cv.RectVector();
49 - let dst = new cv.Mat(video.height, video.width, cv.CV_8UC4); 47 +let classifier = new cv.CascadeClassifier();
50 - let gray = new cv.Mat(); 48 +var streaming = true;
51 - let cap = new cv.VideoCapture(video); 49 +
52 - let faces = new cv.RectVector(); 50 +let utils = new Utils('errorMessage'); //use utils class
53 - let classifier = new cv.CascadeClassifier(); 51 +let faceCascadeFile = "/static/js/haarcascade_frontalface_default.xml"
54 - var streaming = true; 52 +utils.createFileFromUrl(faceCascadeFile, faceCascadeFile, () => {
55 - if (typeof streaming === 'undefined') 53 + alert(faceCascadeFile);
56 - { 54 + classifier.load(faceCascadeFile);
57 - streaming = false; 55 +});
58 - } 56 +const FPS = 30;
59 - classifier.load("{{url_for('static', filename='js/haarcascade_frontalface_default.xml')}}") 57 +function processVideo() {
60 - const FPS = 30;
61 - function processVideo() {
62 try { 58 try {
63 if (!streaming) { 59 if (!streaming) {
64 // clean and stop. 60 // clean and stop.
...@@ -74,8 +70,10 @@ cv['onRuntimeInitialized']=()=>{ ...@@ -74,8 +70,10 @@ cv['onRuntimeInitialized']=()=>{
74 cap.read(src); 70 cap.read(src);
75 src.copyTo(dst); 71 src.copyTo(dst);
76 cv.cvtColor(dst, gray, cv.COLOR_RGBA2GRAY, 0); 72 cv.cvtColor(dst, gray, cv.COLOR_RGBA2GRAY, 0);
73 + alert('d');
77 // detect faces. 74 // detect faces.
78 classifier.detectMultiScale(gray, faces, 1.1, 3, 0); 75 classifier.detectMultiScale(gray, faces, 1.1, 3, 0);
76 + alert('e');
79 // draw faces. 77 // draw faces.
80 for (let i = 0; i < faces.size(); ++i) { 78 for (let i = 0; i < faces.size(); ++i) {
81 let face = faces.get(i); 79 let face = faces.get(i);
...@@ -83,6 +81,7 @@ cv['onRuntimeInitialized']=()=>{ ...@@ -83,6 +81,7 @@ cv['onRuntimeInitialized']=()=>{
83 let point2 = new cv.Point(face.x + face.width, face.y + face.height); 81 let point2 = new cv.Point(face.x + face.width, face.y + face.height);
84 cv.rectangle(dst, point1, point2, [255, 0, 0, 255]); 82 cv.rectangle(dst, point1, point2, [255, 0, 0, 255]);
85 } 83 }
84 + alert('f');
86 cv.imshow('canvasOutput', dst); 85 cv.imshow('canvasOutput', dst);
87 // schedule the next one. 86 // schedule the next one.
88 let delay = 1000/FPS - (Date.now() - begin); 87 let delay = 1000/FPS - (Date.now() - begin);
...@@ -90,10 +89,19 @@ cv['onRuntimeInitialized']=()=>{ ...@@ -90,10 +89,19 @@ cv['onRuntimeInitialized']=()=>{
90 } catch (err) { 89 } catch (err) {
91 console.log(err); 90 console.log(err);
92 } 91 }
93 - } 92 +}
94 - // schedule the first one. 93 +setTimeout(processVideo, 0);
95 - setTimeout(processVideo, 0);
96 } 94 }
97 </script> 95 </script>
96 +</head>
97 +<body onload="cv['onRuntimeInitialized']=()=>{ main() }">
98 +<div id="container">
99 +<video autoplay="true" id="videoInput" width=640 height=480> <!-- style="visibility: hidden"-->
100 +
101 +</video>
102 +<canvas id='canvasOutput' width=640 height=480>
103 +
104 +</canvas>
105 +</div>
98 </body> 106 </body>
99 </html> 107 </html>
......