From 2e4238fc60206fdc035b41e3910404cebe5b0608 Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Mon, 18 Nov 2024 09:49:22 +0100 Subject: [PATCH] Easy testing with or without dark room setup --- .gitignore | 3 ++ __init__.py | 2 +- camera.py | 58 ++++++++++++++++++++++++++++++++++++++ config.darkroom.py | 14 ++++++++++ config.local.py | 14 ++++++++++ config.py | 28 ------------------- leds.py | 60 +++++++++++++++++++++++++++++++++------ requirements.txt | 3 +- scanner.py | 65 ++++++++----------------------------------- templates/object.html | 2 +- templates/scan.html | 2 +- 11 files changed, 156 insertions(+), 95 deletions(-) create mode 100644 camera.py create mode 100644 config.darkroom.py create mode 100644 config.local.py delete mode 100644 config.py diff --git a/.gitignore b/.gitignore index 2a054fe..6517bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Config file +config.py + .device data data-* diff --git a/__init__.py b/__init__.py index 175437f..699b2cd 100644 --- a/__init__.py +++ b/__init__.py @@ -25,7 +25,7 @@ def inject(): conn = db.get() return { 'calibration': utils.get_calibration(conn), - 'leds': config.LEDS_UUIDS, + 'leds': config.GPIO_LEDS.leds, 'CalibrationState': db.CalibrationState, } diff --git a/camera.py b/camera.py new file mode 100644 index 0000000..bec4ce1 --- /dev/null +++ b/camera.py @@ -0,0 +1,58 @@ +import gphoto2 as gp +import shutil +from . import leds + + +class Camera: + def __init__(self): + self.inner = gp.Camera() + + def __enter__(self): + self.inner.init() + + def __exit__(self): + self.inner.exit() + + def capture(self, output_path: str) -> bool: + try: + with self: + file_path = self.inner.capture(gp.GP_CAPTURE_IMAGE) + preview = self.inner.file_get(file_path.folder, file_path.name[:-3] + '.JPG', gp.GP_FILE_TYPE_NORMAL) + raw = self.inner.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_RAW) + + preview.sve(output_path + '.jpg') + raw.save(output_path + '.cr2') + return True + + except Exception as e: + print('An error occured when capturing photo', e) + return False + + +class DummyCamera: + def __init__(self, leds: leds.DummyLeds): + self.leds = leds + + def __enter__(self): + pass + + def __exit__(self): + pass + + def capture(self, output_path: str) -> bool: + # Find which leds are turned on + found = None + all_on = False + for led in self.leds.leds: + if led.is_on: + if found is None: + found = led + else: + all_on = True + + if found: + shutil.copyfile('data-keep/small/' + str(found) + '.jpg', output_path + '.jpg') + elif all_on: + shutil.copyfile('data-keep/small/LED17.jpg', output_path + '.jpg') + else: + shutil.copyfile('data-keep/small/LED17.jpg', output_path + '.jpg') diff --git a/config.darkroom.py b/config.darkroom.py new file mode 100644 index 0000000..09ca3b1 --- /dev/null +++ b/config.darkroom.py @@ -0,0 +1,14 @@ +from os.path import join +from . import camera, leds + +DATA_DIR = 'data' +BACKUPS_DIR = 'data-backups' +CALIBRATION_DIR = join(DATA_DIR, 'calibrations') +OBJECT_DIR = join(DATA_DIR, 'objects') +DATABASE_PATH = join(DATA_DIR, 'db.sqlite') + +AUTO_USE_LAST_CALIBRATION = True +GPIO_CHIP = 'gpiochip0' +LEDS_UUIDS = [17, 18, 22, 23, 24, 27] +GPIO_LEDS = leds.GpioLeds(LEDS_UUIDS) +CAMERA = camera.Camera() diff --git a/config.local.py b/config.local.py new file mode 100644 index 0000000..d0ed701 --- /dev/null +++ b/config.local.py @@ -0,0 +1,14 @@ +from os.path import join +from . import camera, leds + +DATA_DIR = 'data' +BACKUPS_DIR = 'data-backups' +CALIBRATION_DIR = join(DATA_DIR, 'calibrations') +OBJECT_DIR = join(DATA_DIR, 'objects') +DATABASE_PATH = join(DATA_DIR, 'db.sqlite') + +AUTO_USE_LAST_CALIBRATION = False +GPIO_CHIP = None +LEDS_UUIDS = [17, 18, 22, 23, 24, 27] +GPIO_LEDS = leds.DummyLeds(LEDS_UUIDS) +CAMERA = camera.DummyCamera(GPIO_LEDS) diff --git a/config.py b/config.py deleted file mode 100644 index 6760501..0000000 --- a/config.py +++ /dev/null @@ -1,28 +0,0 @@ -from os.path import join - -DATA_DIR = 'data' -BACKUPS_DIR = 'data-backups' -CALIBRATION_DIR = join(DATA_DIR, 'calibrations') -OBJECT_DIR = join(DATA_DIR, 'objects') -DATABASE_PATH = join(DATA_DIR, 'db.sqlite') - -AUTO_USE_LAST_CALIBRATION = False - -GPIO_CHIP = 'gpiochip0' - -# LEDS_UUIDS = [ -# 'ac59350e-3787-46d2-88fa-743c1d34fe86', -# '83ab3133-d4de-4a42-99a7-8f8a3f3732ba', -# '577d6e72-f518-4d65-af28-f8faf1ca3f5d', -# 'ec49a20c-bddd-4614-b828-fa45e01bfb19', -# '5c249cce-d2b6-4b56-96c8-5caa43d8f040', -# '22d783fb-ae55-4581-a3c6-e010d9d5e9de', -# '12cb6a32-04a6-433b-8146-b753b8f1286d', -# '461255a3-259a-4291-adc3-2fb736231a04', -# '3896662f-9826-4445-ad70-86c2e6c143e7', -# 'f87698ec-3cba-42fe-9a61-5ac9f77d767a', -# '4c77a655-4b68-4557-a696-29345c6676a1', -# 'b1cfe287-aa3b-445e-bcdc-75ae375efe43', -# ] - -LEDS_UUIDS = [17, 18, 22, 23, 24, 27] diff --git a/leds.py b/leds.py index b8f47e5..54ecd09 100644 --- a/leds.py +++ b/leds.py @@ -1,20 +1,17 @@ import gpiod -from . import config class GpioLed: - chip = gpiod.Chip(config.GPIO_CHIP) - def __init__(self, gpio_pin: int): self.gpio_pin = gpio_pin self.led = None - def __enter__(self): - self.led = GpioLed.chip.get_line(self.gpio_pin) + def enter(self, chip: gpiod.Chip): + self.led = chip.get_line(self.gpio_pin) self.led.request(consumer=str(self), type=gpiod.LINE_REQ_DIR_OUT) self.off() - def __exit__(self, *args): + def exit(self): self.off() self.led.release() self.led = None @@ -30,18 +27,63 @@ class GpioLed: class GpioLeds: - def __init__(self, gpio_pins: list[int]): + def __init__(self, chip: str, gpio_pins: list[int]): + self.chip = gpiod.Chip(chip) self.leds = [] for pin in gpio_pins: self.leds.append(GpioLed(pin)) def __enter__(self): for led in self.leds: - led.__enter__() + led.enter(self.chip) def __exit__(self, *args): for led in self.leds: - led.__exit__(*args) + led.exit() + + def off(self): + for led in self.leds: + led.off() + + def on(self): + for led in self.leds: + led.on() + + +class DummyLed: + def __init__(self, gpio_pin: int): + self.gpio_pin = gpio_pin + self.is_on = False + + def enter(self): + pass + + def exit(self): + pass + + def on(self): + self.is_on = True + + def off(self): + self.is_on = False + + def __str__(self): + return f'LED{self.gpio_pin:02}' + + +class DummyLeds: + def __init__(self, gpio_pins: list[int]): + self.leds = [] + for pin in gpio_pins: + self.leds.append(DummyLed(pin)) + + def __enter__(self): + for led in self.leds: + led.enter() + + def __exit__(self, *args): + for led in self.leds: + led.exit() def off(self): for led in self.leds: diff --git a/requirements.txt b/requirements.txt index 1dacac3..eb2089e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ Flask pillow -opencv-python gphoto2 scipy -lgpio +gpiod diff --git a/scanner.py b/scanner.py index 0697de4..5ecd274 100644 --- a/scanner.py +++ b/scanner.py @@ -1,51 +1,17 @@ -import cv2 import os from os.path import join -import subprocess -import shutil import time -import gphoto2 as gp -import gpiod -from . import config, leds +from . import config # Delay between to captures DELAY = 0.5 -def capture(camera, output_path: str) -> bool: - try: - print('Capturing image') - file_path = camera.capture(gp.GP_CAPTURE_IMAGE) - print('Camera file path: {0}/{1}'.format(file_path.folder, file_path.name)) - target = output_path + '.cr2' - print('Copying image to', target) - print(file_path.folder, file_path.name[:-3] + 'JPG') - camera_file_jpg = camera.file_get(file_path.folder, file_path.name[:-3] + 'JPG', gp.GP_FILE_TYPE_NORMAL) - camera_file_jpg.save(output_path + '.jpg') - - camera_file_raw = camera.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_RAW) - camera_file_raw.save(target) - - camera.exit() - camera.init() - s = True - - except Exception as e: - print(f'Somethings wrong on gphoto2') - print(e) - s = False - - return s - def scan(output_dir: str): - camera = gp.Camera() - camera.init() - os.makedirs(output_dir, exist_ok=True) - gpio_leds = leds.GpioLeds(config.LEDS_UUIDS) - with gpio_leds: - for count, led in enumerate(gpio_leds.leds): + with config.GPIO_LEDS: + for count, led in enumerate(config.GPIO_LEDS.leds): print(f'Turn on {led}') img = join(output_dir, f'{led}') @@ -53,11 +19,8 @@ def scan(output_dir: str): start = time.time() led.on() - capture(camera, img) + config.CAMERA.capture(img) led.off() - - # For debug purposes - # shutil.copyfile(join('data-keep/small', led + '.jpg'), img) delta = time.time() - start @@ -65,19 +28,15 @@ def scan(output_dir: str): if delta < DELAY: time.sleep(DELAY - delta) - print(f'Turn off {led}') - if count == len(config.LEDS_UUIDS) -1: - + print(f'Turn off {led}') + if count == len(config.LEDS_UUIDS) - 1: # capture with all leds ON OFF - gpio_leds.on() - img = join(output_dir, f'all_on') - capture(camera, img) + config.GPIO_LEDS.on() + img = join(output_dir, 'all_on') + config.CAMERA.capture(img) - gpio_leds.off() - img = join(output_dir, f'all_off') - capture(camera, img) - - camera.exit() + config.GPIO_LEDS.off() + img = join(output_dir, 'all_off') + config.CAMERA.capture(img) yield led - diff --git a/templates/object.html b/templates/object.html index e3fc765..99e48fb 100644 --- a/templates/object.html +++ b/templates/object.html @@ -70,7 +70,7 @@
Voulez-vous vraiment supprimer l'objet ?
-
Supprimer cet objet diff --git a/templates/scan.html b/templates/scan.html index df23253..303d5ba 100644 --- a/templates/scan.html +++ b/templates/scan.html @@ -50,7 +50,7 @@
Voulez-vous vraiment supprimer l'acquisition ?
-