Fix picam support

This commit is contained in:
ABelliqueux 2025-02-15 10:41:26 +01:00
parent e03d5e7872
commit 4cead89259
4 changed files with 113 additions and 120 deletions

View File

@ -29,8 +29,8 @@ import sys
import gphoto2 as gp
camera_current_settings = {
'capturemode' : dict(min=0, max=4, default=0, value=3), # 0: single,1: burst,2:Timer,3:2S Remote,4:Quick remote
'imagesize' : dict(min=0, max=2, default=0, value=2), # 0:L, 1:M, 2: S (1936x1296)
'capturemode' : dict(min=0, max=4, default=0, value=3), # 0: single,1: burst,2:Timer,3:2S Remote,4:Quick remote
'imagesize' : dict(min=0, max=2, default=0, value=2), # 0:L, 1:M, 2: S (1936x1296)
'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' : dict(min=0, max=1, default=0, value=0), # Internal memory
# ~ 'nocfcardrelease' : dict(min=0, max=1, default=0, value=0), # Allow capture without sd card
@ -61,7 +61,7 @@ def apply_gphoto_setting(config, setting, new_value, inc=False):
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
# 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))
@ -124,7 +124,7 @@ def find_file_ext(gp_name:str, full_path:str):
print(suffix)
print(prefix)
return os.path.join(dirname, '.'.join(prefix))
def capture_and_download(target:str='/tmp'):
camera, current_camera_config = initialize_camera()

View File

@ -33,7 +33,7 @@ camera_status = []
LOCALE = os.getenv('LANG', 'en_EN')
_ = gettext.translation('template', localedir='locales', languages=[LOCALE]).gettext
# Config
# Config
# defaults
project_settings_defaults = {
'cam_type': "webcam",
@ -88,8 +88,8 @@ class webcam():
}
self.cam_settings_map = {
'white_balance_auto_preset': 'white_balance_temperature',
'white_balance_automatic': 'white_balance_automatic',
'auto_exposure':'auto_exposure',
'white_balance_automatic': 'white_balance_automatic',
'auto_exposure':'auto_exposure',
'anti_flicker' : 'power_line_frequency',
'lenspos' : 'sharpness',
}
@ -118,13 +118,13 @@ class webcam():
sys.exit()
def test_device(self, source):
self.cap = cv2.VideoCapture(source)
self.cap = cv2.VideoCapture(source)
if self.cap is None or not self.cap.isOpened():
print(_("Warning: unable to open video source: {}").format(source))
return False
self.cap.release()
return True
def capture_preview(self):
ret, overlay = self.cam.read()
if not ret:
@ -251,7 +251,7 @@ class picam():
# Map generic config name to specific picamera setting name
self.cam_settings_map = {
'white_balance_auto_preset': 'AwbMode',
'auto_exposure':'AeExposureMode',
'auto_exposure':'AeExposureMode',
'anti_flicker' : 'AeFlickerMode',
'lenspos' : 'LensPosition',
}
@ -270,48 +270,41 @@ class picam():
# Pi Cam V3 setup
self.Picamera2 = getattr(import_module('picamera2'), 'Picamera2')
self.Transform = getattr(import_module('libcamera'), 'Transform')
# ~ self.Picamera2 = __import__('picamera2.Picamera2')
# ~ self.Transform = __import__('libcamera.Transform')
# ~ from picamera2 import Picamera2
# ~ from libcamera import Transform
try:
self.cam = self.Picamera2()
self.picam_config = self.cam.create_video_configuration(main={"format": 'RGB888',"size": (camera_settings['cam_w'], camera_settings['cam_h'])})
# ~ picam_config["transform"] = Transform(hflip=camera_settings['hflip'], vflip=camera_settings['vflip'])
self.picam_config["transform"] = self.Transform(vflip=camera_current_settings['vertical_flip']['value'],hflip=camera_current_settings['horizontal_flip']['value'])
self.cam.configure(self.picam_config)
# Autofocus, get lens position and switch to manual mode
# Set Af mode to Auto then Manual (0). Default is Continuous (2), Auto is 1
self.cam.set_controls({'AfMode':1})
self.cam.start()
self.cam.autofocus_cycle()
self.lenspos = self.cam.capture_metadata()['LensPosition']
# Set focus, wb, exp to manual
self.camera_default_settings = {'AfMode': 0,
'AwbEnable': 1,
'AwbMode': self.camera_current_settings['white_balance_auto_preset']['default'],
'AeEnable': 1,
'AeExposureMode': self.camera_current_settings['auto_exposure']['default'],
# Enable flicker avoidance due to mains
'AeFlickerMode': 1,
# Mains 50hz = 10000, 60hz = 8333
# ~ 'AeFlickerPeriod': 8333,
'AeFlickerPeriod': 10000,
# Format is (min, max, default) in ms
# here: (60fps, 12fps, None)
# ~ 'FrameDurationLimits':(16666,83333,None)
}
self.cam.set_controls(self.camera_default_settings)
except:
pass
# Cam setup
self.cam = self.Picamera2()
self.picam_config = self.cam.create_video_configuration(main={"format": 'RGB888',"size": (camera_settings['cam_w'], camera_settings['cam_h'])})
self.picam_config["transform"] = self.Transform(vflip=self.camera_current_settings['vertical_flip']['value'],hflip=self.camera_current_settings['horizontal_flip']['value'])
self.cam.configure(self.picam_config)
# Autofocus, get lens position and switch to manual mode
# Set Af mode to Auto then Manual (0). Default is Continuous (2), Auto is 1
self.cam.set_controls({'AfMode':1})
self.cam.start()
self.cam.autofocus_cycle()
self.lenspos = self.cam.capture_metadata()['LensPosition']
# Set focus, wb, exp to manual
self.camera_default_settings = {'AfMode': 0,
'AwbEnable': 1,
'AwbMode': self.camera_current_settings['white_balance_auto_preset']['default'],
'AeEnable': 1,
'AeExposureMode': self.camera_current_settings['auto_exposure']['default'],
# Enable flicker avoidance due to mains
'AeFlickerMode': 1,
# Mains 50hz = 10000, 60hz = 8333
# ~ 'AeFlickerPeriod': 8333,
'AeFlickerPeriod': 10000,
# Format is (min, max, default) in ms
# here: (60fps, 12fps, None)
# ~ 'FrameDurationLimits':(16666,83333,None)
}
self.cam.set_controls(self.camera_default_settings)
def test_device(self, source):
pass
# Same as in webcam() class
def capture_preview(self):
overlay = cam.capture_array("main")
overlay = self.cam.capture_array("main")
# Resize preview to fit screen
overlay = cv2.resize(overlay, (project_settings['screen_w'], project_settings['screen_h']))
if self.liveview_only:
@ -328,7 +321,7 @@ class picam():
return True
self.frame = self.o_frame
return True
# Same as in webcam() class
def capture_frame(self, img_path):
if project_settings['file_extension'] == 'jpg':
@ -336,7 +329,7 @@ class picam():
else:
capture_ok = cv2.imwrite(img_path, self.og_frame)
return capture_ok
def increment_setting(self, setting:str):
if setting in self.camera_current_settings:
if self.camera_current_settings[setting]['value'] + self.camera_current_settings[setting]['step'] in range(self.camera_current_settings[setting]['min'],self.camera_current_settings[setting]['max']+1):
@ -356,21 +349,21 @@ class picam():
elif self.camera_current_settings['anti_flicker']['value'] == 1:
self.cam.set_controls({'AeFlickerMode': 1, 'AeFlickerPeriod':8333})
else:
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):
if to_set is not None:
for setting in to_set:
if inc:
self.increment_setting(setting)
self.cam.set_controls({self.cam_settings_map[setting] : self.camera_current_settings[setting]['value']})
def flip_image(self):
self.cam.stop()
self.picam_config["transform"] = self.Transform(vflip=self.camera_current_settings['vertical_flip']['value'],hflip=self.camera_current_settings['horizontal_flip']['value'])
self.cam.configure(self.picam_config)
self.cam.start()
def focus(self, direction:str='-'):
if direction == '+':
self.lenspos += 0.2
@ -379,11 +372,11 @@ class picam():
# Set AfMode to Manual
self.cam.set_controls({'AfMode': 0, 'LensPosition': self.lenspos})
print(_("-Lens pos: {}".format(self.lenspos)))
def reset_picture_settings(self):
for setting in self.camera_default_settings:
self.cam.set_controls({setting : self.camera_default_settings[setting]})
def close(self):
cam.close()
@ -393,8 +386,8 @@ class dslr():
# ~ import gphoto2 as gp
self.gp = import_module('gphoto2')
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
'imagesize' : dict(min=0, max=2, default=2, value=2), # 0:L, 1:M, 2: S (1936x1296)
'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)
'imagequality' : dict(min=0, max=2, default=2, value=2), # 0 JPEG basic 1 JPEG normal 2 JPEG fine 3 raw 4 raw+jpg
'whitebalance' : dict(min=0, max=7, default=2, value=1), # 0 Automatic 1 Daylight 2 Fluorescent 3 Tungsten 4 Flash 5 Cloudy 6 Shade 7 Preset
'capturetarget' : dict(min=0, max=1, default=0, value=0), # Internal memory
@ -405,7 +398,7 @@ class dslr():
# Map generic config name to specific picamera setting name
self.cam_settings_map = {
'white_balance_auto_preset': 'whitebalance',
'auto_exposure':'iso',
'auto_exposure':'iso',
'anti_flicker' : 'imagesize',
'lenspos' : 'shutterspeed',
}
@ -434,14 +427,14 @@ class dslr():
self.cam.exit()
self.camera = None
self.current_camera_config = None
def test_device(self, source):
pass
def capture_preview(self):
# TODO : check DSLR has preview/live feed
# TODO : check DSLR has preview/live feed
pass
def find_file_ext(self, gp_name:str, full_path:str):
# TODO: use re to sub png with jpg ?
# extract dir path
@ -455,7 +448,7 @@ class dslr():
prefix = new_name.split('.')[:-1]
prefix.insert(len(prefix), suffix)
return os.path.join(dirname, '.'.join(prefix))
def check_status_value(self, config, value, optimal_value=None):
cur_check = self.gp.check_result(self.gp.gp_widget_get_child_by_name(config, value))
cur_check_value = self.gp.check_result(self.gp.gp_widget_get_value(cur_check))
@ -464,7 +457,7 @@ class dslr():
return [cur_check_value, cur_check_choice]
else:
return cur_check_value
def capture_frame(self, img_path):
# CHECK: Should we init and close dslr for each frame ?
# Check battery level
@ -515,7 +508,7 @@ class dslr():
choices = list(self.gp.check_result(self.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
# 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))
@ -537,7 +530,7 @@ class dslr():
self.camera_current_settings[setting]['value'] += self.camera_current_settings[setting]['step']
else:
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['min']
def apply_setting(self, to_set:list=None, inc:bool=False):
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
# iterate over the settings dictionary
@ -559,13 +552,13 @@ class dslr():
# close camera
# ~ self.cam.exit()
return status
def flip_image(self):
self.frame = cv2.flip(self.frame, -1)
def focus(self, direction:str='-'):
self.apply_setting(['shutterspeed'], True)
def reset_picture_settings(self):
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
for setting in self.camera_current_settings:
@ -573,7 +566,7 @@ class dslr():
# TODO: use self.apply_setting() instead
self.apply_gphoto_setting(setting)
status = self.gp.check_result(self.gp.gp_camera_set_config(self.cam, self.camera_current_config))
def close(self):
self.cam.exit()
@ -812,7 +805,7 @@ def update_image(img_list, img_index):
def next_frame(img_index, loop=True):
img_index = check_range(img_index+1, loop)
return img_index, update_image(img_list, img_index)
def previous_frame(img_index):
img_index = check_range(img_index-1)
@ -854,7 +847,7 @@ def check_range(x, loop=True):
return x
def batch_rename(folder:str):
def batch_rename(folder:str):
# initialize counter to 0
frame_list = get_frames_list(folder)
counter = (".%04i." % x for x in count(0))
@ -900,7 +893,7 @@ def remove_frame(img_list, img_index):
def testDevice(source):
cap = cv2.VideoCapture(source)
cap = cv2.VideoCapture(source)
if cap is None or not cap.isOpened():
print(_("Warning: unable to open video source: {}").format(source))
return False
@ -929,7 +922,7 @@ def export_animation(input_filename, export_filename):
project_settings['ffmpeg_path'],
'-v','quiet',
'-y',
'-f', input_format,
'-f', input_format,
'-r', framerate,
'-i', input_filename,
'-vf', output_options,
@ -953,19 +946,19 @@ if cam is None:
def main(args):
global img_list
playback = False
first_playback = True
playhead = 0
loop_playback = True
index = len(img_list)-1
playhead = index
cam.apply_setting()
cam.frame = get_onionskin_frame(savepath)
cam.o_frame = cam.frame.copy()
loop_delta = 0
while True:
start = timer()
@ -1028,7 +1021,7 @@ def main(args):
# Key up, kp 8
elif (k%256 == 82) or (k%256 == 56) or (k%256 == 184):
print(_("Last frame"))
if len(img_list):
if len(img_list):
if playback:
playback = False
index, frame = last_frame(index)
@ -1036,7 +1029,7 @@ def main(args):
# Key down , kp 2
elif (k%256 == 84) or (k%256 == 50) or (k%256 == 178):
print(_("First frame"))
if len(img_list):
if len(img_list):
if playback:
playback = False
index, frame = first_frame(index)
@ -1096,7 +1089,7 @@ def main(args):
img_name = return_next_frame_number(get_last_frame(savepath))
img_path = os.path.join(savepath, img_name)
capture_ok = cam.capture_frame(img_path)
print(_("File {} written.").format(img_path))
print(_("File {} written.").format(img_path))
# Special case when we've no frame yet
if len(img_list) and (img_list[index] == '{letter}.-001.{ext}'.format(letter=project_letter, ext=project_settings['file_extension'])):
img_list[index] = img_name

View File

@ -2,14 +2,14 @@
## Branche gphoto / réflexe nunmérique
**Ceci est la branche qui restaure la possibilité d'utiliser des périphériques compatibles [gphoto](http://gphoto.org/doc/remote).**
**Ceci est la branche qui restaure la possibilité d'utiliser des périphériques compatibles [gphoto](http://gphoto.org/doc/remote).**
<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/>
Seconde version du script python [stopi](https://git.arthus.net/arthus/stopi) destiné à être utilisé avec une télécommande [picote](/arthus/picote/src/branch/picamera).
Cette version utilise opencv et libcamera.Elle fonctionne avec une webcam ou un module vidéo Picamera (v1,v2 ou v3).
Encore une fois, l'objectif est de créer un logiciel simple et minimaliste dans son interface, dont les caractéristiques sont les suivantes :
Seconde version du script python [stopi](https://git.arthus.net/arthus/stopi) destiné à être utilisé avec une télécommande [picote](/arthus/picote/src/branch/picamera).
Cette version utilise opencv et libcamera.Elle fonctionne avec une webcam ou un module vidéo Picamera (v1,v2 ou v3).
Encore une fois, l'objectif est de créer un logiciel simple et minimaliste dans son interface, dont les caractéristiques sont les suivantes :
* Affichage des images en plein écran sans interface : toutes les fonctions utilisent quelques touches du clavier.
* [Pelure d'oignon](https://fr.wikipedia.org/wiki/Pelure_d'oignon#Sciences_et_techniques) entre la dernière image et le flux vidéo.
@ -22,14 +22,14 @@ Encore une fois, l'objectif est de créer un logiciel simple et minimaliste dans
## 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) | | | &check; | | |
| PC Linux (Debian, Manjaro) | &check; | &check; | N/A | N/A | &check; |
| 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) | | | &check; | | |
| PC Linux (Debian, Manjaro) | &check; | &check; | N/A | N/A | &check; |
## Feuille de route
@ -39,22 +39,22 @@ Des fonctions supplémentaires sont prévues :
## Contributions
Les contributions et rapports de bugs sont les bienvenus !
Les contributions et rapports de bugs sont les bienvenus !
## Installation
Dans un terminal :
Dans un terminal :
0. (Utilisateurs Windows) Activer le [sous système Linux **version 2** (WSL2)](https://learn.microsoft.com/fr-fr/windows/wsl/install) et installer Debian.
1. Installer les dépendances suivantes :
1. Installer les dépendances suivantes :
```
# 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 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
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`
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`.
5. Activer l'environnement virtuel avec `source bin/activate`
@ -64,26 +64,26 @@ Dans un terminal :
## Fonction par touches
L'idéal est d'utiliser une télécommande [picote](/arthus/picote) mais le logiciel est aussi pilotable via un clavier/clavier numérique.
L'idéal est d'utiliser une télécommande [picote](/arthus/picote) mais le logiciel est aussi pilotable via un clavier/clavier numérique.
| Fonction | Boutton | Clavier |
| --- | --- | --- |
| Capturer une image | 🟢 | touche Espace ou 0 sur le clavier numérique |
| Supprimer une image | 🔴 | touche Suppr, touche Backspace ou touche - sur le clavier numérique |
| Lecture de l'animation | Alt + 🟢 | touches Entrée |
| Exporter l'animation | Alt + 🔴 | touche E ou * sur le clavier numérique |
| Image suivante | 🔵 | touche flèche droite ou 6 sur le clavier numérique |
| Image précédente | 🟡 | touche flèche gauche ou 4 sur le clavier numérique |
| Aller à la dernière image | Alt + 🔵| touche flèche bas ou 2 sur le clavier numérique |
| Aller à la première image | Alt + 🟡 | touche flèche haut ou 8 sur le clavier numérique |
| Activer/Désactiver onionskin | ⚫ | touche O ou / sur le clavier numérique |
| Quitter le logiciel | n/a | touche Échap, Alt-F4 ou Ctrl-C |
| Capturer une image | 🟢 | touche Espace ou 0 sur le clavier numérique |
| Supprimer une image | 🔴 | touche Suppr, touche Backspace ou touche - sur le clavier numérique |
| Lecture de l'animation | Alt + 🟢 | touches Entrée |
| Exporter l'animation | Alt + 🔴 | touche E ou * sur le clavier numérique |
| Image suivante | 🔵 | touche flèche droite ou 6 sur le clavier numérique |
| Image précédente | 🟡 | touche flèche gauche ou 4 sur le clavier numérique |
| Aller à la dernière image | Alt + 🔵| touche flèche bas ou 2 sur le clavier numérique |
| Aller à la première image | Alt + 🟡 | touche flèche haut ou 8 sur le clavier numérique |
| Activer/Désactiver onionskin | ⚫ | touche O ou / sur le clavier numérique |
| Quitter le logiciel | n/a | touche Échap, Alt-F4 ou Ctrl-C |
| **Réglages de la caméra (compatible showmewebcam seulement)** | | |
| Réinitialiser la caméra | Alt + ⚫ | touche R ou 9 sur le clavier numérique |
| Changer le mode de balance des blancs | ① | touche W ou 7 sur le clavier numérique |
| Changer le mode d'exposition | Alt + ① | touche X ou 1 sur le clavier numérique |
| Afficher seulement le flux vidéo | ② | touche L ou 3 sur le clavier numérique |
| Rotation de 180° de la capture vidéo | Alt + ② | touche F ou 5 sur le clavier numérique |
| Réinitialiser la caméra | Alt + ⚫ | touche R ou 9 sur le clavier numérique |
| Changer le mode de balance des blancs | ① | touche W ou 7 sur le clavier numérique |
| Changer le mode d'exposition | Alt + ① | touche X ou 1 sur le clavier numérique |
| Afficher seulement le flux vidéo | ② | touche L ou 3 sur le clavier numérique |
| Rotation de 180° de la capture vidéo | Alt + ② | touche F ou 5 sur le clavier numérique |
## Installation Kiosque
@ -94,7 +94,7 @@ Pour créer un kiosque d'animation à partir d'une installation minimale de Debi
2. Suivre les [étapes d'installation](#installation) ci-dessus.
3. Activer le login automatique de votre utilisateur au démarrage :
```
sudo systemctl edit getty@tty1.service
sudo systemctl edit getty@tty1.service
# Ajout du contenu suivant dans le fichier créé:
[Service]
ExecStart=
@ -132,7 +132,7 @@ unclutter -idle 0.2 &
/home/$USER/stopi2.sh &
```
Au redémarrage, la session graphique devrait démarrer automatiquement.
Au redémarrage, la session graphique devrait démarrer automatiquement.
# Démarrage 'silencieux'
@ -147,13 +147,13 @@ et modifier la ligne :
en :
`GRUB_CMDLINE_LINUX_DEFAULT="quiet splash loglevel=3`
Puis configurer plymouth : `sudo plymouth-set-default-theme`
Puis configurer plymouth : `sudo plymouth-set-default-theme`
Appliquer les modifs avec `sudo update-grub`.
Appliquer les modifs avec `sudo update-grub`.
## Raspberry Pi OS
Avec Raspberry Pi OS, il suffit d'ajouter les options suivantes dans '/boot/firmware/cmdline.txt':
`loglevel=3 vt.global_cursor_default=0 logo.nologo consoleblank=3 quiet`
``
``

View File

@ -16,11 +16,11 @@ def send_serial_cmd(cam_port, cmd:str, clear=True):
append = b'\r'
con.write(str.encode(cmd) + append)
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())
sys.exit(main())