You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
6.2 KiB
Python

import numpy as np
from datetime import datetime, timedelta
import sys
from time import strptime
from PIL import Image, ImageFont
import pandas as pd
import openpyxl
def divide_chunks(l, n):
"""
Splits a list into chunks of length n. Used to process the images in chunks.
"""
for i in range(0, len(l), n):
yield l[i : i + n]
# Sourced from https://gist.github.com/victorkristof/b9d794fe1ed12e708b9d
def datenum_to_datetime(datenum):
"""
Convert Matlab datenum into Python datetime.
:param datenum: Date in datenum format
:return: Datetime object corresponding to datenum.
"""
days = datenum % 1
hours = days % 1 * 24
minutes = hours % 1 * 60
seconds = np.round(minutes % 1 * 60)
return datetime.fromordinal(int(datenum)) \
+ timedelta(days=int(days)) \
+ timedelta(hours=int(hours)) \
+ timedelta(minutes=int(minutes)) \
+ timedelta(seconds=int(seconds)) \
- timedelta(days=366)
# Sourced from https://stackoverflow.com/questions/32237862/find-the-closest-date-to-a-given-date
def nearest(all_dates, target_date_raw):
abs_deltas_from_target_date = np.absolute(all_dates - target_date_raw)
index_of_min_delta_from_target_date = np.argmin(abs_deltas_from_target_date)
closest_date = all_dates[index_of_min_delta_from_target_date]
return closest_date
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.3+
count = len(it)
def show(j):
x = int(size*j/count)
print("{}[{}{}] {}/{}".format(prefix, u"#"*x, "."*(size-x), j, count),
end='\r', file=out, flush=True)
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
def get_site_tide_data(images_parent_dir, site):
# Retrieve tide data for the given site
db = openpyxl.load_workbook(images_parent_dir + "/Database/CoastSnapDB.xlsx")
beach_data = db[site]
tide_filename = beach_data["B24"].value
if tide_filename == 'NO_TIDE.mat':
return False
tide_filename_pkl = tide_filename[:-4] + '.pkl'
tides_path = images_parent_dir + '/Tide Data/Tide_Data_Python/' + tide_filename_pkl
tides_df = pd.read_pickle(tides_path)
return tides_df
class RegisteredImage():
def __init__(self, pathname, filename):
self.pathname = pathname
self.filename = filename
filename_list = filename.split(".")
date = filename_list[3].split("_")
if 'snap' in filename_list:
self.contributor = filename_list[8] # Mitch filename format
else:
self.contributor = filename_list[6] # Leaman filename format
self.site = filename_list[6]
self.posix_time = filename_list[0]
self.timezone = filename_list[4]
self.year = filename_list[5]
self.month = '{:02d}'.format(strptime(filename_list[2],'%b').tm_mon) # Ensure 2-digit format
self.day = date[0]
self.hour = date[1]
self.minute = date[2]
self.second = date[3]
self.tide = None
self.tag = None
self.width = None
self.height = None
self.font = None
self.large_filename = False
def get_tide(self, tides_df):
# Account for daylight savings
# ASSUMPTION: All .mat tide files are either AEST or AEDT
if self.timezone == 'AEDT':
self.hour = str(int(self.hour) - 1)
date_string = self.year + '-' + self.month + '-' + self.day + ' ' + self.hour + ':' + self.minute + ':' + self.second
img_datetime = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S") # Image date/time as a datetime object
tide_date = nearest(tides_df['time'], img_datetime)
tide = tides_df.loc[tides_df['time'] == tide_date, 'tide level']
tide = tide.iloc[0]
self.tide = "{:.2f}".format(tide)
def create_tag(self):
# Create image tag
hour = self.hour.zfill(2)
minute = self.minute.zfill(2)
if self.tide: # Tag with tide data
tide = self.tide
if float(self.tide) >= 0:
tide = '+' + self.tide
tag = ('Date:' + self.year + '/' + self.month + '/' + self.day +
' Time:' + hour + ':' + minute +
' Tide:' + tide + 'm AHD' +
' Contributor:' + self.contributor)
if(self.font.getsize(tag)[0] > self.width): # Check if text is wider than the image
self.large_filename = True
tag = ('Date:' + self.year + '/' + self.month + '/' + self.day +
' Time:' + hour + ':' + minute +
' Tide:' + tide + 'm AHD' + '\n' +
'Contributor:' + self.contributor)
self.tag = tag
else: # Tag without tide data
tag = ('Date:' + self.year + '/' + self.month + '/' + self.day +
' Time:' + hour + ':' + minute +
' Contributor:' + self.contributor)
if(self.font.getsize(tag)[0] > self.width): # Check if text is wider than the image
self.large_filename = True
tag = ('Date:' + self.year + '/' + self.month + '/' + self.day +
' Time:' + hour + ':' + minute + '\n' +
'Contributor:' + self.contributor)
self.tag = tag
def get_dimensions(self):
image = Image.open(self.pathname)
# White Text Box
self.width, self.height = image.size
def get_font(self):
image = Image.open(self.pathname)
fontsize = 1
if self.tide:
img_fraction = 0.95
else:
img_fraction = 0.85
font = ImageFont.truetype("fonts/LiberationMono.ttf", fontsize)
generic_large_tag = "1641775682.Mon.Jan.10_11_48_02.AEDT.2022.byron.snap.KateThornborough123"
while font.getsize(generic_large_tag)[0] < img_fraction*image.size[0]:
# iterate until the text size is just larger than the criteria
fontsize += 1
font = ImageFont.truetype("fonts/LiberationMono.ttf", fontsize)
self.font = ImageFont.truetype("fonts/LiberationMono.ttf", fontsize)