Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update farm_ng_amiga examples/tutorial #190

Merged
merged 14 commits into from
Sep 27, 2023
100 changes: 100 additions & 0 deletions website/docs/examples/camera_calibration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
id: camera-calibration
title: Camera Calibration
---

## Camera Calibration

The requirements to run this example are to have a
[**farm-ng brain**](/docs/brain/) running Oak cameras and that
your PC is on the same local network as the brain.

### 1. Install the [farm-ng Brain ADK package](/docs/brain/brain-install)

### 2. Setup

:::tip

It is recommended to also install these dependencies and run the
example in the brain ADK virtual environment.

:::

Create first a virtual environment

```bash
python3 -m venv venv
source venv/bin/activate
```

```bash
# assuming you're already in the amiga-dev-kit/ directory
cd farm-ng-amiga/py/examples/camera_calibration
```

### 3. Install the example's dependencies

```bash
pip3 install -r requirements.txt
```

### 4. Execute the Python script

```bash
python3 main.py --service-config service_config.json
```

:::info
By default, the camera address is assumed top be `localhost`.
:::

### 5. Customize run

```bash
# usage: amiga-camera-calibration [-h] --service-config SERVICE_CONFIG
#
# optional arguments:
# -h, --help show this help message and exit
# --service-config SERVICE_CONFIG
# The camera config.
```

### 6. Code overview

In this example we use the `EventClient` with the `request_reply`
method to receive the camera camera calibration.
The `request_reply` method is a coroutine that returns a `Future` object.
The `Future` object is used to retrieve the result of the request.

The path to the calibration service is `/calibration` and the request message is `Empty`.
The response message is `OakCalibration`, which is automatically decoded by the `request_reply`
method using the `decode=True` argument.

```python
async def main(service_config_path: Path) -> None:
"""Request the camera calibration from the camera service.

Args:
service_config_path (Path): The path to the camera service config.
"""
# create a client to the camera service
config: EventServiceConfig = proto_from_json_file(service_config_path, EventServiceConfig())

# get the calibration message
calibration: oak_pb2.OakCalibration =
await EventClient(config).request_reply("/calibration", Empty(), decode=True)
print(calibration)


if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="amiga-camera-calibration")
parser.add_argument("--service-config", type=Path, required=True, help="The camera config.")
args = parser.parse_args()

asyncio.run(main(args.service_config))
```

:::tip
We highly recommend to have some basic knowledge about
[**`asyncio`**](https://docs.python.org/3/library/asyncio.html).
:::
74 changes: 0 additions & 74 deletions website/docs/examples/camera_calibration/camera-calibration.md

This file was deleted.

83 changes: 31 additions & 52 deletions website/docs/examples/camera_client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pip3 install -r requirements.txt
### 3. Execute the Python script

```bash
python3 main.py --port 50051
python3 main.py --service-config service_config.json
```

:::info
Expand All @@ -55,78 +55,57 @@ the `WifiClient` (coming soon)
```bash
python3 main.py --help

# usage: amiga-camera-app [-h] --port PORT [--address ADDRESS]
#[--stream-every-n STREAM_EVERY_N]

# usage: amiga-camera-stream [-h] --service-config SERVICE_CONFIG
#
# optional arguments:
# -h, --help show this help message and exit
# --port PORT The camera port.
# --address ADDRESS The camera address
# --stream-every-n STREAM_EVERY_N
# Streaming frequency
# --service-config SERVICE_CONFIG
# The camera config.
```

Usage example:

```bash
python3 main.py --address 192.168.1.93 --port 50051
```
To customize the run, you need to update the `service_config.json`
by modifying the `host` and `port` fields.

### 5. Code overview

Basic structure to consume from the camera client in an async
fashion.
In this example we use the `EventClient` with the `subscribe` method to receive the camera stream.

```python
from farm_ng.oak.client import OakCameraClient,
OakCameraClientConfig
from farm_ng.oak import oak_pb2

async def main(address: str, port: int, stream_every_n: int) ->
None:
async def main(service_config_path: Path) -> None:
"""Run the camera service client.

# configure the camera client
config = OakCameraClientConfig(address=address, port=port)
client = OakCameraClient(config)
Args:
service_config_path (Path): The path to the camera service config.
"""
# create a client to the camera service
config: EventServiceConfig = proto_from_json_file(service_config_path, EventServiceConfig())

# get the streaming object
response_stream = client.stream_frames(every_n=stream_every_n)
# instantiate the image decoder
image_decoder = ImageDecoder()

# start the streaming service
await client.connect_to_service()
async for event, message in EventClient(config).subscribe(config.subscriptions[0], decode=True):
print(f"Timestamps: {event.timestamps[-2]}")
print(f"Meta: {message.meta}")
print("###################\n")

while True:
# query the service state
state: oak_pb2.OakServiceState = await client.get_state()
# cast image data bytes to numpy and decode
image = np.from_dlpack(image_decoder.decode(message.image_data))

if state.value != oak_pb2.OakServiceState.RUNNING:
print("Camera is not streaming!")
continue
# visualize the image
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
cv2.imshow("image", image)
cv2.waitKey(1)

response: oak_pb2.StreamFramesReply = await
response_stream.read()
if response and response.status == oak_pb2.ReplyStatus.OK:
# get the sync frame
frame: oak_pb2.OakSyncFrame = response.frame
print(f"Got frame: {frame.sequence_num}")
print(f"Device info: {frame.device_info}")
print("#################################\n")

if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="amiga-camera-app")
parser.add_argument("--port", type=int, required=True,
help="The camera port.")
parser.add_argument("--address", type=str,
default="localhost", help="The camera address")
parser.add_argument("--stream-every-n", type=int, default=4,
help="Streaming frequency")
parser = argparse.ArgumentParser(prog="amiga-camera-stream")
parser.add_argument("--service-config", type=Path, required=True, help="The camera config.")
args = parser.parse_args()

asyncio.run(main(args.address, args.port, args.
stream_every_n))
asyncio.run(main(args.service_config))
```

:::tip
We highgly recommend to have some basic knowledge about
We highly recommend to have some basic knowledge about
[**`asyncio`**](https://docs.python.org/3/library/asyncio.html).
:::
Loading
Loading