Fix picam support
This commit is contained in:
parent
d254b6307b
commit
e03d5e7872
|
@ -29,12 +29,12 @@ import sys
|
||||||
import gphoto2 as gp
|
import gphoto2 as gp
|
||||||
|
|
||||||
camera_current_settings = {
|
camera_current_settings = {
|
||||||
'capturemode' : 3, # use IR remote
|
'capturemode' : dict(min=0, max=4, default=0, value=3), # 0: single,1: burst,2:Timer,3:2S Remote,4:Quick remote
|
||||||
'imagesize' : 2, # use size S (1936x1296)
|
'imagesize' : dict(min=0, max=2, default=0, value=2), # 0:L, 1:M, 2: S (1936x1296)
|
||||||
'whitebalance' : 1, # Natural light
|
'whitebalance' : dict(min=0, max=7, default=0, value=1), # 0 Automatic 1 Daylight 2 Fluorescent 3 Tungsten 4 Flash 5 Cloudy 6 Shade 7 Preset
|
||||||
'capturetarget' : 0, # Internal memory
|
'capturetarget' : dict(min=0, max=1, default=0, value=0), # Internal memory
|
||||||
'nocfcardrelease' : 0, # Allow capture without sd card
|
# ~ 'nocfcardrelease' : dict(min=0, max=1, default=0, value=0), # Allow capture without sd card
|
||||||
'recordingmedia' : 1, # Write to RAM
|
# ~ 'recordingmedia' : dict(min=0, max=1, default=0, value=1), # Write to RAM
|
||||||
}
|
}
|
||||||
|
|
||||||
def initialize_camera():
|
def initialize_camera():
|
||||||
|
@ -50,12 +50,28 @@ def initialize_camera():
|
||||||
return camera, current_camera_config
|
return camera, current_camera_config
|
||||||
|
|
||||||
|
|
||||||
def apply_gphoto_setting(config, setting, new_value):
|
# TODO: find how to use gp.CameraWidget.get_range() and check parameter value is in range before applying.
|
||||||
|
|
||||||
|
def apply_gphoto_setting(config, setting, new_value, inc=False):
|
||||||
# find the $setting config item
|
# find the $setting config item
|
||||||
try:
|
try:
|
||||||
|
# Get widget with name $setting
|
||||||
cur_setting = gp.check_result(gp.gp_widget_get_child_by_name(config, setting))
|
cur_setting = gp.check_result(gp.gp_widget_get_child_by_name(config, setting))
|
||||||
# find corresponding choice
|
# Get a list of available choices
|
||||||
cur_setting_choice = gp.check_result(gp.gp_widget_get_choice(cur_setting, new_value))
|
choices = list(gp.check_result(gp.gp_widget_get_choices(cur_setting)))
|
||||||
|
# Build dict with name/value equivalence
|
||||||
|
choices_dict = {choices.index(i):i for i in list(choices)}
|
||||||
|
# Increment mode : current value is increased or looped
|
||||||
|
if inc:
|
||||||
|
# Get current setting value
|
||||||
|
new_value = gp.check_result(gp.gp_widget_get_value(cur_setting))
|
||||||
|
# Check current value + 1 is in range
|
||||||
|
if new_value in range(0, len(choices)):
|
||||||
|
# Apply or loop value accordingly
|
||||||
|
pass
|
||||||
|
# If new_value exists in list, apply
|
||||||
|
if new_value['value'] in choices_dict:
|
||||||
|
cur_setting_choice = gp.check_result(gp.gp_widget_get_choice(cur_setting, new_value['value']))
|
||||||
# set config value
|
# set config value
|
||||||
gp.check_result(gp.gp_widget_set_value(cur_setting, cur_setting_choice))
|
gp.check_result(gp.gp_widget_set_value(cur_setting, cur_setting_choice))
|
||||||
except:
|
except:
|
||||||
|
@ -66,8 +82,6 @@ def apply_dslr_settings(camera_settings):
|
||||||
camera, config = initialize_camera()
|
camera, config = initialize_camera()
|
||||||
# iterate over the settings dictionary
|
# iterate over the settings dictionary
|
||||||
for setting in camera_settings:
|
for setting in camera_settings:
|
||||||
print(setting)
|
|
||||||
print(camera_settings[setting])
|
|
||||||
apply_gphoto_setting(config, setting, camera_settings[setting])
|
apply_gphoto_setting(config, setting, camera_settings[setting])
|
||||||
# validate config
|
# validate config
|
||||||
status = gp.check_result(gp.gp_camera_set_config(camera, config))
|
status = gp.check_result(gp.gp_camera_set_config(camera, config))
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import cv2
|
import cv2
|
||||||
import gettext
|
import gettext
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
from importlib import import_module
|
||||||
import os
|
import os
|
||||||
# Needed for utf-8 text
|
# Needed for utf-8 text
|
||||||
from PIL import ImageFont, ImageDraw, Image
|
from PIL import ImageFont, ImageDraw, Image
|
||||||
|
@ -222,7 +223,7 @@ class webcam():
|
||||||
|
|
||||||
class showmewebcam(webcam):
|
class showmewebcam(webcam):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.serialutils = __import__('serialutils')
|
self.serialutils = import_module('serialutils')
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.camera_current_settings = {
|
self.camera_current_settings = {
|
||||||
'auto_exposure': dict(min=0, max=1, step=1, default=camera_settings['auto_exposure'], value=camera_settings['auto_exposure']),
|
'auto_exposure': dict(min=0, max=1, step=1, default=camera_settings['auto_exposure'], value=camera_settings['auto_exposure']),
|
||||||
|
@ -267,8 +268,10 @@ class picam():
|
||||||
self.onionskin_was_on = self.onionskin
|
self.onionskin_was_on = self.onionskin
|
||||||
self.liveview_only = False
|
self.liveview_only = False
|
||||||
# Pi Cam V3 setup
|
# Pi Cam V3 setup
|
||||||
self.Picamera2 = __import__('picamera2.Picamera2')
|
self.Picamera2 = getattr(import_module('picamera2'), 'Picamera2')
|
||||||
self.Transform = __import__('libcamera.Transform')
|
self.Transform = getattr(import_module('libcamera'), 'Transform')
|
||||||
|
# ~ self.Picamera2 = __import__('picamera2.Picamera2')
|
||||||
|
# ~ self.Transform = __import__('libcamera.Transform')
|
||||||
# ~ from picamera2 import Picamera2
|
# ~ from picamera2 import Picamera2
|
||||||
# ~ from libcamera import Transform
|
# ~ from libcamera import Transform
|
||||||
try:
|
try:
|
||||||
|
@ -308,10 +311,7 @@ class picam():
|
||||||
|
|
||||||
# Same as in webcam() class
|
# Same as in webcam() class
|
||||||
def capture_preview(self):
|
def capture_preview(self):
|
||||||
ret, overlay = self.cam.read()
|
overlay = cam.capture_array("main")
|
||||||
if not ret:
|
|
||||||
print(_("Failed to grab frame."))
|
|
||||||
return False
|
|
||||||
# Resize preview to fit screen
|
# Resize preview to fit screen
|
||||||
overlay = cv2.resize(overlay, (project_settings['screen_w'], project_settings['screen_h']))
|
overlay = cv2.resize(overlay, (project_settings['screen_w'], project_settings['screen_h']))
|
||||||
if self.liveview_only:
|
if self.liveview_only:
|
||||||
|
@ -359,6 +359,7 @@ class picam():
|
||||||
self.cam.set_controls({'AeFlickerMode': 1, 'AeFlickerPeriod':10000})
|
self.cam.set_controls({'AeFlickerMode': 1, 'AeFlickerPeriod':10000})
|
||||||
|
|
||||||
def apply_setting(self, to_set:list=None, inc:bool=False):
|
def apply_setting(self, to_set:list=None, inc:bool=False):
|
||||||
|
if to_set is not None:
|
||||||
for setting in to_set:
|
for setting in to_set:
|
||||||
if inc:
|
if inc:
|
||||||
self.increment_setting(setting)
|
self.increment_setting(setting)
|
||||||
|
@ -390,7 +391,7 @@ class picam():
|
||||||
class dslr():
|
class dslr():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# ~ import gphoto2 as gp
|
# ~ import gphoto2 as gp
|
||||||
self.gp = __import__('gphoto2')
|
self.gp = import_module('gphoto2')
|
||||||
self.camera_current_settings = {
|
self.camera_current_settings = {
|
||||||
'capturemode' : dict(min=0, max=4, default=0, value=1), # 0: single,1: burst,2:Timer,3:2S Remote,4:Quick remote
|
'capturemode' : dict(min=0, max=4, default=0, value=1), # 0: single,1: burst,2:Timer,3:2S Remote,4:Quick remote
|
||||||
'imagesize' : dict(min=0, max=2, default=2, value=2), # 0:L, 1:M, 2: S (1936x1296)
|
'imagesize' : dict(min=0, max=2, default=2, value=2), # 0:L, 1:M, 2: S (1936x1296)
|
||||||
|
|
27
readme.md
27
readme.md
|
@ -1,9 +1,8 @@
|
||||||
# Stopi2
|
# Stopi2
|
||||||
|
|
||||||
## Branche libcamera
|
## Branche gphoto / réflexe nunmérique
|
||||||
|
|
||||||
**Ceci est la branche qui restaure la possibilité d'utiliser des périphériques compatibles rpi-libcamera (Modules Raspicam v1,v2 et v3).**
|
**Ceci est la branche qui restaure la possibilité d'utiliser des périphériques compatibles [gphoto](http://gphoto.org/doc/remote).**
|
||||||
**En utilisant la [branche correspondante pour la télécommande picote](/arthus/picote/src/branch/picamera), vous pouvez régler la mise au point du module caméra avec un [codeur rotatif](https://fr.wikipedia.org/wiki/Codeur_rotatif).**
|
|
||||||
|
|
||||||
<a style="max-height: 300px;display: inline-block;" href="./stopi2/raw/branch/master/stopi_station.jpg"><img src="./stopi_station.jpg"/><a/>
|
<a style="max-height: 300px;display: inline-block;" href="./stopi2/raw/branch/master/stopi_station.jpg"><img src="./stopi_station.jpg"/><a/>
|
||||||
|
|
||||||
|
@ -16,6 +15,7 @@ Encore une fois, l'objectif est de créer un logiciel simple et minimaliste dans
|
||||||
* [Pelure d'oignon](https://fr.wikipedia.org/wiki/Pelure_d'oignon#Sciences_et_techniques) entre la dernière image et le flux vidéo.
|
* [Pelure d'oignon](https://fr.wikipedia.org/wiki/Pelure_d'oignon#Sciences_et_techniques) entre la dernière image et le flux vidéo.
|
||||||
* Un seul fichier de configuration permet de régler les options (résolution, images/secondes, mirroir vertical/horizontal, )
|
* Un seul fichier de configuration permet de régler les options (résolution, images/secondes, mirroir vertical/horizontal, )
|
||||||
* Auto configuration de la camera au démarrage (exposition et balance des blancs)
|
* Auto configuration de la camera au démarrage (exposition et balance des blancs)
|
||||||
|
* Pilotage de certains réglages de la caméra depuis la télécommande/clavier (balance des blancs, rotation de l'image, mise au point (picam V3), exposition...)
|
||||||
* Prévisualisation de l'animation
|
* Prévisualisation de l'animation
|
||||||
* Exportation vidéo avec [ffmpeg](https://ffmpeg.org/)
|
* Exportation vidéo avec [ffmpeg](https://ffmpeg.org/)
|
||||||
* Interface localisée (anglais et français disponible pour le moment.)
|
* Interface localisée (anglais et français disponible pour le moment.)
|
||||||
|
@ -23,6 +23,22 @@ Encore une fois, l'objectif est de créer un logiciel simple et minimaliste dans
|
||||||
## Banc de test
|
## Banc de test
|
||||||
|
|
||||||
Ce script a été testé avec une webcam compatible V4L2, une ["showmewebcam"](https://github.com/showmewebcam/showmewebcam) à base de rpi 0 et d'un module caméra v2 (8Mp), et un ordinateur classique sous [Debian](https://debian.org) et un [RPI 4B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) munis d'un module [Picamera V3](https://www.raspberrypi.com/products/camera-module-3/).
|
Ce script a été testé avec une webcam compatible V4L2, une ["showmewebcam"](https://github.com/showmewebcam/showmewebcam) à base de rpi 0 et d'un module caméra v2 (8Mp), et un ordinateur classique sous [Debian](https://debian.org) et un [RPI 4B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) munis d'un module [Picamera V3](https://www.raspberrypi.com/products/camera-module-3/).
|
||||||
|
|
||||||
|
Voici un récapitulatif des tests effectués :
|
||||||
|
|
||||||
|
| Machine \ Type de Caméra | Webcam | [Showmewebcam](https://github.com/showmewebcam/showmewebcam) | RPI Caméra module V1 (5MP) | [RPI Caméra module V3](https://www.raspberrypi.com/products/camera-module-3/) (12MP) | [Réflexe numérique](http://gphoto.org/doc/remote) (Nikon D3000/D40x)|
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| Raspberry Pi 4B (Debian 12) | | | ✓ | | |
|
||||||
|
| PC Linux (Debian, Manjaro) | ✓ | ✓ | N/A | N/A | ✓ |
|
||||||
|
|
||||||
|
## Feuille de route
|
||||||
|
|
||||||
|
Des fonctions supplémentaires sont prévues :
|
||||||
|
|
||||||
|
* Réflexe numérique: utilisation du liveview de l'appareil (si je trouve un modèle compatible pour le développement)
|
||||||
|
|
||||||
|
## Contributions
|
||||||
|
|
||||||
Les contributions et rapports de bugs sont les bienvenus !
|
Les contributions et rapports de bugs sont les bienvenus !
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
@ -33,15 +49,16 @@ Dans un terminal :
|
||||||
1. Installer les dépendances suivantes :
|
1. Installer les dépendances suivantes :
|
||||||
```
|
```
|
||||||
# Avec une distribution basée sur Debian (Ubuntu, Mint...)
|
# Avec une distribution basée sur Debian (Ubuntu, Mint...)
|
||||||
sudo apt install --no-install-recommends --no-install-suggests git ffmpeg python3-pip python3-venv libtiff5-dev libtopenjp2 libopenjp2-7-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev libharfbuzz-dev libfribidi-dev libxcb1-dev python3-tk python3-dev libopenblas-dev libatlas-base-dev libhdf5-dev libhdf5-serial-dev libatlas-base-dev libjasper-dev libqtgui4 libqt4-test v4l-utils
|
sudo apt install --no-install-recommends --no-install-suggests git ffmpeg python3-pip python3-venv libtiff5-dev libopenjp2-7 libopenjp2-7-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev libharfbuzz-dev libfribidi-dev libxcb1-dev python3-tk python3-dev libopenblas-dev libatlas-base-dev libhdf5-dev libhdf5-serial-dev libatlas-base-dev libjasper-dev libqtgui4 libqt4-test v4l-utils
|
||||||
```
|
```
|
||||||
- (Optionnel) Pour installer un environnement graphique minimal sur une [installation console](https://debian-facile.org/doc:install:installation-minimale) : `sudo apt install --no-install-recommends --no-install-suggests openbox xserver-xorg xinit pcmanfm gmrun lxterminal hsetroot unclutter plymouth plymouth-themes`
|
- (Optionnel) Pour installer un environnement graphique minimal sur une [installation console](https://debian-facile.org/doc:install:installation-minimale) : `sudo apt install --no-install-recommends --no-install-suggests openbox xserver-xorg xinit pcmanfm gmrun lxterminal hsetroot unclutter plymouth plymouth-themes`
|
||||||
2. Cloner le dépôt dans le dossier de votre choix : `git clone https://git.arthus.net/arthus/stopi2.git`
|
2. Cloner le dépôt dans le dossier de votre choix : `git clone https://git.arthus.net/arthus/stopi2.git`
|
||||||
3. Aller dans répertoire du projet : `cd stopi2`
|
3. Aller dans répertoire du projet : `cd stopi2`
|
||||||
4. Créer un environnement virtuel (venv) Python : `python -m venv ./`
|
4. Créer un environnement virtuel (venv) Python : `python -m venv ./`
|
||||||
|
- `pip install -vvv --upgrade pip setuptools wheel`
|
||||||
- (Optionnel) Dans le cas de l'utilisation d'une "raspicam", il faudra ajouter le paramètre `--system-site-packages` pour avoir accès au module picamera2, et installer la librairie correspondante `python3-picamera2`.
|
- (Optionnel) Dans le cas de l'utilisation d'une "raspicam", il faudra ajouter le paramètre `--system-site-packages` pour avoir accès au module picamera2, et installer la librairie correspondante `python3-picamera2`.
|
||||||
5. Activer l'environnement virtuel avec `source bin/activate`
|
5. Activer l'environnement virtuel avec `source bin/activate`
|
||||||
6. Installer les dépendances python (~150Mo) : `pip install -r requirements.txt`
|
6. Installer les dépendances python (~150Mo) : `MAKEFLAGS="-j$(nproc)" pip install -r requirements.txt`
|
||||||
7. Activer l'éxécution du script : `chmod +x stopi2.sh`
|
7. Activer l'éxécution du script : `chmod +x stopi2.sh`
|
||||||
8. Lancer le script : `./stopi2.sh`
|
8. Lancer le script : `./stopi2.sh`
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,11 @@ def send_serial_cmd(cam_port, cmd:str, clear=True):
|
||||||
append = b'\r'
|
append = b'\r'
|
||||||
con.write(str.encode(cmd) + append)
|
con.write(str.encode(cmd) + append)
|
||||||
con.close()
|
con.close()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
cmd = "/usr/bin/v4l2-ctl --all"
|
||||||
|
send_serial_cmd(find_cam_port(), cmd)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
sys.exit(main())
|
Loading…
Reference in New Issue