Files
pi_mcps/mcp/mcp-image-gen/patrick_hidden_gen.py

412 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Patrick Hidden Name Artwork Generation Pipeline
Autonomous script to generate 26 ultra-detailed, visually rich digital artworks
where the name "PATRICK" is cleverly concealed within each composition.
Letters emerge organically from shapes, patterns, negative space, silhouettes,
alignment, or cumulative elements — never as plain text.
Visible only upon close inspection.
Uses the existing mcp-image-gen infrastructure (ComfyUI FLUX workflows).
Output organized in ~/Pictures/patrick_hidden_name/{theme}/{style}/
Usage:
cd /home/pplate/pi_mcps
python mcp/mcp-image-gen/patrick_hidden_gen.py
python mcp/mcp-image-gen/patrick_hidden_gen.py --dry-run
python mcp/mcp-image-gen/patrick_hidden_gen.py --model heretic
"""
import argparse
import copy
import json
import random
import time
import urllib.request
from pathlib import Path
from typing import Dict, List, Any, Optional
# --- Configuration ---
OUTPUT_ROOT = Path.home() / "Pictures" / "patrick_hidden_name"
PROGRESS_FILE = OUTPUT_ROOT / ".progress.json"
WORKFLOW_SCHNELL = Path(__file__).parent / "src/workflows/flux_schnell.json"
WORKFLOW_HERETIC = Path(__file__).parent / "src/workflows/flux2_klein_heretic.json"
# Core hidden-name prompting technique — applied to every asset
_HT = (
"the name PATRICK is cleverly and seamlessly concealed within the composition, "
"letters P-A-T-R-I-C-K emerge organically from shapes patterns negative space "
"silhouettes alignment or cumulative arrangement of multiple elements, "
"never plain text, subtle yet unmistakable once discovered, requires genuine "
"visual discovery and close inspection, natural integration into the scene, "
)
# Base quality boosters
_Q = "ultra-high detail, photorealistic rendering with cinematic lighting, intricate textures, depth of field, 8k resolution, masterpiece, best quality, "
ASSET_MANIFEST: List[Dict[str, Any]] = [
# 1. Dense crowds of marionette puppets — photoreal
{"id":"phn_01","theme":"marionettes","style":"photoreal","name":"marionette_crowd_puppets",
"prompt":_Q+_HT+"dense crowd of antique wooden marionette puppets on theatrical stage, "
"strings and body poses form PATRICK through negative space and limb alignment, "
"dramatic stage lighting with velvet curtains, realistic wood grain and fabric textures, "
"photorealistic cinematic","width":1024,"height":1024,"steps":4},
# 2. Marionettes — painterly
{"id":"phn_02","theme":"marionettes","style":"painterly","name":"marionette_theater_oil",
"prompt":_Q+_HT+"oil painting of crowded marionette theater, puppet strings and poses "
"form hidden PATRICK letters in composition, baroque style, rich colors, dramatic chiaroscuro "
"lighting, thick impasto brushwork","width":1024,"height":1024,"steps":20},
# 3. Birds — aerial formation
{"id":"phn_03","theme":"birds","style":"aerial","name":"bird_flock_formation",
"prompt":_Q+_HT+"aerial photograph of massive flock of starlings in precise murmuration, "
"bird silhouettes and gaps spell PATRICK through negative space and wing alignments, "
"golden hour light, vast sky, ultra realistic feathers and motion blur","width":1280,"height":720,"steps":4},
# 4. Birds — macro
{"id":"phn_04","theme":"birds","style":"macro","name":"bird_swarm_closeup",
"prompt":_Q+_HT+"macro photography of bird murmuration where individual bird silhouettes "
"and wing alignments subtly spell PATRICK, intricate feather detail, soft bokeh background, "
"extreme close focus","width":1024,"height":1024,"steps":4},
# 5. Tree roots — photoreal
{"id":"phn_05","theme":"tree_roots","style":"photoreal","name":"ancient_tree_roots",
"prompt":_Q+_HT+"ancient oak tree with massive tangled roots and branches that naturally "
"form letters PATRICK in their curves and intersections, forest floor moss and dappled sunlight, "
"hyper realistic bark texture, dramatic directional lighting","width":1024,"height":1024,"steps":4},
# 6. Tree roots — painterly
{"id":"phn_06","theme":"tree_roots","style":"painterly","name":"tree_root_illustration",
"prompt":_Q+_HT+"detailed botanical illustration of tree roots and branches forming hidden "
"PATRICK name through organic growth patterns, ink and watercolor, scientific accuracy with "
"artistic flair, John Muir style","width":1024,"height":1024,"steps":12},
# 7. School of fish
{"id":"phn_07","theme":"fish_school","style":"underwater","name":"fish_school_choreography",
"prompt":_Q+_HT+"underwater scene of thousands of tropical fish in synchronized school, "
"swimming patterns and gaps between bodies form PATRICK, crystal clear tropical water, "
"realistic scales and light caustics, underwater photography","width":1024,"height":1024,"steps":4},
# 8. Architecture — gothic facade
{"id":"phn_08","theme":"architecture","style":"architectural","name":"gothic_facade_hidden",
"prompt":_Q+_HT+"ornate gothic cathedral facade where windows arches and stone carvings "
"subtly align to spell PATRICK in negative space and shadow play, dramatic sunset lighting, "
"ultra detailed stone texture, architectural rendering","width":1024,"height":1024,"steps":4},
# 9. Architecture — aerial
{"id":"phn_09","theme":"architecture","style":"aerial","name":"modern_skyscraper_letters",
"prompt":_Q+_HT+"aerial view of modern city building complex where rooflines shadows and "
"window patterns form the hidden name PATRICK, golden hour, photorealistic architectural "
"rendering, top-down perspective","width":1280,"height":720,"steps":4},
# 10. Coral reef
{"id":"phn_10","theme":"coral_reef","style":"underwater","name":"vibrant_coral_reef",
"prompt":_Q+_HT+"vibrant coral reef ecosystem where branching coral fish and rock formations "
"naturally compose letters PATRICK through color and shape alignment, crystal water, "
"macro detail on polyps and textures, underwater photography","width":1024,"height":1024,"steps":4},
# 11. City skyline at night
{"id":"phn_11","theme":"city_skyline","style":"night","name":"neon_skyline_hidden",
"prompt":_Q+_HT+"futuristic city skyline at night where building lights and window patterns "
"subtly spell PATRICK in the neon glow and negative space between towers, cyberpunk atmosphere, "
"realistic reflections and bokeh, long exposure photography","width":1280,"height":720,"steps":4},
# 12. Rolling hills landscape
{"id":"phn_12","theme":"hills_landscape","style":"aerial","name":"rolling_hills_contours",
"prompt":_Q+_HT+"aerial view of rolling green hills and valleys where landscape contours "
"hedgerows and elevation shadows subtly form PATRICK, golden hour pastoral scene, "
"drone photography style","width":1280,"height":720,"steps":4},
# 13. Persian rug
{"id":"phn_13","theme":"persian_rug","style":"macro","name":"persian_rug_intricate",
"prompt":_Q+_HT+"extremely detailed close-up of hand-woven Persian rug where geometric and "
"floral patterns align to conceal name PATRICK in repeating motifs and negative space, "
"rich colors, silk texture, macro photography","width":1024,"height":1024,"steps":4},
# 14. Butterflies
{"id":"phn_14","theme":"butterflies","style":"painterly","name":"butterfly_swarm_metamorphosis",
"prompt":_Q+_HT+"swarm of colorful butterflies in flight where wing patterns and flight paths "
"collectively form hidden letters PATRICK, ethereal garden setting, detailed wing scales, "
"soft natural light, painterly illustration style","width":1024,"height":1024,"steps":12},
# 15. Circuit board
{"id":"phn_15","theme":"circuit_board","style":"macro","name":"circuit_board_traces",
"prompt":_Q+_HT+"extreme macro of complex multilayer circuit board where copper traces "
"solder points and component placement subtly spell PATRICK in wiring layout, "
"realistic metallic reflections, depth of field, technical precision","width":1024,"height":1024,"steps":4},
# 16. Ocean waves
{"id":"phn_16","theme":"ocean_waves","style":"photoreal","name":"crashing_waves_hidden",
"prompt":_Q+_HT+"dramatic crashing ocean waves where foam spray and wave crests align to "
"reveal name PATRICK in negative space and water movement, powerful seascape, "
"photorealistic water physics and light refraction","width":1280,"height":720,"steps":4},
# 17. Smoke and clouds
{"id":"phn_17","theme":"smoke_clouds","style":"painterly","name":"ethereal_smoke_clouds",
"prompt":_Q+_HT+"ethereal smoke and cloud formations in sky where swirling patterns and "
"negative space subtly spell PATRICK, dramatic volumetric lighting, painterly atmospheric "
"style, high detail turbulence and wisps","width":1024,"height":1024,"steps":12},
# 18. Dense jungle foliage
{"id":"phn_18","theme":"jungle_foliage","style":"macro","name":"dense_jungle_canopy",
"prompt":_Q+_HT+"dense tropical jungle foliage where leaves vines and light rays through "
"canopy form hidden name PATRICK through alignment and negative space, "
"ultra detailed leaf veins and moisture, macro realism","width":1024,"height":1024,"steps":4},
# 19. Roman mosaic
{"id":"phn_19","theme":"roman_mosaic","style":"architectural","name":"roman_mosaic_floor",
"prompt":_Q+_HT+"ancient Roman mosaic floor where thousands of tiny colored tiles arrange "
"to subtly hide name PATRICK in geometric pattern, realistic stone texture, "
"archaeological lighting, high detail tesserae","width":1024,"height":1024,"steps":4},
# 20. Military parade — aerial
{"id":"phn_20","theme":"military_parade","style":"aerial","name":"parade_formation_overhead",
"prompt":_Q+_HT+"aerial view of military parade formation where soldiers in perfect alignment "
"create letters PATRICK through their positions and shadows, crisp uniforms, "
"dramatic overhead perspective, photorealistic","width":1280,"height":720,"steps":4},
# 21. Stained glass
{"id":"phn_21","theme":"stained_glass","style":"architectural","name":"cathedral_stained_glass",
"prompt":_Q+_HT+"intricate stained glass window in gothic cathedral where lead lines and "
"colored glass panes form hidden name PATRICK through negative space and symbolic arrangement, "
"luminous backlighting, ultra detailed glass texture","width":1024,"height":1024,"steps":4},
# 22. Spider web
{"id":"phn_22","theme":"spider_web","style":"macro","name":"dew_spider_web_geometry",
"prompt":_Q+_HT+"macro photograph of perfect orb spider web with morning dew where radial "
"and spiral threads align to spell PATRICK in geometric structure, sparkling water droplets, "
"soft morning light, extreme detail","width":1024,"height":1024,"steps":4},
# 23. Galaxy star map
{"id":"phn_23","theme":"galaxy_stars","style":"cosmic","name":"star_map_constellation",
"prompt":_Q+_HT+"detailed star map of spiral galaxy where constellations and star clusters "
"subtly form letters PATRICK through their positions and connecting lines, "
"nebulae and cosmic dust, astronomical precision","width":1024,"height":1024,"steps":4},
# 24. Subway map
{"id":"phn_24","theme":"subway_map","style":"architectural","name":"subway_network_map",
"prompt":_Q+_HT+"highly detailed schematic subway tunnel map where intersecting colored lines "
"station markers and tunnel curves naturally spell name PATRICK in network layout, "
"clean diagrammatic style with realistic depth","width":1280,"height":720,"steps":4},
# 25. Marionettes — architectural rendering
{"id":"phn_25","theme":"marionettes","style":"architectural","name":"puppet_theater_stage",
"prompt":_Q+_HT+"architectural rendering of elaborate marionette theater stage where puppet "
"strings stage lights and scenery elements form hidden PATRICK, dramatic perspective, "
"ultra detailed wood and fabric","width":1024,"height":1024,"steps":4},
# 26. Birds — painterly
{"id":"phn_26","theme":"birds","style":"painterly","name":"bird_migration_painting",
"prompt":_Q+_HT+"painterly illustration of migrating bird flock where formation creates "
"concealed PATRICK letters, dramatic sky with volumetric clouds, rich oil painting texture, "
"romantic naturalist style","width":1024,"height":1024,"steps":20},
]
# ─────────────────────────────────────────────────────────
# Pipeline helpers (ported from cannamanage_gen.py)
# ─────────────────────────────────────────────────────────
def load_progress() -> Dict[str, Any]:
if PROGRESS_FILE.exists():
try:
with open(PROGRESS_FILE) as f:
return json.load(f)
except (json.JSONDecodeError, IOError):
pass
return {"completed": [], "failed": [], "started_at": time.strftime("%Y-%m-%dT%H:%M:%S")}
def save_progress(progress: Dict[str, Any]) -> None:
OUTPUT_ROOT.mkdir(parents=True, exist_ok=True)
with open(PROGRESS_FILE, "w") as f:
json.dump(progress, f, indent=2)
def load_workflow(model: str) -> Dict:
path = WORKFLOW_HERETIC if model == "heretic" else WORKFLOW_SCHNELL
with open(path) as f:
return json.load(f)
def submit_prompt(comfyui_url: str, workflow: Dict) -> str:
data = json.dumps({"prompt": workflow}).encode()
req = urllib.request.Request(
f"{comfyui_url}/prompt", data=data, headers={"Content-Type": "application/json"}
)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())["prompt_id"]
def wait_for_image(comfyui_url: str, prompt_id: str, timeout: int = 300) -> Optional[Dict]:
print(" ⏳ Waiting for ComfyUI...", end="", flush=True)
start = time.time()
while time.time() - start < timeout:
try:
with urllib.request.urlopen(f"{comfyui_url}/history/{prompt_id}") as resp:
history = json.loads(resp.read())
if prompt_id in history:
print(" done.", flush=True)
outputs = history[prompt_id].get("outputs", {})
for node_out in outputs.values():
if "images" in node_out:
return node_out["images"][0]
return None
except Exception:
pass
print(".", end="", flush=True)
time.sleep(2)
print(" timeout!", flush=True)
return None
def download_image(comfyui_url: str, image_info: Dict, output_path: Path) -> bool:
try:
url = (
f"{comfyui_url}/view"
f"?filename={image_info['filename']}"
f"&subfolder={image_info.get('subfolder', '')}"
f"&type=output"
)
with urllib.request.urlopen(url) as resp:
img_data = resp.read()
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_bytes(img_data)
print(f" ✅ Saved: {output_path} ({len(img_data) // 1024}KB)")
return True
except Exception as e:
print(f" ❌ Download failed: {e}")
return False
def patch_workflow(workflow: Dict, asset: Dict, model: str) -> Dict:
wf = copy.deepcopy(workflow)
seed = random.randint(0, 2**32 - 1)
if model == "heretic":
wf["2"]["inputs"]["text"] = asset["prompt"]
wf["3"]["inputs"]["text"] = "plain text letters, obvious text overlay, watermark, low quality"
wf["6"]["inputs"]["width"] = asset["width"]
wf["6"]["inputs"]["height"] = asset["height"]
wf["7"]["inputs"]["steps"] = asset["steps"]
wf["13"]["inputs"]["filename_prefix"] = asset["name"]
if "10" in wf:
wf["10"]["inputs"]["noise_seed"] = seed
else:
# flux_schnell.json: node 6=pos, 33=neg, 27=latent(w/h), 13=ksampler(steps/seed), 9=save
wf["6"]["inputs"]["text"] = asset["prompt"]
wf["33"]["inputs"]["text"] = "plain text letters, obvious text overlay, watermark, low quality"
wf["27"]["inputs"]["width"] = asset["width"]
wf["27"]["inputs"]["height"] = asset["height"]
wf["13"]["inputs"]["steps"] = asset["steps"]
wf["13"]["inputs"]["seed"] = seed
wf["9"]["inputs"]["filename_prefix"] = asset["name"]
return wf
def generate_asset(comfyui_url: str, asset: Dict, model: str, progress: Dict) -> bool:
if asset["id"] in progress["completed"]:
print(f" ⏭️ Skipping already completed: {asset['name']}")
return True
print(f"\n Prompt : {asset['prompt'][:100]}...")
print(f" Size : {asset['width']}×{asset['height']} Steps: {asset['steps']}")
try:
workflow = load_workflow(model)
workflow = patch_workflow(workflow, asset, model)
prompt_id = submit_prompt(comfyui_url, workflow)
image_info = wait_for_image(comfyui_url, prompt_id)
if not image_info:
progress["failed"].append(asset["id"])
save_progress(progress)
return False
output_dir = OUTPUT_ROOT / asset["theme"] / asset["style"]
output_dir.mkdir(parents=True, exist_ok=True)
output_path = output_dir / f"{asset['name']}.png"
if download_image(comfyui_url, image_info, output_path):
progress["completed"].append(asset["id"])
save_progress(progress)
return True
else:
progress["failed"].append(asset["id"])
save_progress(progress)
return False
except Exception as e:
print(f" ❌ Error: {e}")
progress["failed"].append(asset["id"])
save_progress(progress)
return False
def main():
parser = argparse.ArgumentParser(
description="Patrick Hidden Name Artwork Generation Pipeline"
)
parser.add_argument("--dry-run", action="store_true",
help="Print manifest without generating")
parser.add_argument("--model", choices=["schnell", "heretic"], default="schnell",
help="Model: schnell (~10s/img) or heretic (~52s/img, higher quality)")
parser.add_argument("--comfyui", default="http://localhost:8188",
help="ComfyUI URL")
args = parser.parse_args()
comfyui_url = args.comfyui
print("🚀 Patrick Hidden Name Artwork Pipeline")
print(f" Output : {OUTPUT_ROOT}")
print(f" Model : {args.model}")
print(f" ComfyUI : {comfyui_url}")
print(f" Total : {len(ASSET_MANIFEST)} ultra-detailed hidden-name artworks")
print(" Technique: Letters P-A-T-R-I-C-K concealed via organic shapes/negative space")
if args.dry_run:
print()
for asset in ASSET_MANIFEST:
print(f" {asset['id']:8} | {asset['theme']:15} | {asset['style']:12} | {asset['name']}")
total_est = sum(a["steps"] * 2.5 for a in ASSET_MANIFEST) / 60
print(f"\n ⏱️ Estimated runtime (schnell @4 steps): ~{total_est:.0f} minutes")
print("\nDry run complete. Remove --dry-run to begin generation.")
return
progress = load_progress()
remaining = [a for a in ASSET_MANIFEST if a["id"] not in progress["completed"]]
print(f" Resume : {len(progress['completed'])} completed, "
f"{len(progress['failed'])} failed, {len(remaining)} remaining")
if not remaining:
print("\n✅ All assets already complete!")
return
print(f"\nStarting generation... (Ctrl+C to pause — progress is saved)")
n_done = 0
n_fail = 0
for i, asset in enumerate(ASSET_MANIFEST, 1):
if asset["id"] in progress["completed"]:
continue
print(f"\n[{asset['theme']}/{asset['style']}] [{i}/{len(ASSET_MANIFEST)}] {asset['name']}")
if generate_asset(comfyui_url, asset, args.model, progress):
n_done += 1
else:
n_fail += 1
print("\n" + "=" * 60)
print("🎉 PIPELINE COMPLETE")
print(f" ✅ Completed this run : {n_done}")
print(f" ❌ Failed this run : {n_fail}")
print(f" 📦 Total completed : {len(progress['completed'])} / {len(ASSET_MANIFEST)}")
if progress["failed"]:
print(f" Failed IDs: {', '.join(progress['failed'][-10:])}")
print(f" Assets saved to: {OUTPUT_ROOT}")
print("=" * 60)
if __name__ == "__main__":
main()