iT邦幫忙

0

N01_使用 p5.js 和 ml5.js 的BodyPix來實現人形去背與物件碰撞的體感互動

  • 分享至 

  • xImage
  •  

使用 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


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言