feat(mcp): update bigmind/mcp-image-gen/webscraper servers; add image-gen batch scripts
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user