From be44951c76e1b75a96839f0c18c157026d4bee1a Mon Sep 17 00:00:00 2001 From: Ross Cutler <46252169+rosscutler@users.noreply.github.com> Date: Wed, 4 Jun 2025 16:38:04 -0700 Subject: [PATCH] Add font option for trapping clips --- docs/conf-trapping.md | 6 ++- docs/prep_acr.md | 9 ++-- docs/prep_avatar.md | 1 + docs/prep_dcr.md | 9 ++-- src/create_split_screen_dcr.py | 39 +++++++++++----- src/trapping_clips/create_trapping_clips.py | 52 ++++++++++++++------- 6 files changed, 76 insertions(+), 40 deletions(-) diff --git a/docs/conf-trapping.md b/docs/conf-trapping.md index 6779fcf..7f56a4a 100644 --- a/docs/conf-trapping.md +++ b/docs/conf-trapping.md @@ -20,7 +20,9 @@ * `include_from_source_stimuli_in_second = 2`: use first 2 seconds from the `source` clips to generate the trapping clips. It may lead to a clip duration that is different from the rest of clips which should be rated. - * `keep_original_duration = true`: As a result each generated clips will be as long as the corresponding original clip. - It is the recommended setting. +* `keep_original_duration = true`: As a result each generated clips will be as long as the corresponding original clip. +It is the recommended setting. + +If the default font `arial.ttf` is not available on your system, provide the path to a TrueType font file using the `--font` argument when running `create_trapping_clips.py`. \ No newline at end of file diff --git a/docs/prep_acr.md b/docs/prep_acr.md index 8b98dcd..19843d8 100644 --- a/docs/prep_acr.md +++ b/docs/prep_acr.md @@ -61,10 +61,11 @@ column name `training_pvs` (see [training_clips_acr.csv](../sample_inputs/traini ``` bash cd src\trapping_clips pip install -r requirements.txt - python create_trapping_clips.py ^ - --source tp_src ^ - --des tp_out ^ - --cfg your_config_file.cfg + python create_trapping_clips.py ^ + --source tp_src ^ + --des tp_out ^ + --cfg your_config_file.cfg ^ + --font path_to_font.ttf ``` 5. Trapping clips are stored in `tp_out` directory. List of clips and their correct answer can be found in `tp_out\output_report.csv`. diff --git a/docs/prep_avatar.md b/docs/prep_avatar.md index ed3165d..0cb24a0 100644 --- a/docs/prep_avatar.md +++ b/docs/prep_avatar.md @@ -57,6 +57,7 @@ For details about the different test methods for Photorealistic Avatars, please --source tp_src ^ --des tp_out ^ --cfg your_config_file.cfg ^ + --font path_to_font.ttf ^ --avatar ``` 4. Trapping clips will be stored in the `tp_out` directory. The list of clips and their correct answers can be found in `tp_out\trapping_output_report.csv`. diff --git a/docs/prep_dcr.md b/docs/prep_dcr.md index d70ea01..cfcb898 100644 --- a/docs/prep_dcr.md +++ b/docs/prep_dcr.md @@ -57,10 +57,11 @@ column named `training_pvs` and URLs to corresponding reference clips in column ``` bash cd src\trapping_clips pip install -r requirements.txt - python create_trapping_clips.py ^ - --source tp_src ^ - --des tp_out ^ - --cfg your_config_file.cfg + python create_trapping_clips.py ^ + --source tp_src ^ + --des tp_out ^ + --cfg your_config_file.cfg ^ + --font path_to_font.ttf ``` 5. Trapping clips are stored in `tp_out` directory. List of clips and their correct answer can be found in `tp_out\output_report.csv`. diff --git a/src/create_split_screen_dcr.py b/src/create_split_screen_dcr.py index 022e1fa..ff74afd 100644 --- a/src/create_split_screen_dcr.py +++ b/src/create_split_screen_dcr.py @@ -11,8 +11,20 @@ import configparser as CP import csv import cv2 -from PIL import Image, ImageFont, ImageDraw -from moviepy.editor import * +from PIL import Image, ImageFont, ImageDraw +from moviepy.editor import * + +DEFAULT_FONT = "arial.ttf" +font_file = DEFAULT_FONT + +def load_font(size): + try: + return ImageFont.truetype(font_file, size) + except OSError: + try: + return ImageFont.truetype("DejaVuSans-Bold.ttf", size) + except OSError: + return ImageFont.load_default() video_extension = '.mp4' trapping_videos = [] @@ -40,14 +52,14 @@ def create_image(width, height, clip_id, des_folder): font_size += 5 else: font_size -= 1 - font = ImageFont.truetype("arial.ttf", font_size) + font = load_font(font_size) text_width = font.getsize(msg)[0] percentage = text_width / expected_text_width # create the image img = Image.new('RGB', (width, height), color=(127, 127, 127)) d = ImageDraw.Draw(img) - font = ImageFont.truetype("arial.ttf", font_size) + font = load_font(font_size) text_width = font.getsize(msg)[0] text_height = font.getsize(msg)[1] @@ -157,12 +169,15 @@ def create_trap_stimulus(source, message, output, cfg): parser = argparse.ArgumentParser(description='Create split screen for DCR test.') parser.add_argument("--source", help="source directory containing all video clips", required=True) - parser.add_argument("--des", help="destination directory where the screens to be stored", required=True) - - args = parser.parse_args() - - assert os.path.exists(args.source), f"Invalid source directory {args.source}]" - - print('Start scanning the source clip directory') - n_created_screens = create_split_screens(args.source, args.des) + parser.add_argument("--des", help="destination directory where the screens to be stored", required=True) + parser.add_argument("--font", help="path to a TrueType font file", default=DEFAULT_FONT) + + args = parser.parse_args() + + font_file = args.font + + assert os.path.exists(args.source), f"Invalid source directory {args.source}]" + + print('Start scanning the source clip directory') + n_created_screens = create_split_screens(args.source, args.des) print(f'{n_created_screens} files created.') diff --git a/src/trapping_clips/create_trapping_clips.py b/src/trapping_clips/create_trapping_clips.py index b6cf67a..523e327 100644 --- a/src/trapping_clips/create_trapping_clips.py +++ b/src/trapping_clips/create_trapping_clips.py @@ -6,17 +6,30 @@ @author: Babak Naderi """ -import argparse -from os.path import isfile, join, basename -import configparser as CP -import csv -import json -import cv2 -from PIL import Image, ImageFont, ImageDraw -from moviepy import VideoFileClip, concatenate_videoclips -import base64 -import os -import uuid +import argparse +from os.path import isfile, join, basename +import configparser as CP +import csv +import json +import cv2 +from PIL import Image, ImageFont, ImageDraw +from moviepy import VideoFileClip, concatenate_videoclips +import base64 +import os +import uuid + +DEFAULT_FONT = "arial.ttf" +font_file = DEFAULT_FONT + +def load_font(size): + """Load the configured font, falling back to a default if not found.""" + try: + return ImageFont.truetype(font_file, size) + except OSError: + try: + return ImageFont.truetype("DejaVuSans-Bold.ttf", size) + except OSError: + return ImageFont.load_default() video_extension = '.mp4' trapping_videos = [] @@ -77,9 +90,9 @@ def create_msg_img(cfg, score, des, v_width, v_height): percentage = 0 font_size = 15 - score_text = str(score) - if args.avatar and 'avatar_rating_answers' in cfg: - score_text = {json.loads(cfg['avatar_rating_answers'])[str(score)] + score_text = str(score) + if args.avatar and 'avatar_rating_answers' in cfg: + score_text = json.loads(cfg['avatar_rating_answers'])[str(score)] if len(cfg['message_line1'].format(score_text)) > len(cfg['message_line2'].format(score_text)): text = cfg['message_line1'].format(score_text) @@ -90,14 +103,14 @@ def create_msg_img(cfg, score, des, v_width, v_height): font_size += 5 else: font_size -= 1 - font = ImageFont.truetype("arial.ttf", font_size) + font = load_font(font_size) text_width = font.getbbox(text)[2] percentage = text_width / expected_text_width # create the image img = Image.new('RGB', (v_width, v_height), color=(127, 127, 127)) d = ImageDraw.Draw(img) - font = ImageFont.truetype("arial.ttf", font_size) + font = load_font(font_size) text = title text_bbox = font.getbbox(text) @@ -206,8 +219,11 @@ def create_trap_stimulus(source, message, output, cfg): parser.add_argument("--cfg", help="Check trapping.cfg for all the details", required=True) # is avatar - parser.add_argument("--avatar", help="Is avatar", action='store_true', default=False) - args = parser.parse_args() + parser.add_argument("--avatar", help="Is avatar", action='store_true', default=False) + parser.add_argument("--font", help="path to a TrueType font file to use for the messages", default=DEFAULT_FONT) + + args = parser.parse_args() + font_file = args.font cfgpath = args.cfg assert os.path.exists(cfgpath), f"No configuration file in {cfgpath}]"