-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from nhtua/master
Init project
- Loading branch information
Showing
7 changed files
with
516 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# GreenCam | ||
|
||
## What is GreenCam? | ||
|
||
GreenCam is **a virtual green backdrop** for OBS Studio. Yep! you are not crazy. It basically replaces every things around you by green color. So that you can use the Chroma Key filter in OBS Studio to put yourself in any other video. GreenCam is powered by a machine learning technology called [Tensorflow](https://github.com/tensorflow/tfjs) and its public model [BodyPix](https://github.com/tensorflow/tfjs-models/tree/master/body-pix). | ||
|
||
I do a lot of live streaming at home. There is a small living room, a lot of messy stuffs that needs to hide, not much spaces (and budget) to setup a standard professional studio. I found there are some applications, like XSplit VCam or Chroma Cam, which removes/changes the background of your video, but I don't want to pay them since I can do exactly the same thing for FREE!! | ||
|
||
## How to use GreenCam with OBS Studio | ||
|
||
### Prerequisite | ||
I tested GreenCam with my OBS Studio 26. But you should able to run GreenCam in any version support Browser plugin. | ||
|
||
- OBS Studio with Browser plugin enabled | ||
- NodeJS Erbium (12 LTS) or later | ||
- A webcam | ||
|
||
### Follow steps below to setup: | ||
|
||
1. Download source code from [Github](https://github.com/nhtua/greencam). | ||
2. Run commands: | ||
``` | ||
$ cd /path/to/greencam | ||
$ npm install | ||
``` | ||
3. Edit your application shortcut. I'm using Linux, but Windows should be similar. The ideas is to add some options to the starting command which enables OBS loading a webpage with a WebCam. | ||
``` | ||
$ cd /usr/share/applications/ | ||
$ ls | grep obs | ||
# pick the name that you see here. For me, it's `com.obsproject.Studio.desktop` | ||
$ sudo vi com.obsproject.Studio.desktop | ||
# find the line `Exec=`, modify it into the line below | ||
Exec=obs --enable-gpu --enable-media-stream | ||
# press : and "x", then press Enter to escape Vi editor | ||
``` | ||
4. Open OBS studio, in a scene | ||
- click `+` button on the `source` panel | ||
- choose `Browser`. | ||
- Name it `GreenCam` then click `OK` | ||
5. In the next dialog | ||
- tick the box `Local file` | ||
- Pick the file `index.html` from GreenCam source code | ||
- input width=640, height=480 | ||
- leave everything else default | ||
- click `OK` at the end. | ||
6. Right click on your new `source` - `GreenCam` | ||
- Choose Filter | ||
- On the `Effect Filters` panel, click `+` | ||
- Choose `Chroma Key` | ||
- Key color type = `green` | ||
7. Close the dialog of filters. **Congrats!** You have your new webcam with background removed. | ||
|
||
## Development | ||
It is a hack I did in one night. But might be some errors, or incompatible problems will happens in your machine. Also, there are a lot of features that may be included in next version of GreenCam, like: | ||
- Custom parameters/algorithm to have smoother, better shapes | ||
- Custom background color, video | ||
- Add an editor that can run in browser to test customized parameters and generate a link to run in OBS | ||
|
||
All Pull Requests are welcome!! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
window.onload = (event) => { | ||
start() | ||
} | ||
|
||
function getVideo() { | ||
return document.getElementById("inputVideo"); | ||
} | ||
function getCanvasContext(id) { | ||
const canvas = document.getElementById(id); | ||
return canvas.getContext('2d'); | ||
} | ||
|
||
function start() { | ||
const video = getVideo(); | ||
if (navigator.mediaDevices.getUserMedia) { | ||
navigator.mediaDevices.getUserMedia({ video: true }) | ||
.then(function (stream) { | ||
video.srcObject = stream; | ||
video.play(); | ||
|
||
video.onloadeddata = (e) => { | ||
initMLModel() | ||
} | ||
}) | ||
.catch(function (err) { | ||
console.log("Something went wrong!"); | ||
console.error(err); | ||
}); | ||
} | ||
} | ||
|
||
function initMLModel() { | ||
const video = getVideo(); | ||
const context = getCanvasContext("outputVideo"); | ||
bodyPix.load({ | ||
architechture: 'MobileNetV1', | ||
outputStride: 16, | ||
multiplier: 0.75, | ||
quantBytes: 2 | ||
}).then(model => { | ||
console.log('BodyPix model loaded.'); | ||
transformFrame(model, video, context) | ||
}).catch(err => { | ||
console.error(err); | ||
}) | ||
} | ||
|
||
function transformFrame(model, sourceVideo, targetCanvasCtx) { | ||
const w = sourceVideo.videoWidth || sourceVideo.width; | ||
const h = sourceVideo.videoHeight || sourceVideo.height; | ||
const tempCanvas = document.getElementById('bufferVideo'); | ||
const tempCtx = tempCanvas.getContext('2d'); | ||
tempCtx.drawImage(sourceVideo, 0, 0, w, h); | ||
const frame = tempCtx.getImageData(0, 0, w, h); | ||
console.log(frame); | ||
model.segmentPerson(tempCanvas, { | ||
flipHorizontal: true, | ||
internalResolution: 'high', | ||
segmentationThreshold: 0.3, | ||
scoreThreshold: 0.3, | ||
maxDetections: 1, | ||
nmsRadius: 20 | ||
}).then(segment => { | ||
for (let x = 0; x < w; x++) { | ||
for (let y = 0; y < h; y++) { | ||
let n = x + y * w; | ||
if(segment.data[n] == 0) { | ||
frame.data[n * 4 + 0] = 0; | ||
frame.data[n * 4 + 1] = 255; | ||
frame.data[n * 4 + 2] = 0; | ||
frame.data[n * 4 + 3] = 255; | ||
} | ||
} | ||
} | ||
targetCanvasCtx.putImageData(frame, 0, 0); | ||
window.requestAnimationFrame(()=>{ | ||
transformFrame(model, sourceVideo, targetCanvasCtx) | ||
}); | ||
}).catch(err => { | ||
console.error(err); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" dir="ltr"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Virtual Green Background</title> | ||
<script src="node_modules/@tensorflow/tfjs/dist/tf.min.js" charset="utf-8"></script> | ||
<script src="node_modules/@tensorflow-models/body-pix/dist/body-pix.min.js" charset="utf-8"></script> | ||
<script src="node_modules/bluebird/js/browser/bluebird.min.js" charset="utf-8"></script> | ||
<script src="app.js" charset="utf-8"></script> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
<body> | ||
<video id="inputVideo" width="640" height="480" autoplay="true" muted></video> | ||
<canvas id="outputVideo" width="640" height="480"></canvas> | ||
<canvas id="bufferVideo" width="640" height="480"></canvas> | ||
</body> | ||
</html> |
Oops, something went wrong.