@ -25,7 +25,7 @@
},
{
"cell_type": "code",
"execution_count": null ,
"execution_count": 1 ,
"metadata": {
"cellView": "form",
"id": "aP9FjmWxtLKJ"
@ -38,7 +38,7 @@
},
{
"cell_type": "code",
"execution_count": null ,
"execution_count": 2 ,
"metadata": {
"cellView": "form",
"id": "xpPKQR40qvz2"
@ -46,7 +46,7 @@
"outputs": [],
"source": [
"#@title Setup\n",
"import argparse, subprocess, sys, time \n",
"import subprocess\n",
"\n",
"def setup():\n",
" install_cmds = [\n",
@ -65,10 +65,8 @@
"sys.path.append('src/clip')\n",
"sys.path.append('clip-interrogator')\n",
"\n",
"import clip\n",
"import gradio as gr\n",
"import torch\n",
"from clip_interrogator import Interrogator, Config\n",
"from clip_interrogator import Config, Interrogator\n",
"\n",
"ci = Interrogator(Config())\n",
"\n",
@ -84,7 +82,7 @@
},
{
"cell_type": "code",
"execution_count": 4 ,
"execution_count": 3 ,
"metadata": {
"cellView": "form",
"colab": {
@ -150,7 +148,7 @@
},
{
"cell_type": "code",
"execution_count": null ,
"execution_count": 3 ,
"metadata": {
"cellView": "form",
"id": "OGmvkzITN4Hz"
@ -159,43 +157,69 @@
"source": [
"#@title Batch process a folder of images 📁 -> 📝\n",
"\n",
"#@markdown This will generate prompts for every image in a folder and save results to desc.csv in the same folder.\n",
"#@markdown This will generate prompts for every image in a folder and either save results \n",
"#@markdown to a desc.csv file in the same folder or rename the files to contain their prompts.\n",
"#@markdown The renamed files work well for [DreamBooth extension](https://github.com/d8ahazard/sd_dreambooth_extension)\n",
"#@markdown in the [Stable Diffusion Web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui).\n",
"#@markdown You can use the generated csv in the [Stable Diffusion Finetuning](https://colab.research.google.com/drive/1vrh_MUSaAMaC5tsLWDxkFILKJ790Z4Bl?usp=sharing)\n",
"#@markdown notebook or use it to train a different model or just print it out for fun. \n",
"#@markdown If you make something cool, I'd love to see it! Tag me on twitter or something. 😀\n",
"\n",
"import csv\n",
"import os\n",
"from IPython.display import display\n",
"from IPython.display import clear_output, display\n",
"from PIL import Image\n",
"from tqdm import tqdm\n",
"\n",
"folder_path = \"/content/my_images\" #@param {type:\"string\"}\n",
"mode = 'best' #@param [\"best\",\"classic\", \"fast\"]\n",
"prompt_mode = 'best' #@param [\"best\",\"classic\", \"fast\"]\n",
"output_mode = 'rename' #@param [\"desc.csv\",\"rename\"]\n",
"max_filename_len = 128 #@param {type:\"integer\"}\n",
"\n",
"\n",
"files = [f for f in os.listdir(folder_path) if f.endswith('.jpg') or f.endswith('.png')] if os.path.exists(folder_path) else []\n",
"def sanitize_for_filename(prompt: str, max_len: int) -> str:\n",
" name = \"\".join(c for c in prompt if (c.isalnum() or c in \",._-! \"))\n",
" name = name.strip()[:(max_len-4)] # extra space for extension\n",
" return name\n",
"\n",
"ci.config.quiet = True\n",
"\n",
"files = [f for f in os.listdir(folder_path) if f.endswith('.jpg') or f.endswith('.png')] if os.path.exists(folder_path) else []\n",
"prompts = []\n",
"for file in files:\n",
"for idx, file in enumerate(tqdm(files, desc='Generating prompts')):\n",
" if idx > 0 and idx % 100 == 0:\n",
" clear_output(wait=True)\n",
"\n",
" image = Image.open(os.path.join(folder_path, file)).convert('RGB')\n",
" prompt = inference(image, mode)\n",
" prompt = inference(image, prompt_ mode)\n",
" prompts.append(prompt)\n",
"\n",
" print(prompt)\n",
" thumb = image.copy()\n",
" thumb.thumbnail([256, 256])\n",
" display(thumb)\n",
"\n",
" print(prompt)\n",
" if output_mode == 'rename':\n",
" name = sanitize_for_filename(prompt, max_filename_len)\n",
" ext = os.path.splitext(file)[1]\n",
" filename = name + ext\n",
" idx = 1\n",
" while os.path.exists(os.path.join(folder_path, filename)):\n",
" print(f'File {filename} already exists, trying {idx+1}...')\n",
" filename = f\"{name}_{idx}{ext}\"\n",
" idx += 1\n",
" os.rename(os.path.join(folder_path, file), os.path.join(folder_path, filename))\n",
"\n",
"if len(prompts):\n",
" csv_path = os.path.join(folder_path, 'desc.csv')\n",
" with open(csv_path, 'w', encoding='utf-8', newline='') as f:\n",
" w = csv.writer(f, quoting=csv.QUOTE_MINIMAL)\n",
" w.writerow(['image', 'prompt'])\n",
" for file, prompt in zip(files, prompts):\n",
" w.writerow([file, prompt])\n",
"\n",
" print(f\"\\n\\n\\n\\nGenerated {len(prompts)} and saved to {csv_path}, enjoy!\")\n",
" if output_mode == 'desc.csv':\n",
" csv_path = os.path.join(folder_path, 'desc.csv')\n",
" with open(csv_path, 'w', encoding='utf-8', newline='') as f:\n",
" w = csv.writer(f, quoting=csv.QUOTE_MINIMAL)\n",
" w.writerow(['image', 'prompt'])\n",
" for file, prompt in zip(files, prompts):\n",
" w.writerow([file, prompt])\n",
"\n",
" print(f\"\\n\\n\\n\\nGenerated {len(prompts)} prompts and saved to {csv_path}, enjoy!\")\n",
" else:\n",
" print(f\"\\n\\n\\n\\nGenerated {len(prompts)} prompts and renamed your files, enjoy!\")\n",
"else:\n",
" print(f\"Sorry, I couldn't find any images in {folder_path}\")\n"
]
@ -208,7 +232,7 @@
"provenance": []
},
"kernelspec": {
"display_name": "Python 3.8.10 ('venv': venv)",
"display_name": "Python 3.9.5 ('venv': venv)",
"language": "python",
"name": "python3"
},
@ -222,12 +246,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10 "
"version": "3.9.5 "
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "f7a8d9541664ade9cff251487a19c76f2dd1b4c864d158f07ee26d1b0fd5c9a1 "
"hash": "10f7ca63a88f18f789e6adaf7a045f1bcd3706c5534a32f168d622925241605d "
}
}
},