Skip to content

Commit

Permalink
Add command for camera setup prior capture loop
Browse files Browse the repository at this point in the history
  • Loading branch information
nvtkaszpir committed Mar 8, 2024
1 parent eea48da commit e55c970
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 4 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ set -o allexport; source .env; set +o allexport

```

Any linux host with ffmpeg and RTSP camera:

```shell
# go to Prusa Connect site, add camera, copy token, turn on your 3D printer

cp ffmpeg-mediamtx-rtsp-tcp.dist .env
# edit .env file, set token and fingerprint
# change 'rtsp://raspberry-pi:8554/cam' to rtsp://<username>:<password>@<camera-ip-address>/<stream-name>

set -o allexport; source .env; set +o allexport

./prusa-connect-camera.sh

```

## Docs

```shell
Expand Down
13 changes: 13 additions & 0 deletions docs/config.for.camera.csi.legacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,16 @@ Example for older operating systems with (command `raspistill`):
- save edited file `.env`

Next, [test config](./test.config.md).

## Real world scenario

Some older RPI 3 with older Debian with basic cam:

```shell
PRINTER_ADDRESS=127.0.0.1
PRUSA_CONNECT_CAMERA_TOKEN=token-change-me
PRUSA_CONNECT_CAMERA_FINGERPRINT=trash-cam-night-video-wide-1
CAMERA_DEVICE=/dev/video0
CAMERA_COMMAND=raspistill
CAMERA_COMMAND_EXTRA_PARAMS="--nopreview --mode 640:480 -o"
```
15 changes: 15 additions & 0 deletions docs/config.for.camera.csi.libcamera.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,18 @@ Example for newer operating systems (commands `libcamera` or `rpicam-still`):
- save edited file `.env`

Next, [test config](./test.config.md).

## Real example

My Rpi Zero W with Raspberry Pi Camera v2 with maximum resolution available

<!-- markdownlint-disable line_length -->
```shell
PRINTER_ADDRESS=192.168.1.25
PRUSA_CONNECT_CAMERA_TOKEN=redatcted
PRUSA_CONNECT_CAMERA_FINGERPRINT=c10eb887-f107-41a4-900e-2c38ea12a11c
CAMERA_DEVICE=/dev/video0
CAMERA_COMMAND=rpicam-still
CAMERA_COMMAND_EXTRA_PARAMS="--immediate --nopreview --mode 2592:1944:12:P --lores-width 0 --lores-height 0 --thumb none -o"
```
<!-- markdownlint-enable line_length -->
16 changes: 16 additions & 0 deletions docs/config.for.camera.esphome.snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,19 @@ Flash the device and wait until it boots and is available.
- save edited file `.env`

Next, [test config](./test.config.md).

## Real world example

I have esp32-wrover-dev board with camera + esphome + web ui for camera exposing
snapshot frame on port `8081`.

We can use curl to fetch it.

```shell
PRINTER_ADDRESS=127.0.0.1
PRUSA_CONNECT_CAMERA_TOKEN=redacted
PRUSA_CONNECT_CAMERA_FINGERPRINT=06f47777-f179-4025-bd80-9e4cb8db2aed
CAMERA_DEVICE=/dev/null
CAMERA_COMMAND=curl
CAMERA_COMMAND_EXTRA_PARAMS=http://esp32-wrover-0461c8.local:8081/ -o
```
17 changes: 17 additions & 0 deletions docs/config.for.camera.esphome.stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ With esphome camera stream we can use the `ffmpeg` to fetch the image from the
camera stream. It requires a bit more computing power from esp device and the
host that runs the image processing.

Notice that this is not recommended way due to the amout of consumed resources.

## Prepare esphome device

Configure esphome device:
Expand Down Expand Up @@ -37,3 +39,18 @@ Flash the device and wait until it boots and is available.
- save edited file `.env`

Next, [test config](./test.config.md).

## Real world example

The same ESP device with stream, notice different port (`8080`).

<!-- markdownlint-disable line_length -->
```shell
PRINTER_ADDRESS=127.0.0.1
PRUSA_CONNECT_CAMERA_TOKEN=token-change-me
PRUSA_CONNECT_CAMERA_FINGERPRINT=f68336b-8dab-42cd-8729-6abd8855ff63
CAMERA_DEVICE=/dev/null
CAMERA_COMMAND=ffmpeg
CAMERA_COMMAND_EXTRA_PARAMS="-y -i 'http://esp32-wrover-0461c8.local:8080/' -vframes 1 -q:v 1 -f image2 -update 1 "
```
<!-- markdownlint-enable line_length -->
7 changes: 7 additions & 0 deletions docs/config.for.camera.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Notice that each camera should have different fingerprint and token.

