Picamera2 support

This commit is contained in:
ABelliqueux 2024-02-26 18:32:18 +01:00
parent bf156cb6e2
commit b6cf074362
2 changed files with 65 additions and 29 deletions

View File

@ -1,4 +1,5 @@
[DEFAULT]
camera_type = 0
file_extension = 'JPG'
trigger_mode = 'key'
projects_folder = ''

View File

@ -30,7 +30,7 @@ from io import BytesIO
from itertools import count
import locale
import os
from PIL import Image, ImageTk, ImageFilter, ImageDraw, ImageFont
from PIL import Image, ImageTk, ImageFilter, ImageDraw, ImageOps, ImageFont
import sys
import threading
import time
@ -73,6 +73,8 @@ _ = gettext.translation('template', localedir='locales', languages=[LOCALE]).get
# Config
# defaults
project_settings_defaults = {
# DSLR = 0, picam = 1, webcam = 2
'camera_type': 0,
'file_extension':'JPG',
'trigger_mode': 'key',
'projects_folder': '',
@ -103,7 +105,7 @@ for location in config_locations:
with open(os.path.expanduser(location + 'config.toml'), 'rb') as config_file:
project_settings = tomllib.load(config_file)
if 'CHECK' in project_settings:
camera_settings = project_settings['CHECK']
camera_status = project_settings['CHECK']
if 'CAMERA' in project_settings:
camera_settings = project_settings['CAMERA']
if 'DEFAULT' in project_settings:
@ -115,6 +117,8 @@ class KISStopmo(tk.Tk):
def __init__(self, *args, **kargs):
self.check_config()
if project_settings['camera_type']:
from picamera2 import Picamera2
# Default config
# Set script settings according to config file
self.onion_skin = project_settings['onion_skin_onstartup']
@ -157,16 +161,36 @@ class KISStopmo(tk.Tk):
self.img_index = self.check_range(len(self.img_list)-1, False)
self.splash_text = _("No images yet! Start shooting...")
# Camera setup
self.camera = gp.check_result(gp.gp_camera_new())
try:
gp.check_result(gp.gp_camera_init(self.camera))
# get configuration tree
self.current_camera_config = gp.check_result(gp.gp_camera_get_config(self.camera))
self.apply_camera_settings(self.camera, self.current_camera_config)
if self.check_status(self.camera, self.current_camera_config) is False:
print(_("Warning: Some settings are not set to the recommended value!"))
except:
self.splash_text += _("\nCamera not found or busy.")
if project_settings['camera_type'] != 0:
try:
self.camera = Picamera2()
self.picam_conf_full = self.camera.create_still_configuration(main={"size":(1920,1080)}, lores={"size":(800,600)})
self.camera.configure(self.picam_conf_full)
# Autofocus, get lens position and switch to manual mode
# Set Af mode to Manual (1). Default is Continuous (2), Auto is 1
# TODO: lock exposure, wb
self.camera.set_controls({'AfMode':1})
self.camera.start(show_preview=False)
self.camera.autofocus_cycle()
self.camera_lenspos = self.camera.capture_metadata()['LensPosition']
self.camera.set_controls({'AfMode':0, 'AwbEnable': False, 'AeEnable': False})
self.camera.stop()
except:
self.camera = False
self.splash_text += _("\nCamera not found or busy.")
else:
self.camera = gp.check_result(gp.gp_camera_new())
try:
gp.check_result(gp.gp_camera_init(self.camera))
# get configuration tree
self.current_camera_config = gp.check_result(gp.gp_camera_get_config(self.camera))
self.apply_camera_settings(self.camera, self.current_camera_config)
if self.check_status(self.camera, self.current_camera_config) is False:
print(_("Warning: Some settings are not set to the recommended value!"))
except:
self.camera = False
self.splash_text += _("\nCamera not found or busy.")
self.timeout = 3000 # milliseconds
@ -200,8 +224,8 @@ class KISStopmo(tk.Tk):
if project_settings['trigger_mode'] != 'event':
root.bind("<j>", self.capture_image)
def check_config(self):
global project_settings
for setting in project_settings_defaults:
@ -414,7 +438,8 @@ class KISStopmo(tk.Tk):
# ~ image = Image.open(filepath)
# ~ print( filetuple[0] + "is not in cache")
image = Image.open(os.path.join(self.savepath, filetuple[0]))
image = image.resize((w, h))
# ~ image = image.resize((w, h),reducing_gap=1.5)
image = ImageOps.fit(image, (w, h))
if vflip:
image = image.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
if hflip:
@ -465,6 +490,7 @@ class KISStopmo(tk.Tk):
def update_image(self, event=None, index=None):
# TODO : check event mode stille works
if event is not None:
self.img_index = self.check_range(self.img_index+1)
if index is None:
@ -639,20 +665,25 @@ class KISStopmo(tk.Tk):
next_filename = self.return_next_frame_number(self.get_last_frame(self.savepath))
# build full path to file
target_path = os.path.join(self.savepath, next_filename)
# ~ print(target_path)
# Get file from camera
if event_data is None:
# ~ print("j pressed")
new_frame_path = self.camera.capture(gp.GP_CAPTURE_IMAGE)
# ~ self.camera.trigger_capture()
new_frame = self.camera.file_get(
new_frame_path.folder, new_frame_path.name, gp.GP_FILE_TYPE_NORMAL)
print(_("Saving {}{}").format(new_frame_path.folder, new_frame_path.name))
if project_settings['camera_type']:
self.camera.start(show_preview=False)
self.camera.set_controls({"LensPosition": self.camera_lenspos})
self.camera.capture_file(target_path, 'main', format='jpeg')
self.camera.stop()
else:
print(_("Getting file {}").format(event_data.name))
new_frame = self.camera.file_get(
event_data.folder, event_data.name, gp.GP_FILE_TYPE_NORMAL)
new_frame.save(target_path)
# Get file from DSLR camera
if event_data is None:
# ~ print("j pressed")
new_frame_path = self.camera.capture(gp.GP_CAPTURE_IMAGE)
# ~ self.camera.trigger_capture()
new_frame = self.camera.file_get(
new_frame_path.folder, new_frame_path.name, gp.GP_FILE_TYPE_NORMAL)
print(_("Saving {}{}").format(new_frame_path.folder, new_frame_path.name))
else:
print(_("Getting file {}").format(event_data.name))
new_frame = self.camera.file_get(
event_data.folder, event_data.name, gp.GP_FILE_TYPE_NORMAL)
new_frame.save(target_path)
# ~ next_filename = prefix+next(filename)+ext
# ~ print(self.img_list)
if '{letter}.-001.JPG'.format(letter=self.project_letter) in self.img_list:
@ -698,7 +729,11 @@ class KISStopmo(tk.Tk):
# check with self.export_task.done() == True ? https://stackoverflow.com/questions/69350645/proper-way-to-retrieve-the-result-of-tasks-in-asyncio
def end_bg_loop(KISStopmo):
KISStopmo.camera.exit()
if KISStopmo.camera is not False:
if project_settings['camera_type']:
KISStopmo.camera.stop()
else:
KISStopmo.camera.exit()
KISStopmo.end_thread = True
root = tk.Tk()