Team Ai
Datasetpublic

codeShare/lora-training-data

sourceHugging Faceupdated 1mo agoView on Hugging Face
2likes785downloads
add_text_to_image.ipynb1 linesDownload Raw Back to root
1{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[{"file_id":"https://huggingface.co/codeShare/FLUX.2-klein-9b-SDNQ-4bit/blob/main/colab_notebooks/utils/add_text_to_image.ipynb","timestamp":1780166500666},{"file_id":"https://huggingface.co/codeShare/FLUX.2-klein-9b-SDNQ-4bit/blob/main/colab_notebooks/utils/add_text_to_image.ipynb","timestamp":1780149484702},{"file_id":"https://huggingface.co/codeShare/FLUX.2-klein-9b-SDNQ-4bit/blob/main/colab_notebooks/utils/add_text_to_image.ipynb","timestamp":1780103636563},{"file_id":"https://huggingface.co/codeShare/FLUX.2-klein-9b-SDNQ-4bit/blob/main/colab_notebooks/utils/add_text_to_image.ipynb","timestamp":1780102966743}],"mount_file_id":"1DLjgfTYS2IVwm-exCVkWgsqE8QocMwUq","authorship_tag":"ABX9TyNl1xxKlEEw92z6DypGhVEw"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"code","source":["# ============================================================\n","# GOOGLE COLAB - FUTURISTIC TEXT DATASET GENERATOR (UPDATED)\n","# ============================================================\n","\n","# @title Parameters\n","zip_filepath = \"/content/drive/MyDrive/to_add_print.zip\"  # @param {type:\"string\"}\n","save_to_drive = True  # @param {type:\"boolean\"}\n","clear_previous_run_output = True  # @param {type:\"boolean\"}\n","create_missing_text_files = True  # @param {type:\"boolean\"}\n","num_variants_per_image = 3  # @param {type:\"slider\", min:1, max:10, step:1}\n","\n","import os\n","import zipfile\n","import random\n","import shutil\n","import requests\n","import colorsys\n","\n","from PIL import (\n","    Image,\n","    ImageDraw,\n","    ImageFont,\n","    ImageFilter\n",")\n","\n","from google.colab import drive\n","\n","drive.mount('/content/drive', force_remount=True)\n","\n","# ============================================================\n","# SETUP\n","# ============================================================\n","\n","os.makedirs(\"/content/fonts\", exist_ok=True)\n","os.makedirs(\"/content/extracted\", exist_ok=True)\n","\n","# Clear previous output if requested\n","if clear_previous_run_output and os.path.exists(\"/content/output\"):\n","    shutil.rmtree(\"/content/output\")\n","os.makedirs(\"/content/output\", exist_ok=True)\n","\n","# ============================================================\n","# FONT DOWNLOADS (UPDATED & EXPANDED)\n","# ============================================================\n","\n","font_urls = [\n","    # Futuristic\n","    \"https://github.com/google/fonts/raw/main/ofl/orbitron/Orbitron-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/quantico/Quantico-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/exo2/Exo2-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/rajdhani/Rajdhani-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/teko/Teko-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/audiowide/Audiowide-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/russoone/RussoOne-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/syncopate/Syncopate-Bold.ttf\",\n","\n","    # Heavy\n","    \"https://github.com/google/fonts/raw/main/ofl/anton/Anton-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/bangers/Bangers-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/ultra/Ultra-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/blackopsone/BlackOpsOne-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/alfaslabone/AlfaSlabOne-Regular.ttf\",\n","\n","    # Tech\n","    \"https://github.com/google/fonts/raw/main/ofl/chakrapetch/ChakraPetch-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/oxanium/Oxanium-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/jura/Jura-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/spacegrotesk/SpaceGrotesk-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/spacemono/SpaceMono-Bold.ttf\",\n","\n","    # Additional Futuristic\n","    \"https://github.com/google/fonts/raw/main/ofl/barlowcondensed/BarlowCondensed-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/barlow/Barlow-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/manrope/Manrope-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/prompt/Prompt-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/kanit/Kanit-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/rubikmonoone/RubikMonoOne-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/titilliumweb/TitilliumWeb-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/michroma/Michroma-Regular.ttf\",\n","\n","    # Cyberpunk\n","    \"https://github.com/google/fonts/raw/main/ofl/wallpoet/Wallpoet-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/kdamthmorpro/KdamThmorPro-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/iceberg/Iceberg-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/brunoace/BrunoAce-Regular.ttf\",\n","\n","    # Display\n","    \"https://github.com/google/fonts/raw/main/ofl/paytoneone/PaytoneOne-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/fjallaone/FjallaOne-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/sairaextra/SairaExtraCondensed-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/squadaone/SquadaOne-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/archivo/Archivo-Bold.ttf\",\n","\n","    # Industrial\n","    \"https://github.com/google/fonts/raw/main/ofl/bebasneue/BebasNeue-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/archivoblack/ArchivoBlack-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/oswald/Oswald-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/notosans/NotoSans-Bold.ttf\",\n","\n","    # Experimental\n","    \"https://github.com/google/fonts/raw/main/ofl/monoton/Monoton-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/pressstart2p/PressStart2P-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/majormonodisplay/MajorMonoDisplay-Regular.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/silkscreen/Silkscreen-Bold.ttf\",\n","    \"https://github.com/google/fonts/raw/main/ofl/vt323/VT323-Regular.ttf\",\n","]\n","\n","font_paths = []\n","font_names = []\n","\n","print(\"Downloading fonts...\")\n","\n","for url in font_urls:\n","    try:\n","        response = requests.get(url)\n","        if response.status_code == 200:\n","            filename = url.split(\"/\")[-1]\n","            save_path = f\"/content/fonts/{filename}\"\n","            with open(save_path, \"wb\") as f:\n","                f.write(response.content)\n","\n","            font_paths.append(save_path)\n","            clean_name = (\n","                filename\n","                .replace(\".ttf\", \"\")\n","                .replace(\"-\", \" \")\n","                .replace(\"_\", \" \")\n","            )\n","            font_names.append(clean_name)\n","            print(f\"Downloaded {filename}\")\n","    except:\n","        pass\n","\n","print(f\"\\nLoaded {len(font_paths)} fonts.\")\n","\n","# ============================================================\n","# EXTRACT DATASET\n","# ============================================================\n","\n","with zipfile.ZipFile(zip_filepath, 'r') as zip_ref:\n","    zip_ref.extractall(\"/content/extracted\")\n","\n","# ============================================================\n","# FIND IMAGE/TEXT PAIRS\n","# ============================================================\n","\n","image_extensions = ('.jpg', '.jpeg', '.png', '.webp')\n","\n","pairs = []\n","\n","for root, _, files in os.walk(\"/content/extracted\"):\n","    for file in files:\n","        if '._' in file:\n","            continue\n","        if file.lower().endswith(image_extensions):\n","            base = os.path.splitext(file)[0]\n","            img_path = os.path.join(root, file)\n","            txt_path = os.path.join(root, base + \".txt\")\n","            pairs.append((img_path, txt_path))\n","\n","print(f\"Found {len(pairs)} image/text pairs.\")\n","\n","# ============================================================\n","# WORDS\n","# ============================================================\n","\n","futuristic_words = [\n","    \"NEXUS\", \"VOID\", \"QUANTUM\", \"NEBULA\", \"SYNAPSE\", \"CHRONOS\", \"LUMEN\",\n","    \"VORTEX\", \"PHOTON\", \"ASTRAL\", \"OMEGA\", \"CYBER\", \"MATRIX\", \"HYPERION\",\n","    \"PULSE\", \"ECLIPSE\", \"APEX\", \"AETHER\", \"SPECTRA\", \"ZENITH\", \"COSMOS\",\n","    \"GLYPH\", \"HALO\", \"STARFORGE\", \"NOVA\", \"ARCANE\", \"VELOCITY\", \"PRISM\",\n","    \"VOIDCORE\", \"STARLINE\", \"FUSION\", \"PHASE\", \"OBSIDIAN\", \"ORBIT\",\n","    \"NEXUS-X\", \"SOLAR\", \"LUCID\", \"NEMESIS\", \"VECTOR\", \"ION\",\n","]\n","\n","# ============================================================\n","# GRADIENT PALETTE (NEW)\n","# ============================================================\n","\n","def generate_gradient_pair():\n","    # Biased palette towards yellow, purple, orange, red, pink, teal\n","    biased_palette = [\n","        # Yellow\n","        (255,255,0), (255,180,0), (255,215,0),\n","        # Purple\n","        (255,0,255), (128,0,255), (138,43,226), (75,0,130),\n","        # Orange\n","        (255,100,0), (255,69,0), (255,140,0),\n","        # Red\n","        (255,0,0), (255,80,80), (255,0,100),\n","        # Pink\n","        (255,0,128), (255,20,147), (255,100,255),\n","        # Teal (cyan/blue-green)\n","        (0,255,255), (0,255,128), (64,224,208), (0,255,200), (0,180,255)\n","    ]\n","\n","    color1 = random.choice(biased_palette)\n","    color2 = random.choice(biased_palette)\n","    while color1 == color2:\n","        color2 = random.choice(biased_palette)\n","    return color1, color2\n","\n","# ============================================================\n","# CREATE SINGLE-PASS GRADIENT TEXT (UPDATED)\n","# ============================================================\n","\n","def create_gradient_text(\n","    text,\n","    font,\n","    gradient_colors,\n","    glow_radius=8\n","):\n","    temp_draw = ImageDraw.Draw(Image.new(\"RGB\", (1, 1)))\n","    bbox = temp_draw.textbbox((0, 0), text, font=font)\n","\n","    text_w = bbox[2] - bbox[0]\n","    text_h = bbox[3] - bbox[1]\n","\n","    padding = 80\n","    canvas_w = text_w + padding * 2\n","    canvas_h = text_h + padding * 2\n","\n","    # Mask\n","    mask = Image.new(\"L\", (canvas_w, canvas_h), 0)\n","    mask_draw = ImageDraw.Draw(mask)\n","    mask_draw.text((padding, padding), text, font=font, fill=255)\n","\n","    # Horizontal Gradient using lines (faster & cleaner)\n","    gradient = Image.new(\"RGBA\", (canvas_w, canvas_h))\n","    draw_grad = ImageDraw.Draw(gradient)\n","\n","    color1, color2 = gradient_colors\n","\n","    for x in range(canvas_w):\n","        t = x / max(1, canvas_w - 1)\n","        r = int(color1[0] * (1 - t) + color2[0] * t)\n","        g = int(color1[1] * (1 - t) + color2[1] * t)\n","        b = int(color1[2] * (1 - t) + color2[2] * t)\n","        draw_grad.line([(x, 0), (x, canvas_h)], fill=(r, g, b, 255))\n","\n","    gradient.putalpha(mask)\n","\n","    # Glow\n","    glow = gradient.filter(ImageFilter.GaussianBlur(radius=glow_radius))\n","    final = Image.blend(glow, gradient, 0.72)\n","\n","    return final\n","\n","# ============================================================\n","# SAFE DRAWING\n","# ============================================================\n","\n","def draw_text(image, text, font, position, angle):\n","    gradient_colors = generate_gradient_pair()\n","\n","    text_layer = create_gradient_text(\n","        text=text,\n","        font=font,\n","        gradient_colors=gradient_colors,\n","        glow_radius=random.randint(4, 10)\n","    )\n","\n","    if angle != 0:\n","        text_layer = text_layer.rotate(\n","            angle, expand=True, resample=Image.BICUBIC\n","        )\n","\n","    img_w, img_h = image.size\n","    layer_w, layer_h = text_layer.size\n","    x, y = position\n","\n","    # Strict bounds checking\n","    x = max(0, min(x, img_w - layer_w))\n","    y = max(0, min(y, img_h - layer_h))\n","\n","    if layer_w > img_w or layer_h > img_h:\n","        return\n","\n","    image.paste(text_layer, (x, y), text_layer)\n","\n","# ============================================================\n","# PROCESS DATASET\n","# ============================================================\n","\n","image_counter = 0 # To ensure unique numbering across all variants\n","\n","for idx, (img_path, original_txt_path) in enumerate(pairs):\n","    print(f\"[{idx+1}/{len(pairs)}] Processing {os.path.basename(img_path)}\")\n","\n","    for variant_idx in range(num_variants_per_image):\n","        image_counter += 1\n","        print(f\"  Variant {variant_idx + 1}/{num_variants_per_image}\")\n","\n","        img = Image.open(img_path).convert(\"RGB\")\n","        w, h = img.size\n","\n","        # Font\n","        font_index = random.randint(0, len(font_paths) - 1)\n","        font_path = font_paths[font_index]\n","        font_name = font_names[font_index]\n","\n","        # Adaptive Font Size\n","        font_size = int(min(w, h) * random.uniform(0.10, 0.20))\n","        font = ImageFont.truetype(font_path, font_size)\n","\n","        # Word\n","        word = random.choice(futuristic_words)\n","        style_roll = random.random()\n","        if style_roll < 0.30:\n","            word = word.lower()\n","        elif style_roll < 0.60:\n","            word = word.capitalize()\n","\n","        # Angle\n","        angle = random.uniform(-18, 18)\n","\n","        # Sample layer to check size\n","        sample_layer = create_gradient_text(\n","            text=word,\n","            font=font,\n","            gradient_colors=generate_gradient_pair(),\n","            glow_radius=8\n","        )\n","        if angle != 0:\n","            sample_layer = sample_layer.rotate(angle, expand=True, resample=Image.BICUBIC)\n","\n","        text_w, text_h = sample_layer.size\n","\n","        if text_w >= w or text_h >= h:\n","            print(f\"    Skipping variant due to text size exceeding image dimensions: {word}\")\n","            continue\n","\n","        # Position biases\n","        upper_y = int(h * random.uniform(0.02, 0.18))\n","        lower_y = int(h * random.uniform(0.68, 0.88))\n","        left_x = int(w * random.uniform(0.02, 0.15))\n","        right_x = int(w * random.uniform(0.55, 0.80))\n","\n","        positions = [\n","            (left_x, upper_y), (right_x, upper_y),\n","            (left_x, lower_y), (right_x, lower_y)\n","        ]\n","        random.shuffle(positions)\n","\n","        num_texts = 1 # Assuming only one text per image for now\n","        selected_positions = positions[:num_texts]\n","\n","        # Draw\n","        for pos in selected_positions:\n","            draw_text(img, word, font, pos, angle)\n","\n","        # Save Image\n","        base_filename = os.path.splitext(os.path.basename(img_path))[0]\n","        out_img_name = f\"{base_filename}_{variant_idx + 1}.jpg\"\n","        out_img_path = os.path.join(\"/content/output\", out_img_name)\n","        img.save(out_img_path, quality=95, format=\"JPEG\")\n","\n","        # Caption\n","        original_caption = \"\"\n","        if os.path.exists(original_txt_path):\n","            with open(original_txt_path, \"r\", encoding=\"utf-8\") as f:\n","                original_caption = f.read().strip()\n","\n","        added_caption = (\n","            f\"The image features the word '{word}' rendered using a bold futuristic \"\n","            f\"{font_name} font with a glowing gradient, slightly rotated and \"\n","            f\"positioned near the upper or lower regions of the frame.\"\n","        )\n","\n","        final_caption = original_caption + \"\\n\" + added_caption if original_caption else added_caption\n","\n","        out_txt_name = f\"{base_filename}_{variant_idx + 1}.txt\"\n","        out_txt_path = os.path.join(\"/content/output\", out_txt_name)\n","        with open(out_txt_path, \"w\", encoding=\"utf-8\") as f:\n","            f.write(final_caption)\n","\n","# ============================================================\n","# EXPORT ZIP\n","# ============================================================\n","\n","random_id = random.randint(100000, 999999)\n","zip_name = f\"processed_dataset_{random_id}\"\n","\n","shutil.make_archive(f\"/content/{zip_name}\", \"zip\", \"/content/output\")\n","\n","if save_to_drive:\n","    drive_output = f\"/content/drive/MyDrive/{zip_name}.zip\"\n","    shutil.copy(f\"/content/{zip_name}.zip\", drive_output)\n","\n","print(\"\\n✅ COMPLETE\")\n","print(f\"Saved ZIP: {zip_name}.zip\")\n","if save_to_drive:\n","    print(f\"Copied to Drive: {drive_output}\")"],"metadata":{"id":"Fbza2TA8LI7t","cellView":"form"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Hencaa5rLvcV"},"source":[" # Disconnect"]},{"cell_type":"code","execution_count":null,"metadata":{"cellView":"form","id":"75027cc1"},"outputs":[],"source":["#@title Auto Disconnect Runtime upon code completion\n","disconnect_runtime = True #@param {type:'boolean'}\n","\n","if disconnect_runtime:\n","  from google.colab import runtime\n","  runtime.unassign()"]}]}