3 Commits

3 changed files with 53 additions and 21 deletions

View File

@@ -12,6 +12,7 @@ This script is designed to create geotagged frames from video and GPX track."""
end = "End of program, press Enter to quit." end = "End of program, press Enter to quit."
paths_title = "## Paths" paths_title = "## Paths"
parameters_title = "## Process parameters" parameters_title = "## Process parameters"
tags_title = "## Additional tags"
metadata = """{} ({} {}B)\n metadata = """{} ({} {}B)\n
- Duration : {} s\n - Duration : {} s\n
- Start time : {}.{}\n - Start time : {}.{}\n
@@ -21,7 +22,7 @@ metadata = """{} ({} {}B)\n
cv2_tqdm = 'frame(s)' cv2_tqdm = 'frame(s)'
[ui.parameters] [ui.parameters]
toml_setting² = "Setting with TOML file ({}/{}) ? " toml_setting = "Setting with TOML file ({}/{}) ? "
timelapse = "Timelapse video ({}/{}) ? " timelapse = "Timelapse video ({}/{}) ? "
timelapse_fps = "Timelapse framerate (frame/s) [{}-{}] : " timelapse_fps = "Timelapse framerate (frame/s) [{}-{}] : "
@@ -38,7 +39,7 @@ video_start_datetime_err = "Error... entered datetime is not valid."
rec_timezone = "Enter time offset related to UTC (example for CEST : +02:00) : " rec_timezone = "Enter time offset related to UTC (example for CEST : +02:00) : "
time_offset = "Enter time offset between video and GPX in seconds [{}-{}] : " time_offset = "Enter time offset with GPS track in seconds [{}-{}] : "
time_offset_err = "Error... please enter a decimal between {} and {}." time_offset_err = "Error... please enter a decimal between {} and {}."
[ui.paths] [ui.paths]

View File

