p5.js-web-editor/dist/static/assets/webcam.js

331 lines
8.4 KiB
JavaScript
Raw Normal View History

2020-09-07 14:31:01 +02:00
console.log('p5 version:', p5);
console.log('ml5 version:', ml5);
2020-09-21 12:22:19 +02:00
console.log(location.origin);
2020-09-07 14:31:01 +02:00
let assets = {};
var draw = function () {
};
2020-09-21 12:22:19 +02:00
// var gotResults = function(err, result) {
// if (err) {
// console.log(err)
// return
// }
// };
// function code_error(type, error) {
// window.parent.postMessage({
// 'type': type,
// 'error': error.message,
// 'name': error.name,
// 'line': error.lineNumber - 2, // seems it giveswrong line numbers
// 'column': error.columnNumber
// }, '*');
// }
// function no_code_error(type){
// window.parent.postMessage({
// 'type': type,
// 'error': null
// }, '*');
// }
// window.addEventListener("message", function (e) {
// if (event.origin !== window.location.origin) {
// console.error("Invalid origin of message. Ignored");
// return;
// }
// console.debug("receive", e.data);
2020-09-07 14:31:01 +02:00
2020-09-21 12:22:19 +02:00
// switch (e.data.action) {
// case 'asset':
// if(e.data.content === null){
// delete assets[e.data.id];
// } else {
// assets[e.data.id] = loadImage(e.data.content);
// }
2020-09-07 14:31:01 +02:00
2020-09-21 12:22:19 +02:00
// break;
// case 'code':
// let f = new Function("");
// try {
// f = new Function(e.data.draw);
// no_code_error('syntax');
// } catch (error) {
// code_error('syntax', error);
// // window.parent.postMessage({'syntax': error.lineNumber});
// }
// handleResults = f;
// break;
2020-09-07 14:31:01 +02:00
2020-09-21 12:22:19 +02:00
// default:
// console.error("Invalid action", e.data.action);
// break;
// }
2020-09-07 14:31:01 +02:00
2020-09-21 12:22:19 +02:00
// });
2020-09-07 14:31:01 +02:00
let faceapi;
var video;
2020-09-21 12:22:19 +02:00
var lastFrame;
var detections = [];
2020-09-22 08:26:54 +02:00
var factor_x, factor_y;
2020-09-07 14:31:01 +02:00
2020-09-21 12:22:19 +02:00
// function pause() {
// if (running)
// running = false;
// else {
// running = true;
// faceapi.detect(gotResults);
// }
// }
2020-09-07 14:31:01 +02:00
// by default all options are set to true
const detection_options = {
withLandmarks: true,
withDescriptors: false,
minConfidence: 0.5,
2020-09-21 12:22:19 +02:00
Mobilenetv1Model: window.parent.location.origin + '/assets/faceapi',
FaceLandmarkModel: window.parent.location.origin + '/assets/faceapi',
FaceLandmark68TinyNet: window.parent.location.origin + '/assets/faceapi',
FaceRecognitionModel: window.parent.location.origin + '/assets/faceapi',
TinyFaceDetectorModel: window.parent.location.origin + '/assets/faceapi',
2020-09-07 14:31:01 +02:00
}
2020-09-21 12:22:19 +02:00
2020-09-07 14:31:01 +02:00
function setup() {
2020-09-21 12:22:19 +02:00
// createCanvas(1280,720, WEBGL);
2020-09-22 08:26:54 +02:00
createCanvas(540,420);
2020-09-07 14:31:01 +02:00
smooth();
noFill();
2020-09-21 12:22:19 +02:00
push();
translate(-width/2, -height/2);
2020-09-07 14:31:01 +02:00
let constraints = {
video: {
width: { min: 720 },
height: { min: 540 }
},
audio: false
};
video = createCapture(constraints);
2020-09-21 12:22:19 +02:00
lastFrame = createGraphics(video.width, video.height);
2020-09-07 14:31:01 +02:00
console.log(video);
// HeadGazeSetup(video);
// video.size(width, height);
video.hide(); // Hide the video element, and just show the canvas
faceapi = ml5.faceApi(video, detection_options, modelReady);
textAlign(RIGHT);
}
function modelReady() {
faceapi.detect(gotResults);
}
var handleResults = function(){
// background(parseInt(Math.random()*255),parseInt(Math.random()*255),parseInt(Math.random()*255));
background((millis()/100)%255,0,0);
image(video, -width/2 + 10, -height/2 + 10, width - 20, height -20);
};
2020-09-21 12:22:19 +02:00
2020-09-07 14:31:01 +02:00
gotResults = function(err, result) {
if (err) {
console.log(err)
return
}
2020-09-21 12:22:19 +02:00
// store data for async draw function
2020-09-22 08:26:54 +02:00
// TODO results to more compatible format
detections = parseDetectionResults(result);
2020-09-21 14:57:54 +02:00
// size of video becomes known only after camera approval
if(lastFrame.width != video.width || lastFrame.height != video.height){
console.log('Resizing canvas');
lastFrame.resizeCanvas(video.width, video.height);
}
// lastFrame.background('red');
2020-09-21 12:22:19 +02:00
lastFrame.image(video, 0,0, video.width, video.height);
2020-09-07 14:31:01 +02:00
2020-09-22 08:26:54 +02:00
factor_x = width / video.width;
factor_y = height / video.height;
2020-09-21 12:22:19 +02:00
faceapi.detect(gotResults);
2020-09-07 14:31:01 +02:00
}
function drawBox(detections) {
for (let i = 0; i < detections.length; i++) {
const alignedRect = detections[i].alignedRect;
const x = alignedRect._box._x
const y = alignedRect._box._y
const boxWidth = alignedRect._box._width
const boxHeight = alignedRect._box._height
noFill();
stroke(161, 95, 251);
strokeWeight(2);
rect(x, y, boxWidth, boxHeight);
}
}
2020-09-21 14:57:54 +02:00
function drawLandmarks(detection) {
// for (let i = 0; i < detections.length; i++) {
const mouth = detection.parts.mouth;
const nose = detection.parts.nose;
const leftEye = detection.parts.leftEye;
const rightEye = detection.parts.rightEye;
const rightEyeBrow = detection.parts.rightEyeBrow;
const leftEyeBrow = detection.parts.leftEyeBrow;
const jawOutline = detection.parts.jawOutline;
drawPart(mouth, true);
drawPart(nose, true);
drawPart(leftEye, true);
drawPart(leftEyeBrow, false);
drawPart(rightEye, true);
drawPart(rightEyeBrow, false);
drawPart(jawOutline, false);
// }
2020-09-07 14:31:01 +02:00
}
function drawPart(feature, closed) {
beginShape();
2020-09-21 14:57:54 +02:00
2020-09-07 14:31:01 +02:00
for (let i = 0; i < feature.length; i++) {
2020-09-22 08:26:54 +02:00
const x = feature[i].x;
const y = feature[i].y;
2020-09-07 14:31:01 +02:00
vertex(x, y)
}
if (closed === true) {
endShape(CLOSE);
} else {
endShape();
}
2020-09-21 14:57:54 +02:00
}
2020-09-22 09:11:45 +02:00
// /**
// * Wrapper around p5.js color class
// * @param {*} c color, either as array, or string (css name or HEX string)
// */
// function getColor(c) {
// if(!Array.isArray(c)) c = [c];
// return new p5.Color(p5.instance, c);
// }
2020-09-21 14:57:54 +02:00
2020-09-22 09:11:45 +02:00
// var colors = {
// red: getColor('red'),
// blue: getColor('blue'),
// green: getColor('green'),
// };
2020-09-21 14:57:54 +02:00
function faceDistance(face1, face2){
// distance between faces, in pixels, not meters.. for now
2020-09-22 08:26:54 +02:00
// we cheat a little: take centers, visualise circle with r = max(width, height)
// and find distance between these circles
box1 = (face1.box.x, face1.box.x + face1.box.width)
box2 = (face2.box.x, face2.box.x + face2.box.width)
c1 = {
x: face1.box.x + face1.box.width / 2,
y: face1.box.y + face1.box.height / 2,
}
c2 = {
x: face2.box.x + face2.box.width / 2,
y: face2.box.y + face2.box.height / 2,
}
2020-09-21 14:57:54 +02:00
2020-09-22 08:26:54 +02:00
r1 = Math.max(face1.box.width, face1.box.height) / 2;
r2 = Math.max(face2.box.width, face2.box.height) / 2;
dx = c1.x - c2.x;
dy = c1.y - c2.y;
return Math.sqrt( Math.pow(dx, 2) + Math.pow(dy, 2) ) - r1 - r2;
2020-09-21 14:57:54 +02:00
}
2020-09-22 09:11:45 +02:00
function mergePoints() {
// a points should be {x: , y: }
// collect all points in the arguments:
let points = [];
for(let arg of arguments) {
if(Array.isArray(arg)) {
points.push(...arg);
} else {
points.push(arg);
}
}
return points;
}
2020-09-21 14:57:54 +02:00
function getBoundingBox(){
// arguments contains points, or sets of points. Find bbox
2020-09-22 09:11:45 +02:00
const points = mergePoints(...arguments);
const xs = points.map((point) => point.x);
const ys = points.map((point) => point.y);
const minx = Math.min(...xs);
const miny = Math.min(...ys);
return {
x: minx,
y: miny,
width: Math.max(...xs) - minx,
height: Math.max(...ys) - miny,
}
2020-09-22 08:26:54 +02:00
}
function parseDetectionResults(results) {
let detections = [];
for(let result of results) {
const landmarks = result.landmarks._positions.map((pos) => parseCoordinate(pos));
let detection = {
2020-09-22 09:20:45 +02:00
'points': landmarks,
2020-09-22 09:11:45 +02:00
// TODO: rotation
2020-09-22 08:26:54 +02:00
'parts': {},
'box': {
x: result.alignedRect._box._x * factor_x,
y: result.alignedRect._box._y * factor_y,
width: result.alignedRect._box._width * factor_x,
height: result.alignedRect._box._height * factor_y,
}
}
for(let idx in result.parts) {
detection.parts[idx] = result.parts[idx].map((pos) => parseCoordinate(pos));
}
detections.push(detection);
}
return detections;
}
/**
* face api detector returns coordinates with _x and _y attributes.
* We convert this to the canvas's coordinates
* @param Object {_x: , _y: }
*/
function parseCoordinate(position) {
return {
x: position._x * factor_x,
y: position._y * factor_y,
}
2020-09-07 14:31:01 +02:00
}