使用 p5.js 和 ml5.js 的BodyPix
来实现人形去背与物件碰撞的体感互动
今天来尝试透过与Microsoft Bing的对话来产生体感互动的程式。
过程中遇到有些程式码的功能本身是不存在的,Bing AI会当作假设有这个功能属性的状况,接下去的程式流程,所以还需要去找出真正有这个功能的套件。
基本上,透过与Microsoft Bing的对话,可以帮助到初步整体框架的程式流程,接下来的细部流程或是功能的调整,以及另外的套件的引入,仍是需要自身进行编写的。
以下是经过修正调整后,确定可以执行的程式码。
使用p5.js和ml5.js的BodyPix来实现人形分割与物件碰撞的体感互动
将分割后的人形接着进行轮廓路径的侦测,以此轮廓做为画面中物件掉落的碰撞互动。
使用ml5.js的BodyPix模型的segmentation
结果中的personMask
属性来获取人体的遮罩。接着使用物件位置处的人形遮罩的颜色来检测是否产生碰撞,作为实现物件与人体轮廓的碰撞互动。
以下是一个完整的HTML文件,包括引入p5.js和ml5.js。
<!DOCTYPE html><html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.min.js"></script> <script src="https://unpkg.com/ml5@latest/dist/ml5.min.js" type="text/javascript"></script> <script src="https://unpkg.com/p5.collide2d@0.7.3/p5.collide2d.js"></script> </head> <body> <script>let bodypix;let video;let segmentation;let particles = [];let pg;let st = 0;let imgData = [];let can;function setup() { can = createCanvas(320, 240); // 加载摄像头视频 video = createCapture(VIDEO); video.size(width, height); video.hide(); // 加载BodyPix模型 bodypix = ml5.bodyPix(video, modelReady); pg = createGraphics(width, height); textSize(32);}function modelReady() { console.log('Model Ready!'); bodypix.segment(gotResults);}function gotResults(err, result) { if (err) { console.log(err); return; } segmentation = result; // 继续进行分割 bodypix.segment(gotResults);}function draw() { background(0); if (segmentation) { //image(segmentation.backgroundMask, 0, 0, width, height); image(segmentation.personMask, 0, 0, width, height); // 绘制人体轮廓 pg.background(0); pg.image(segmentation.personMask, 0, 0, width, height); //pg.image(segmentation.backgroundMask, 0, 0, width, height); // 更新物件位置 for (let i = particles.length - 1; i >= 0; i--) { let p = particles[i]; p.update(); p.display(); // 检测物件与人体轮廓之间的碰撞 const ctx = pg.elt.getContext("2d"); ctx.getContextAttributes().willReadFrequently = true; let imageData = ctx.getImageData(p.x, p.y, 1, 1).data; let br = (imageData[0]+imageData[1]+imageData[2])/3; if(br<1 && p.y>10){ p.collide(); } // 移除超出画面的物件 if (p.y > height + p.r || p.y < -30 || p.x > width + p.r || p.x < -p.r) { particles.splice(i, 1); } } // 随机生成新物件 if (random(5) < 2) { particles.push(new Particle(random(width), -20)); } } fill(10, 10, 0); text(particles.length, 15, 30);}class Particle { constructor(x, y) { this.x = x; this.y = y; this.r = random(5, 15); this.speedx = random(-5, 5); this.speedy = random(5, 10); this.color = color(random(255), random(255), random(255)); this.st = 0; } update() { this.y += this.speedy; this.x += this.speedx; } display() { fill(this.color); noStroke(); ellipse(this.x, this.y, this.r * 2); } collide() { if(this.st==0){ this.st = 1; this.speedx *= -0.5; this.speedy *= -0.5; this.y += this.speedy; this.x += this.speedx; } }} </script> </body></html>
参考来源:
1.Microsoft Bing的聊天对谈
2.p5.collide2D
3.bodypix
4.HTML canvas getImageData() Method
5.bodypix demo