Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"exifread",
"rawpy",
"opencv-python",
"hachoir"
]


Expand Down
26 changes: 20 additions & 6 deletions ledsa/core/ConfigData.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import configparser as cp
from datetime import datetime, timedelta

Expand Down Expand Up @@ -271,10 +272,15 @@ def in_time_diff_to_img_time(self) -> None:
time = input('Please give the time shown on the clock in the time reference image in hh:mm:ss: ')
self['DEFAULT']['time_ref_img_time'] = str(time)
time = self['DEFAULT']['time_ref_img_time']
print(self['DEFAULT']['img_directory'] + self['DEFAULT']['time_img_id'])
tag = 'EXIF DateTimeOriginal'
exif_entry = get_exif_entry(self['DEFAULT']['img_directory'] + self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['time_img_id']), tag)
print(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['time_img_id'])))
if '.CR3' in os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['time_img_id'])):
tag = 'Creation date'
else:
tag = 'EXIF DateTimeOriginal'
exif_entry = get_exif_entry(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['time_img_id'])), tag)
date, time_meta = exif_entry.split(' ')
self['DEFAULT']['date'] = date
img_time = _get_datetime_from_str(date, time_meta)
Expand Down Expand Up @@ -351,8 +357,13 @@ def get_start_time(self) -> None:
Updates the 'DEFAULT' key with the 'start_time' computed.

"""
exif_entry = get_exif_entry(self['DEFAULT']['img_directory'] + self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['first_img_experiment_id']), 'EXIF DateTimeOriginal')
if '.CR3' in os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['first_img_experiment_id'])):
tag = 'Creation date'
else:
tag = 'EXIF DateTimeOriginal'
exif_entry = get_exif_entry(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format(
self['DEFAULT']['first_img_experiment_id'])), tag)
date, time_meta = exif_entry.split(' ')
time_img = _get_datetime_from_str(date, time_meta)
start_time = time_img - timedelta(seconds=self['DEFAULT'].getint('exif_time_infront_real_time'))
Expand All @@ -366,6 +377,7 @@ def _get_datetime_from_str(date: str, time: str) -> datetime:
The function can handle two formats:
1. '%Y:%m:%d %H:%M:%S' - standard format with colons in the date.
2. '%d.%m.%Y %H:%M:%S' - format with periods in the date.
3. '%d-%m-%Y %H:%M:%S' - format with hyphens in the date.

:param date: The date string.
:type date: str
Expand All @@ -376,6 +388,8 @@ def _get_datetime_from_str(date: str, time: str) -> datetime:
"""
if date.find(":") != -1:
date_time = datetime.strptime(date + ' ' + time, '%Y:%m:%d %H:%M:%S')
elif date.find("-") != -1:
date_time = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S')
else:
date_time = datetime.strptime(date + ' ' + time, '%d.%m.%Y %H:%M:%S')
return date_time
Expand Down
25 changes: 23 additions & 2 deletions ledsa/core/image_reading.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os

from hachoir.parser import createParser
from hachoir.metadata import extractMetadata
from pathlib import Path
import exifread
import numpy as np
import rawpy
Expand All @@ -22,7 +24,7 @@ def read_channel_data_from_img(filename: str, channel: int) -> np.ndarray:
extension = os.path.splitext(filename)[-1]
if extension in ['.JPG', '.JPEG', '.jpg', '.jpeg', '.PNG', '.png']:
channel_array = _read_channel_data_from_img_file(filename, channel)
elif extension in ['.CR2']:
elif extension in ['.CR2','.CR3','.NEF','.ARW','.DNG']:
channel_array = _read_channel_data_from_raw_file(filename, channel)
return channel_array

Expand Down Expand Up @@ -91,6 +93,25 @@ def get_exif_entry(filename: str, tag: str) -> str:
:rtype: str
:raises KeyError: If the EXIF tag is not found in the image metadata.
"""

#Read Metadata CR3 (! ISO, Blende und Verschlusszeit kann durch diese Methode nicht ausgegeben werden)
if '.CR3' in filename:
parser = createParser(str(filename))
if not parser:
raise ValueError(f"Konnte Datei nicht parsen: {filename}")

metadata = extractMetadata(parser)
if not metadata:
raise ValueError("Keine Metadaten gefunden.")

try:
for line in metadata.exportPlaintext():
if tag in line:
return line.split(":", 1)[1].strip()
except:
print("Keine Aufnahmezeit gefunden.")
exit(1)

with open(filename, 'rb') as f:
exif = exifread.process_file(f, details=False, stop_tag=tag)
try:
Expand Down
17 changes: 11 additions & 6 deletions ledsa/data_extraction/init_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def generate_image_infos_csv(config: ConfigData, build_experiment_infos=False, b
_save_analysis_infos(img_data)


def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str, img_number: int) -> None:
def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str, img_number: str) -> None:
"""
Calculate experiment and real-time based on image metadata and config settings.