Fingerprint can be easily generated using command:

```shell
uuidgen
```
just copy/paste the output as fingerprint value into the config.

**Do not** change fingerprint after launching the script - thus camera is registered
and you may need to revert the change or delete and readd camera again and start
from scratch.
Expand Down
40 changes: 40 additions & 0 deletions docs/config.for.camera.rtsp.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,43 @@ If that works, then configuration should be pretty straightforward:
You can try with `UDP`, but you may not get it ;-)

Next, [test config](./test.config.md).

## Real world example

My another Rpi Zero W named `hormex` has two cameras:

- CSI
- endoscope on /dev/video

and I'm running `mediamtx` server to conver those to RTSP streams.
More about mediamtx is [here](./stream.mediamtx.md).

So I can have two configs:

`.stream-csi` over UDP:

<!-- markdownlint-disable line_length -->

```shell
PRINTER_ADDRESS=127.0.0.1
PRUSA_CONNECT_CAMERA_TOKEN=redacted
PRUSA_CONNECT_CAMERA_FINGERPRINT=62e8ab72-9766-4ad5-b8b1-174d389fc0d3
CAMERA_DEVICE=/dev/null
CAMERA_COMMAND=ffmpeg
CAMERA_COMMAND_EXTRA_PARAMS="-loglevel error -y -rtsp_transport udp -i "rtsp://hormex:8554/cam" -f image2 -vframes 1 -pix_fmt yuvj420p "
```
<!-- markdownlint-enable line_length -->

`.stream-endo` over TCP:

<!-- markdownlint-disable line_length -->
```shell
PRINTER_ADDRESS=127.0.0.1
PRUSA_CONNECT_CAMERA_TOKEN=redacted
PRUSA_CONNECT_CAMERA_FINGERPRINT=01a67af8-86a3-45c7-b6e2-39e9d086b367
CAMERA_DEVICE=/dev/null
CAMERA_COMMAND=ffmpeg
CAMERA_COMMAND_EXTRA_PARAMS="-loglevel error -y -rtsp_transport tcp -i "rtsp://hormex:8554/endoscope" -f image2 -vframes 1 -pix_fmt yuvj420p "

```
<!-- markdownlint-enable line_length -->
15 changes: 15 additions & 0 deletions docs/config.for.camera.usb.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,18 @@ Notice not every device is an actual camera.
- save edited file `.env`

Next, [test config](./test.config.md).

## Real world example

Raspberry Pi Zero W with endoscope camera over USB, registered as `/dev/video1`:

<!-- markdownlint-disable line_length -->
```shell
PRINTER_ADDRESS=192.168.1.25
PRUSA_CONNECT_CAMERA_TOKEN=redacted
PRUSA_CONNECT_CAMERA_FINGERPRINT=7054ba85-bc19-4eb9-badc-6129575d9651
CAMERA_DEVICE=/dev/video1
CAMERA_COMMAND=fswebcam
CAMERA_COMMAND_EXTRA_PARAMS="--resolution 1280x960 --no-banner"
```
<!-- markdownlint-enable line_length -->
78 changes: 78 additions & 0 deletions docs/configuration.tuning.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,81 @@ For Raspberry Cam v2 you could use `csi.dist` as ssource and add

For certain USB cameras (such as Tracer Endoscope) you shoudl use `usb.dist` and
you should be able to add `--resolution 1280x960` to the `CAMERA_COMMAND_EXTRA_PARAMS`.

## Setting up video camera controls

Get device capabilities, especially User controls

```shell
v4l2-ctl -d /dev/video0 --all
```

and set accordingly parameters you want in `CAMERA_SETUP_COMMAND` env var, for example:

```shell
CAMERA_SETUP_COMMAND="v4l2-ctl --set-ctrl brightness=64,gamma=300 -d $CAMERA_DEVICE"
```

remember to restart given camera service.

You can try to use `guvcview` desktop application to check prams in realtime.

## Image flip and rotation

You can pass on params to rpicam-still or fswebcam as you want.

### rpicam-still

See `rpicam-still --help`

```text
--hflip Read out with horizontal mirror
--vflip Read out with vertical flip
--rotation Use hflip and vflip to create the given rotation <angle>
```

so for example:

```shell
CAMERA_COMMAND=rpicam-still
CAMERA_COMMAND_EXTRA_PARAMS="--rotation 90 --immediate --nopreview --thumb none -o"
```

