Skip to content

Commit

Permalink
a bunch of pointless changes nobody cares about
Browse files Browse the repository at this point in the history
* updated readme
* frame transformers now work directly on ArrayBuffers
* mode option parser less bad
* new constructor options
  • Loading branch information
turbocrime committed Sep 20, 2023
1 parent 905131d commit 59b7372
Show file tree
Hide file tree
Showing 10 changed files with 574 additions and 393 deletions.
59 changes: 22 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,60 +33,49 @@ original kinect only.
### Xbox NUI Camera

* depth 11bpp, 10bpp
* visible 8bpp bayer
* visible 8bpp bayer, 16bpp yuv
* infrared 10bpp
* arbitrary register manipulation

visible and infrared stream from the same endpoint, so you can only have one at a time.
visible and infrared stream from the same endpoint, so you can only have one at a time. you can use my pipeline and get a `ReadableStream<ImageData>` that you just blit to canvas, or set a custom deraw function.

## why

i failed to build libfreenect with emscripten. libusb added webusb/wasm platform support last year, so theoretically it's possible.

whatever. its the future and webusb is real
building libfreenect with emscripten turned out to be impossible for various reasons. whatever. it's the future and webusb is real

## how

go dig your kinect out of the closet. plug it in. open <https://turbocrime.github.io/webnect>

for a local demo, clone this repo.

## diy

available on npm as [`@webnect/webnect`](https://www.npmjs.com/package/@webnect/webnect)

or for a local demo, clone this repo. run

```sh
$ pnpm install
$ pnpm dev
```

that kicks off a little https guy with a fresh self-signed cert.

open <https://localhost:5174/>

after you dismiss the scary ssl warning you'll see a page with basic demos. go wild.

by default, it will try to acquire just the camera. hit the button (webusb requires user action to initiate), then select one of the available devices in the modal (there is probably only one).

no docs, but the lib is pretty simple. you can instantiate a new kinect with
no docs yet, but it's pretty simple. you can grab a new kinect camera with

```typescript
import { KinectDevice } from webnect;
const k = await (new KinectDevice()).ready;
import k from "@webnect/webnect";
const dev: USBDevice = await k.claimNuiCamera();
const kcam = k.Camera(dev);
kcam.mode({ depth: k.DEPTH_MODE });
const depthStream: ReadableStream<ImageData> = kcam.depth.getReader();
```

the constructor takes a single optional argument, `devices`, of type
alternatively, if you want raw frames in a specific mode, you could

```typescript
devices? : {
camera?: USBDevice | boolean, // default true
motor?: USBDevice| boolean, // default false
audio?: USBDevice | boolean, // default false
}
import k, { Modes, CamType, CamFmtVisible } from "@webnect/webnect";
const dev: USBDevice = await k.claimNuiCamera();
const kcam = k.Camera(dev, {
modes: { depth: Modes.OFF, video: { stream: CamType.VISIBLE, format: CamFmtVisible.YUV_16B } },
deraw: { depth: false, video: false }
});
const yuvFrameStream: ReadableStream<ArrayBuffer> = kcam.video.getReader();
```

pass a boolean indicating your desire to request acquisition, or pass a USBDevice if you have already one already acquired.

### um its broekn
### um its broekn??

if you see an empty device selection modal, you probably have the wrong model kinect. you can check your usb devices with `lsusb` on linux or on `system_profiler SPUSBDataType` on macos

Expand All @@ -100,10 +89,6 @@ also, typescript aint exactly the optimal language for bitmath or destructuring

## way

the mathy parts are an obvious candidate for assemblyscript and webgpu acceleration. do NOT send a patch i wanna do it

i should probably learn how to actually use canvas and streams

probably going after pose features next, maybe registration of visible light to depth frames. and then audio device and firmware stuff.
probably going after pose features next, maybe alignment of video to depth. and then firmware/audio stuff.

someday.... kinect2?
41 changes: 24 additions & 17 deletions demo/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ const ui = Object.fromEntries(

const getUsb = () => navigator.usb.getDevices();

const customDepthRgba = (raw: ArrayBuffer, rgba?: Uint8ClampedArray) => {
const rgbaFrame = rgba ?? new Uint8ClampedArray(cWidth * cHeight * 4);
const customDepthRgba = (raw: ArrayBuffer, out?: ArrayBuffer) => {
const rgbaFrame = out
? new Uint8ClampedArray(out)
: new Uint8ClampedArray(cWidth * cHeight * 4);
// frame is 11bit packed gray, unpack to u16 gray
const grayFrame = format.unpackGray(11, raw);
const grayFrame = new Uint16Array(format.unpackGray(11, raw)!);

// moving color ramps
const colorMarch = window.performance.now() / 10;
Expand All @@ -64,7 +66,7 @@ const customDepthRgba = (raw: ArrayBuffer, rgba?: Uint8ClampedArray) => {
rgbaFrame[i * 4 + 2] = ((grayPixel << 3) + colorMarch) & 0xff;
rgbaFrame[i * 4 + 3] = grayPixel < 2047 ? 0xff : 0x00;
}
return rgbaFrame;
if (!out) return rgbaFrame.buffer;
};

async function listDevices(devices: USBDevice[]) {
Expand Down Expand Up @@ -108,7 +110,9 @@ async function setupDevices(devices: USBDevice[]) {

function setupCameraDemo(cameraDevice: USBDevice) {
cameraDevice.open();
const camera = new k.Camera(cameraDevice);
const camera = new k.Camera(cameraDevice, {
deraw: { depth: customDepthRgba },
});
cameraDemo.hidden = false;
cameraDemo.disabled = false;
cameraDemo.classList.remove("disabled");
Expand Down Expand Up @@ -166,29 +170,32 @@ function setupCameraDemo(cameraDevice: USBDevice) {
const flip = ui.videoFlipCb.checked ? 1 : 0;
switch (ui.videoModeOpt.value) {
case "depth": {
camera.mode({ ...k.Modes.DEPTH, flip }, k.Modes.OFF);
camera.depth.rawDeveloper!.customFn = customDepthRgba;
camStream = camera.depth.readable;
camera.mode({
depth: { ...k.Modes.DEPTH, flip },
video: k.Modes.OFF,
});
//camera.deraw({ depth: customDepthRgba });
camStream = camera.depth;
break;
}
case "visible": {
camera.mode(k.Modes.OFF, {
...k.Modes.VISIBLE,
flip,
camera.mode({
depth: k.Modes.OFF,
video: { ...k.Modes.VISIBLE, flip },
});
camStream = camera.video.readable;
camStream = camera.video;
break;
}
case "ir": {
camera.mode(k.Modes.OFF, {
...k.Modes.INFRARED,
flip,
camera.mode({
depth: k.Modes.OFF,
video: { ...k.Modes.INFRARED, flip },
});
camStream = camera.video.readable;
camStream = camera.video;
break;
}
default:
camStream = camera.video.readable;
camStream = camera.depth;
}

reader = camStream.getReader();
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@webnect/webnect",
"author": "turbocrime",
"description": "a webUSB driver for the xbox360 kinect",
"version": "0.0.4",
"version": "0.0.5",
"type": "module",
"workspaces": [
"demo"
Expand Down Expand Up @@ -38,7 +38,7 @@
"types": "./dist/index.d.ts"
},
"devDependencies": {
"@biomejs/biome": "^1.1.2",
"@biomejs/biome": "^1.2.2",
"@types/w3c-web-usb": "^1.0.6",
"typescript": "^5.2.2"
}
Expand Down
44 changes: 22 additions & 22 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 59b7372

Please sign in to comment.