Skip to main content

tensorcamera

Point your phone at something and see your own model's prediction, live.

This is the server half. The other half is the Tensor Camera app (iOS), which streams camera frames to whatever machine your model is on and shows what comes back.

pip install tensorcamera

Two minutes, no code

pip install 'tensorcamera[hf]'
tensorcamera serve --model objects

That downloads a model from Hugging Face, starts a server, and prints a QR code. Scan it with the app. tensorcamera presets lists the other built-in models, and any Hub id works too.

Your own model

from tensorcamera import TensorCamera

cam = TensorCamera(model="my-classifier", labels=["dog", "cat"])

@cam.on_frame
def predict(frame):
    probs = my_model(frame.resized(224)[None] / 255.0)[0]
    index = probs.argmax()
    return {"label": cam.labels[index], "confidence": float(probs[index])}

cam.serve()

serve() prints a QR code and listens on port 8080. Phone and computer need to be on the same Wi-Fi network.

The handler

Return whatever is convenient:

Return Meaning
None Skip this frame, send nothing
"Found a dog" Display text only
("dog", 0.94) Label and confidence
{"label": ..., "confidence": ..., "text": ..., "top": [...]} Full control

Return a label and a confidence if you can. Display text is for humans; label is what lets the app fire rules — play a sound, speak, vibrate, POST a webhook — when something is detected. A bare string leaves the app display-only.

The frame

@cam.on_frame
def predict(frame):
    frame.array        # numpy uint8, HWC, RGB — what Keras and torch expect
    frame.float01      # numpy float32, HWC, RGB, 0..1
    frame.resized(224) # numpy uint8, 224x224x3
    frame.jpeg         # raw JPEG bytes, undecoded
    frame.width, frame.height, frame.seq, frame.ts

Decoding is lazy. If your handler never touches the pixels, no decode happens.

Talking back to the phone

cam.send_action({"type": "sound", "asset": "bark.mp3"})
cam.send_action({"type": "speak", "text": "dog detected"})
cam.send_action({"type": "haptic", "style": "success"})

The app ignores anything it does not support, and refuses action types it did not advertise. It also rate-limits inbound actions, so a 10 fps stream cannot fire a sound ten times a second — but prefer device-side rules for that, since they keep working when the connection drops.

Keeping up

If inference is slower than the frame rate, predictions drift behind reality. Tell the phone how fast you actually are:

cam = TensorCamera(max_fps=3)

The app throttles to that budget. The server logs a warning the first time a handler overruns it.

Options

TensorCamera(
    model="my-classifier",   # shown in the app's diagnostics
    labels=["dog", "cat"],   # populates the rule editor's label picker (≤40)
    max_fps=10,              # frame budget asked of the phone
    quality=0.4,             # requested JPEG quality
    width=640, height=480,   # requested frame size
    token="shared-secret",   # require this from clients; carried in the QR code
)

cam.serve(host="0.0.0.0", port=8080, show_qr=True, name="Workshop MacBook")

Older app versions

The app on the App Store today predates this protocol. It sends raw float32 tensors on an untyped channel with no handshake, and expects a plain string back. This server detects that and handles it — including the newer app's legacy mode, which sends JPEG on the same channel. Both work, no flags.

You lose structured predictions and rules against an old client, because the v0 wire format has nowhere to put a label. Everything else works.

Protocol

The wire format is specified in PROTOCOL.md. You should not need it — that is the point of this package — but it is there if you want to write a server in another language. The app talks to anything that speaks it; this package is one implementation, not the contract.

Licence

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tensorcamera-0.1.1.tar.gz (34.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tensorcamera-0.1.1-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file tensorcamera-0.1.1.tar.gz.

File metadata

  • Download URL: tensorcamera-0.1.1.tar.gz
  • Upload date:
  • Size: 34.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tensorcamera-0.1.1.tar.gz
Algorithm Hash digest
SHA256 47f0206d06ffe1d886835d91435ef969a6730976eb24bc742cd022bc184d6fa7
MD5 dae6b9c17e626880e64ac4522f15e94c
BLAKE2b-256 a3bf87f7ed168566ce0438bceb85e2601640bc58a4444df6136349d6fa0716e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tensorcamera-0.1.1.tar.gz:

Publisher: publish.yml on SpunkySarb/tensorcamera

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tensorcamera-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: tensorcamera-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 19.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tensorcamera-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f01b80c864125031d01d8b2ad1ef153c9b120f3d30f9010e331741e1ed2b0f99
MD5 90a07991fc925a984be59ef06d4e552b
BLAKE2b-256 ba944a5a2fdfb3192e9177c83830f7140e85c8c7f4b278936c19f8a7cd375915

See more details on using hashes here.

Provenance

The following attestation bundles were made for tensorcamera-0.1.1-py3-none-any.whl:

Publisher: publish.yml on SpunkySarb/tensorcamera

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page