### fswebcam

See `fswebcam --help`

```text
--flip <direction> Flips the image. (h, v)
--crop <size>[,<offset>] Crop a part of the image.
--scale <size> Scales the image.
--rotate <angle> Rotates the image in right angles.
```

so for example:

```shell
CAMERA_COMMAND=fswebcam
CAMERA_COMMAND_EXTRA_PARAMS="--flip v --resolution 640x480 --no-banner"
```

## ffdshow

With ffdshow you can things with filters, it will just require more computing power.

See [here](https://superuser.com/questions/578321/how-can-i-rotate-a-video-180-with-ffmpeg)
for basic ones.

You probably want to use `-vf "transpose=1"` to rotate image 90 degrees clockwise:
<!-- markdownlint-disable line_length -->
```shell
CAMERA_COMMAND=ffmpeg
CAMERA_COMMAND_EXTRA_PARAMS="-y -i 'http://esp32-wrover-0461c8.local:8080/' -vf "transpose=1" -vframes 1 -q:v 1 -f image2 -update 1 "
```
<!-- markdownlint-disable line_length -->

Frankly speaking you can do anything you want with ffdshow, for example

`-vf transpose=1,shufflepixels=m=block:height=16:width=16`

Why? why not :D
14 changes: 12 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
This project aims to make it easier to use any camera to be used as
Prusa Connect camera.

## Features

- allows to read images from CSI cameras, USB cameras, RTSP streams, still images...
- do not send pictures if the printer is offline
- store data in memory to prevent MicroSD wear out
- verbose error messages to see if the image capture works
- ability to run multiple cameras in separate instances

## Planned

- run in container

## Architecture

```mermaid
Expand All @@ -25,8 +37,6 @@ sequenceDiagram

## Known limitations

- TODO: camera pre-configuration is not yet supported
(such as fixed white balance etc)
- this script performs processing of the single camera, if you need more cameras
then just create multiple copies with different settings (see below)
- Rpi Zero W or older devices may have CPU limitations to process remote streams
Expand Down
5 changes: 3 additions & 2 deletions docs/stream.mediamtx.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# mediamtx

Use mediamtx on antoher Raspberry Pi to create RTSP camera stream for test.
Use [mediamtx](https://github.com/bluenviron/mediamtx) on another Raspberry Pi
to create RTSP camera stream for test.

Assuming you run [mediamtx with Raspberry Pi CSI camera](https://github.com/bluenviron/mediamtx#raspberry-pi-cameras)
and that `raspberry-pi` is the hostname of your device and that you expose two cams:
Expand Down Expand Up @@ -32,7 +33,7 @@ Start mediamtx server:
```

This should allow us to reach two streams, replace `rpi-address` with the name
of your Raspberry Pi hostname or IP address
of your Raspberry Pi hostname or IP address. The ports are default for mediamtx.

```shell
ffplay rtsp://rpi-address:8554/cam
Expand Down
18 changes: 18 additions & 0 deletions prusa-connect-camera.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
# camera device to use, if you use camera attached to the CSI via camera ribbon then leave as is
: "${CAMERA_DEVICE:=/dev/video0}"

# camera setup command and params
# executed before taking image
# defualt is empty, because some cameras do not support it
# in general you want to use something like v4l2-ctl
# <setup_command>
# so for example:
# setup_command=v4l2-ctl --set-ctrl brightness=10,gamma=120 -d $CAMERA_DEVICE
# will translate to:
# v4l2-ctl --set-ctrl brightness=10,gamma=120 -d /dev/video0
: "${CAMERA_SETUP_COMMAND:=}"

# avaliable options:
# rpicam-still - using CSI camera + modern Rasberry Pi operating systems since Debian 11 Bullseye
# raspistill - using CSI camera + older Raspberyy Pi operating systems
Expand Down Expand Up @@ -137,6 +148,13 @@ if [[ -z "${command_capture}" ]]; then
exit 1
fi

CAMERA_SETUP_COMMAND
if [[ -n "${CAMERA_SETUP_COMMAND}" ]]; then
echo "INFO: Running CAMERA_SETUP_COMMAND command"
echo "${CAMERA_SETUP_COMMAND}"
eval ${CAMERA_SETUP_COMMAND}
fi

echo "Camera capture command: ${command_capture} ${CAMERA_COMMAND_EXTRA_PARAMS} ${TARGET_DIR}/camera_${camera_id}.jpg"


Expand Down

0 comments on commit e55c970

Please sign in to comment.