Expand All @@ -107,8 +107,8 @@ def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str
:return: Tuple containing experiment time and real time.
:rtype: tuple
"""
exif_entry = get_exif_entry(config['DEFAULT']['img_directory'] +
config['DEFAULT']['img_name_string'].format(int(img_number)), tag)
exif_entry = get_exif_entry(os.path.join(config['DEFAULT']['img_directory'],
config['DEFAULT']['img_name_string'].format(img_number)), tag)
date, time_meta = exif_entry.split(' ')
date_time_img = _get_datetime_from_str(date, time_meta)

Expand All @@ -125,7 +125,7 @@ def _get_datetime_from_str(date: str, time: str) -> datetime:
"""
Convert date and time strings to a datetime object.

:param date: Date string in the format '%Y:%m:%d' or '%d.%m.%Y'.
:param date: Date string in the format '%Y:%m:%d' or '%d.%m.%Y' or '%Y-%m-%d'.
:type date: str
:param time: Time string in the format '%H:%M:%S'.
:type time: str
Expand All @@ -134,6 +134,8 @@ def _get_datetime_from_str(date: str, time: str) -> datetime:
"""
if date.find(":") != -1:
date_time = datetime.strptime(date + ' ' + time, '%Y:%m:%d %H:%M:%S')
elif date.find("-") != -1:
date_time = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S')
else:
date_time = datetime.strptime(date + ' ' + time, '%d.%m.%Y %H:%M:%S')
return date_time
Expand Down Expand Up @@ -193,9 +195,12 @@ def _build_img_data_string(build_type: str, config: ConfigData) -> str:
img_increment = config.getint(build_type, 'num_skip_imgs') + 1 if build_type == 'analyse_photo' else 1
img_id_list = _find_img_number_list(first_img_id, last_img_id, img_increment)
for img_id in img_id_list:
tag = 'EXIF DateTimeOriginal'
if '.CR3' in config['DEFAULT']['img_name_string']:
tag = 'Creation date'
else:
tag = 'EXIF DateTimeOriginal'
experiment_time, time = _calc_experiment_and_real_time(build_type, config, tag, img_id)
img_data += (str(img_idx) + ',' + config[build_type]['img_name_string'].format(int(img_id)) +
img_data += (str(img_idx) + ',' + config[build_type]['img_name_string'].format(img_id) +
',' + time.strftime('%H:%M:%S') + ',' + str(experiment_time) + '\n')
img_idx += 1
return img_data
Expand Down
2 changes: 1 addition & 1 deletion ledsa/data_extraction/step_3_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def generate_analysis_data(img_filename: str, channel: int, search_areas: np.nda
return img_analysis_data


def create_fit_result_file(img_data: List[LEDAnalysisData], img_id: int, channel: int) -> None: # TODO: rename because misleading
def create_fit_result_file(img_data: List[LEDAnalysisData], img_id: str, channel: int) -> None: # TODO: rename because misleading
"""
Create a result file for a single image, containing the pixel values and, if applicable, the fit results of all LEDs.

Expand Down
64 changes: 38 additions & 26 deletions ledsa/tools/exposure_checker.ipynb
Original file line number Diff line number Diff line change
@@ -1,64 +1,73 @@
{
"cells": [
{
"metadata": {},
"cell_type": "markdown",
"id": "d5b8be1e27d27315",
"metadata": {},
"source": [
"# Image Exposure Checker\n",
"\n",
"This notebook allows you to check the exposure of a series of pictures. It calculates the pixel saturation value as a percentage.\n"
],
"id": "d5b8be1e27d27315"
"This notebook allows you to check the exposure of a series of pictures. It calculates the pixel saturation value as a percentage.\n",
"\n",
"Does not work for Images in CR3 format.\n"
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Dependencies\n",
"id": "9df8a44a552be70"
"id": "9df8a44a552be70",
"metadata": {},
"source": [
"# Dependencies\n"
]
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"id": "41c98f47ba1f266f",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from ledsa.core.image_reading import read_channel_data_from_img, get_exif_entry"
],
"id": "41c98f47ba1f266f"
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Configuration\n",
"id": "8bab111a65dd1b89"
"id": "8bab111a65dd1b89",
"metadata": {},
"source": [
"# Configuration\n"
]
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"id": "aa799b526e7eb076",
"metadata": {},
"outputs": [],
"source": [
"# Configure the image path and range\n",
"image_dir = \"/path/to/your/images\" # Update this to your image directory\n",
"image_name_string = \"IMG_{:04d}.JPG\" # F-string template for image names\n",
"image_range = range(1, 10) # Range of image numbers to process\n",
"channel = 0 # Color channel to analyze (0=Red, 1=Green, 2=Blue)\n",
"saturation = 255"
],
"id": "aa799b526e7eb076"
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Process Images\n",
"id": "9b3295c6d521431e"
"id": "9b3295c6d521431e",
"metadata": {},
"source": [
"# Process Images\n"
]
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"id": "344c5f7ce039571b",
"metadata": {},
"outputs": [],
"source": [
"# Process each image in the range\n",
"for img_id in image_range:\n",
Expand Down Expand Up @@ -89,11 +98,14 @@
"\n",
" \n",
"\n"
],
"id": "344c5f7ce039571b"
]
}
],
"metadata": {},
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions ledsa/tools/photo_renamer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pandas as pd
import exifread

#does not work for Images in CR3 format

def set_working_dir():
"""
Expand Down
Loading