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

fix:libcamera support #1

Merged
merged 9 commits into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,51 @@ The `settings.json` file allows you to configure the behavior of the Camera Skil
"keep_camera_open": false
}
```


### Additional Steps for Raspberry Pi Users

If you plan to use this skill on a Raspberry Pi, it requires access to the `libcamera` package for the Picamera2 library to function correctly. Due to how `libcamera` is installed on the Raspberry Pi (system-wide), additional steps are necessary to ensure compatibility when using a Python virtual environment (venv).

#### **Steps to Enable `libcamera` in Your Virtual Environment**

1. **Install Required System Packages**
Before proceeding, ensure that `libcamera` and its dependencies are installed on your Raspberry Pi. Run the following commands:
```bash
sudo apt update
sudo apt install libcamera-apps python3-picamera2
```

2. **Modify the Virtual Environment Configuration**
If you already have a virtual environment set up, enable access to system-wide packages by modifying the `pyvenv.cfg` file in the virtual environment directory:
```bash
nano /path/to/your/venv/pyvenv.cfg
```

Add or update the following line:
```plaintext
include-system-site-packages = true
```

Save the file and exit.

3. **Verify Access to `libcamera`**
Activate your virtual environment:
```bash
source /path/to/your/venv/bin/activate
```

Check if the `libcamera` package is accessible:
```bash
python3 -c "import libcamera; print('libcamera is accessible')"
```

#### **Why Are These Steps Necessary?**
The `libcamera` package is not available on PyPI and is installed system-wide on the Raspberry Pi. Virtual environments typically isolate themselves from system-wide Python packages, so these adjustments allow the skill to access `libcamera` while still benefiting from the isolation provided by a venv.

#### **Notes**
- These steps are specific to Raspberry Pi users who want to utilize the Picamera2 library for camera functionality. On other platforms, the skill defaults to using OpenCV, which does not require additional configuration.
- Ensure that `libcamera` is installed on your Raspberry Pi before attempting these steps. You can test this by running:
```bash
libcamera-still --version
```
46 changes: 38 additions & 8 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from os.path import dirname, exists, join

import cv2
import numpy as np
from imutils.video import VideoStream
from ovos_utils import classproperty
from ovos_utils.log import LOG
Expand Down Expand Up @@ -32,25 +33,54 @@ def initialize(self):
if "play_sound" not in self.settings:
self.settings["play_sound"] = True
self._camera = None
self.camera_type = self.detect_camera_type()

def open_camera(self) -> VideoStream:
if self._camera is None:
@staticmethod
def detect_camera_type() -> str:
"""Detect if running on Raspberry Pi with libcamera or desktop."""
try:
# only works in rpi
import libcamera
return "libcamera"
except:
return "opencv"
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

def open_camera(self):
"""Open camera based on detected type."""
if self.camera_type == "libcamera":
try:
from picamera2 import Picamera2
self._camera = Picamera2()
self._camera.start()
LOG.info("libcamera initialized")
except Exception as e:
LOG.error(f"Failed to start libcamera: {e}")
return None
elif self.camera_type == "opencv":
try:
LOG.info("initializing camera stream")
self._camera = VideoStream(self.settings.get("video_source", 0))
if not self._camera.stream.grabbed:
self._camera = None
raise ValueError("Camera stream could not be started")
raise ValueError("OpenCV Camera stream could not be started")
self._camera.start()
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
except Exception as e:
LOG.error(f"Failed to open camera: {e}")
LOG.error(f"Failed to start OpenCV camera: {e}")
return None
return self._camera

def get_frame(self, cam) -> np.ndarray:
if self.camera_type == "libcamera":
return cam.capture_array()
else:
return cam.get()
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

def close_camera(self):
"""Close the camera."""
if self._camera:
LOG.info("closing camera stream")
self._camera.stop()
if self.camera_type == "libcamera":
self._camera.close()
elif self.camera_type == "opencv":
self._camera.stop()
self._camera = None

@property
Expand All @@ -73,7 +103,7 @@ def handle_take_picture(self, message):
self.speak_dialog("camera_error")
return
self.play_camera_sound()
frame = cam.get().copy()
frame = self.get_frame(cam)
pic_path = join(self.pictures_folder, time.strftime("%Y-%m-%d_%H-%M-%S") + ".jpg")
cv2.imwrite(pic_path, frame)
self.gui.show_image(pic_path)
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
imutils
ovos_workshop>=0.0.12
opencv-python
picamera2
Loading