Skip to content

Commit

Permalink
add body segmentation (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuinnHe authored Mar 28, 2024
1 parent a396d8d commit 9a822a2
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 106 deletions.
167 changes: 167 additions & 0 deletions docs/reference/body-segmentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Body Segmentation

<center>
<img style="display:block; max-height:20rem" alt="BodyPix Header Image of Harriet Tubman" src="_media/reference__header-bodypix.png">
</center>

## Description

BodySegmentation divides an image input into the people and the background, and then further divide the people into different body parts. The model can detect multiple people at once and for each person, provides 24 body parts that describe important locations on the body.

#### Key Features

* Real-time person segmentation
* Real-time body part segmentation

#### Output Example
Based on your options, the output can be a mask of the background, a mask of the person, or a mask of the body parts. Regardless of the scenario, the segmentation information deemed valuable is consistently stored within the mask property of the resulting object.

```javascript
result.mask;
```

## Getting Started
Integrating Body Segmentation into your ml5.js projects is straightforward. Our documentation and user-friendly API will help you make the most of this combined model!

### Demo

[p5 Web Editor](iframes/body-segmentation ':include :type=iframe width=100% height=550px')

### Quickstart
Before you start, let's create an empty project in the [p5 web editor](https://editor.p5js.org/).

First of all, copy and paste the following code into your **index.html** file. If you are not familiar with the p5 web editor interface, you can find a guide on how to find your **index.html** file [here](/?id=try-ml5js-online-1).

```html
<script src="https://unpkg.com/ml5@alpha/dist/ml5.js"></script>
```

Then, add the code below to your **sketch.js** file:

```js
let bodyPix;
let video;
let segmentation;

let options = {
maskType: "parts",
};

function preload() {
bodyPix = ml5.bodySegmentation("BodyPix", options);
}

function setup() {
createCanvas(640, 480);
// Create the video
video = createCapture(VIDEO);
video.size(width, height);
video.hide();

bodyPix.detectStart(video, gotResults);
}

function draw() {
background(255);
image(video, 0, 0);
if (segmentation) {
image(segmentation, 0, 0, width, height);
}
}
// callback function for body segmentation
function gotResults(result) {
segmentation = result.mask;
}
```
Alternatively, you can open [this example code](https://github.com/ml5js/ml5-next-gen/tree/main/examples/BodySegmentation-maskbodyparts) and try it yourself on p5.js web editor!

### Additional Examples
* [BodySegmentation-maskbackground](https://github.com/ml5js/ml5-next-gen/tree/main/examples/BodySegmentation-maskbackground)
* [BodySegmentation-maskperson](https://github.com/ml5js/ml5-next-gen/tree/main/examples/BodySegmentation-maskperson)

<!-- ### Tutorials
**PoseNet on The Coding Train**
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/OIo-DIOkNVg" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> -->

## Methods

#### ml5.bodySegmentation()

This method is used to initialize the bodySegmentation object.

```javascript
const bodySegmentation = ml5.bodySegmentation(?modelName, ?options, ?callback);
```
**Parameters:**
- **modelName**: OPTIONAL: A string specifying which model to use, "SelfieSegmentation" or "BodyPix".
- **options**: OPTIONAL. An object to change the default configuration of the model. See the example options object:
```javascript
{
runtime: "mediapipe", // "mediapipe" or "tfjs"
modelType: "general", // "general" or "landscape"
maskType: :"background", //"background", "body", or "parts" (used to change the type of segmentation mask output)
}
```
[More info on options for SelfieSegmentation model with mediaPipe runtime](https://github.com/tensorflow/tfjs-models/tree/master/body-segmentation/src/selfie_segmentation_mediapipe#create-a-detector).
[More info on options for SelfieSegmentation model with tfjs runtime](https://github.com/tensorflow/tfjs-models/tree/master/body-segmentation/src/selfie_segmentation_tfjs#create-a-detector).
[More infor on options for BodyPix model.](https://github.com/tensorflow/tfjs-models/blob/master/body-segmentation/src/body_pix/README.md#create-a-detector)
- **callback(bodySegmentation, error)**: OPTIONAL. A function to run once the model has been loaded. Alternatively, call `ml5.bodySegmentation()` within the p5 `preload` function.
**Returns:**
The bodySegmentation object.
#### bodySegmentation.detectStart()
This method repeatedly outputs segmentation masks on an image media through a callback function.
```javascript
bodySegmentation.detectStart(media, callback);
```
**Parameters:**
- **media**: An HTML or p5.js image, video, or canvas element to run the segmentation on.
- **callback(output, error)**: A function to handle the output of `bodySegmentation.detectStart()`. Likely a function to do something with the segmented image. See below for the output passed into the callback function:
```javascript
{
mask: {},//A p5 Image object, can be directly passed into p5 image() function
maskImageData: {}//A ImageData object
}
```
#### bodySegmentation.detectStop()
This method can be called after a call to `bodySegmentation.detectStart` to stop the repeating pose estimation.
```javascript
bodySegmentation.detectStop();
```
#### bodySegmentation.detect()
This method asynchronously outputs a single segmentation mask on an image media when called.
```javascript
bodySegmentation.detect(media, ?callback);
```
**Parameters:**
- **media**: An HTML or p5.js image, video, or canvas element to run the segmentation on.
- **callback(output, error)**: OPTIONAL. A callback function to handle the output of the estimation, see output example above.
**Returns:**
A promise that resolves to the segmentation output.
(footer needed)
99 changes: 0 additions & 99 deletions docs/reference/bodypix.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/reference/bodypose.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ let poses = [];

function preload() {
// Load the bodyPose model, default is MoveNet model
bodyPose = ml5.bodypose();
bodyPose = ml5.bodyPose();
}

function setup() {
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/facemesh.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ let options = { maxFaces: 1, refineLandmarks: false, flipHorizontal: false };

function preload() {
// Load the faceMesh model
faceMesh = ml5.facemesh(options);
faceMesh = ml5.faceMesh(options);
}

function setup() {
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/handpose.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ let hands = [];

function preload() {
// Load the handpose model
handpose = ml5.handpose();
handpose = ml5.handPose();
}

function setup() {
Expand Down
22 changes: 22 additions & 0 deletions docs/reference/iframes/body-segmentation/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5.js iframe</title>
<link rel="stylesheet" href="../style.css">
</head>

<body>
<div class="content-container">
<h1>Body Segmentation Model</h1>
<p>(Add description.) Ensure to enable the webcam.</p>
<button>
<a href="main.html">Start!</a>
</button>
</div>
</body>

</html>
24 changes: 24 additions & 0 deletions docs/reference/iframes/body-segmentation/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">

<head>
<script src="https://unpkg.com/ml5@alpha/dist/ml5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.9/dat.gui.min.js"></script>
<link rel="stylesheet" type="text/css" href="../style.css">
<meta charset="utf-8" />
</head>

<body>
<main>
</main>
<div class="content-container">
<button>
<a href="index.html">Stop</a>
</button>
</div>
<script src="script.js"></script>
</body>

</html>
38 changes: 38 additions & 0 deletions docs/reference/iframes/body-segmentation/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2020-2023 ml5
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

let bodyPix;
let video;
let segmentation;

let options = {
maskType: "parts",
};

function preload() {
bodyPix = ml5.bodySegmentation("BodyPix", options);
}

function setup() {
createCanvas(640, 480);
// Create the video
video = createCapture(VIDEO);
video.size(width, height);
video.hide();

bodyPix.detectStart(video, gotResults);
}

function draw() {
background(255);
image(video, 0, 0);
if (segmentation) {
image(segmentation, 0, 0, width, height);
}
}
// callback function for body segmentation
function gotResults(result) {
segmentation = result.mask;
}
2 changes: 1 addition & 1 deletion docs/reference/iframes/facemesh-keypoints/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ let options = { maxFaces: 1, refineLandmarks: false, flipHorizontal: false };

function preload() {
// Load the faceMesh model
faceMesh = ml5.facemesh(options);
faceMesh = ml5.faceMesh(options);
}

function setup() {
Expand Down
Loading

0 comments on commit 9a822a2

Please sign in to comment.