@@ -11,6 +11,7 @@ intro = """Bienvenue dans le script video2geoframes.py !
Ce script permet, à partir d'une vidéo et d'une trace GPS, de créer un ensemble de photos géotaguées.""" Ce script permet, à partir d'une vidéo et d'une trace GPS, de créer un ensemble de photos géotaguées."""
end = "Fin du programme, appuyez sur Entrée pour fermer." end = "Fin du programme, appuyez sur Entrée pour fermer."
paths_title = "## Chemins" paths_title = "## Chemins"
tags_title = "## Tags additionnels"
parameters_title = "## Paramètres du traitement" parameters_title = "## Paramètres du traitement"
metadatas = """{} ({} {}B) metadatas = """{} ({} {}B)
- Durée : {} s - Durée : {} s
@@ -38,7 +39,7 @@ video_start_datetime_err = "Erreur... l'horodatage entré est invalide."
rec_timezone = "Entrez le décalage horaire par rapport à UTC (exemple pour CEST : +02:00) : " rec_timezone = "Entrez le décalage horaire par rapport à UTC (exemple pour CEST : +02:00) : "
time_offset = "Entrez le décalage temporel entre la vidéo et le GPX en secondes [{}-{}] : " time_offset = "Entrez le décalage temporel avec la trace GPS en secondes [{}-{}] : "
time_offset_err = "Erreur... veuillez entrer un nombre décimal entre {} et {}." time_offset_err = "Erreur... veuillez entrer un nombre décimal entre {} et {}."
[ui.paths] [ui.paths]

View File

@@ -8,7 +8,7 @@ Designed for contribution to street-level imagery projects like Mapillary or Pan
__author__ = "Lucas MATHIEU (@campanu)" __author__ = "Lucas MATHIEU (@campanu)"
__license__ = "AGPL-3.0-or-later" __license__ = "AGPL-3.0-or-later"
__version__ = "2.0-alpha2" __version__ = "2.0-alpha5"
__maintainer__ = "Lucas MATHIEU (@campanu)" __maintainer__ = "Lucas MATHIEU (@campanu)"
__email__ = "campanu@luc-geo.fr" __email__ = "campanu@luc-geo.fr"
@@ -18,6 +18,7 @@ import platform
from datetime import datetime, timedelta from datetime import datetime, timedelta
import cv2 import cv2
import piexif
from tomlkit import dumps, loads from tomlkit import dumps, loads
from tqdm import tqdm from tqdm import tqdm
from exif import Image, GpsAltitudeRef from exif import Image, GpsAltitudeRef
@@ -262,7 +263,7 @@ else:
model = input(locale_toml['ui']['metadatas']['model']) model = input(locale_toml['ui']['metadatas']['model'])
author = input(locale_toml['ui']['metadatas']['author']) author = input(locale_toml['ui']['metadatas']['author'])
# Video metadatas extraction # Video metadatas formatting
print('\n{}'.format(locale_toml['processing']['reading_metadatas'])) print('\n{}'.format(locale_toml['processing']['reading_metadatas']))
video = cv2.VideoCapture(video_path) video = cv2.VideoCapture(video_path)
@@ -276,7 +277,7 @@ video_file_size = byte_multiple(os.stat(video_path).st_size)
video_duration = video_total_frames / video_fps video_duration = video_total_frames / video_fps
video_start_datetime_obj = video_start_datetime_obj + timedelta(seconds=time_offset) video_start_datetime_obj = video_start_datetime_obj + timedelta(seconds=time_offset)
video_start_datetime = video_start_datetime_obj.strftime('%Y:%m:%d %H:%M:%S') video_start_datetime = video_start_datetime_obj.strftime('%Y-%m-%d %H:%M:%S')
video_start_subsectime = video_start_datetime_obj.strftime('%f') video_start_subsectime = video_start_datetime_obj.strftime('%f')
# Metadata recap # Metadata recap
@@ -291,7 +292,9 @@ output_folder = '{}/{}'.format(output_folder, video_file_name)
existing_path(output_folder) existing_path(output_folder)
# Processes # Processes
## Frame sampling + tagging (OpenCV + exif) ## Frame sampling + tagging (OpenCV + piexif)
print('\n{}'.format(locale_toml['processing']['sampling']))
i = 0 i = 0
if timelapse == user_agree: if timelapse == user_agree:
@@ -299,7 +302,7 @@ if timelapse == user_agree:
else: else:
frame_interval = frame_sampling frame_interval = frame_sampling
cv2_tqdm_unit = " {}".format(locale_toml['ui']['units']['cv2_tqdm']) cv2_tqdm_unit = locale_toml['ui']['units']['cv2_tqdm']
cv2_tqdm_range = int(video_duration / frame_interval) cv2_tqdm_range = int(video_duration / frame_interval)
for i in tqdm(range(cv2_tqdm_range), unit=cv2_tqdm_unit): for i in tqdm(range(cv2_tqdm_range), unit=cv2_tqdm_unit):
@@ -313,31 +316,58 @@ for i in tqdm(range(cv2_tqdm_range), unit=cv2_tqdm_unit):
cv2.imwrite(image_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 88, cv2.IMWRITE_JPEG_PROGRESSIVE, 1, cv2.IMWRITE_JPEG_SAMPLING_FACTOR, 0x411111]) cv2.imwrite(image_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 88, cv2.IMWRITE_JPEG_PROGRESSIVE, 1, cv2.IMWRITE_JPEG_SAMPLING_FACTOR, 0x411111])
## Time tags preparation ## Time tags formatting
time_shift = i * frame_sampling time_shift = i * frame_sampling
current_datetime_obj = video_start_datetime_obj + timedelta(seconds=time_shift) current_datetime_obj = video_start_datetime_obj + timedelta(seconds=time_shift)
current_datetime = current_datetime_obj.strftime('%Y:%m:%d %H:%M:%S') current_datetime = current_datetime_obj.strftime('%Y:%m:%d %H:%M:%S')
current_subsec_time = int(int(current_datetime_obj.strftime('%f')) / 1000) current_subsec_time = int(int(current_datetime_obj.strftime('%f')) / 1000)
with open(image_path, 'rb') as image_file: # exif code
image = Image(image_file) # with open(image_path, 'rb') as image_file:
image.make = make # image = Image(image_file)
image.model = model # image.make = make
image.author = author # image.model = model
image.copyright = "{}, {}".format(author, video_start_datetime_obj.strftime('%Y')) # image.author = author
image.datetime_original = current_datetime # image.copyright = "{}, {}".format(author, video_start_datetime_obj.strftime('%Y'))
#image.offset_time_original = video_rec_timezone # image.datetime_original = current_datetime
# #image.offset_time_original = video_rec_timezone
#
# if current_subsec_time > 0 :
# image.subsec_time_original = str(current_subsec_time)
#
# with open(image_path, 'wb') as tagged_image_file:
# tagged_image_file.write(image.get_file())
# piexif code
image_exif = piexif.load(image_path)
image_tags = {
piexif.ImageIFD.Make: make,
piexif.ImageIFD.Model: model,
piexif.ImageIFD.Artist: author,
piexif.ImageIFD.Copyright: "{}, {}".format(author, video_start_datetime_obj.strftime('%Y')),
piexif.ImageIFD.Software : 'video2geoframes.py (v{})'.format(__version__)
}
exif_tags = {
piexif.ExifIFD.DateTimeOriginal: current_datetime,
piexif.ExifIFD.OffsetTimeOriginal: video_rec_timezone
}
if current_subsec_time > 0: if current_subsec_time > 0:
image.subsec_time_original = str(current_subsec_time) exif_tags[piexif.ExifIFD.SubSecTime] = str(current_subsec_time)
with open(image_path, 'wb') as tagged_image_file: image_exif['0th'] = image_tags
tagged_image_file.write(image.get_file()) image_exif['Exif'] = exif_tags
image_exif_bytes = piexif.dump(image_exif)
piexif.insert(image_exif_bytes, image_path)
i += 1 i += 1
# Geo-tagging (ExifTool) # Geo-tagging (ExifTool)
print('\n{}'.format(locale_toml['processing']['geotagging'])) print('\n{}'.format(locale_toml['processing']['geotagging']))
geotagging_cmd = '{} -P -geotag "{}" "-geotime<SubSecDateTimeOriginal" -overwrite_original "{}/{}_f*.jpg"'\ geotagging_cmd = '{} -P -geotag "{}" "-geotime<SubSecDateTimeOriginal" -overwrite_original "{}/{}_f*.jpg"'\
.format(exiftool_path, gps_track_path, output_folder, video_file_name.split('.')[0]) .format(exiftool_path, gps_track_path, output_folder, video_file_name.split('.')[0])
geotagging = os.system(geotagging_cmd) geotagging = os.system(geotagging_cmd)