Guest User

Untitled

a guest
Apr 20th, 2025
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.28 KB | Source Code | 0 0
  1. import os
  2. import json
  3. import base64
  4. import re
  5. from PIL import Image
  6. import requests
  7.  
  8. def sanitize_filename(prompt):
  9. """Очистка имени файла с учётом максимальной длины 146 символов"""
  10. forbidden_chars = r'[\\/:\*\?"<>\|]'
  11. sanitized = re.sub(forbidden_chars, '_', prompt)
  12. sanitized = sanitized.strip().rstrip('.')
  13.  
  14. # Рассчёт максимальной длины для промпта
  15. max_prompt_length = 125 # 146 - (5+1+10+1+4) = 125
  16. if len(sanitized) > max_prompt_length:
  17. sanitized = sanitized[:max_prompt_length].rsplit(' ', 1)[0]
  18.  
  19. return sanitized or 'generated_image'
  20.  
  21. def get_next_counter(output_dir):
  22. max_num = -1
  23. if os.path.exists(output_dir):
  24. for fname in os.listdir(output_dir):
  25. if match := re.match(r'^(\d{5})-\d+', fname):
  26. num = int(match.group(1))
  27. max_num = max(max_num, num)
  28. return max_num + 1 if max_num != -1 else 0
  29.  
  30. def parse_parameters(parameters_str):
  31. lines = [line.strip() for line in parameters_str.split('\n') if line.strip()]
  32.  
  33. prompt = lines[0] if lines else ""
  34. negative_prompt = ""
  35. params = {}
  36.  
  37. current_line = 1
  38.  
  39. if current_line < len(lines) and lines[current_line].startswith("Negative prompt:"):
  40. negative_prompt = lines[current_line].split(":", 1)[1].strip()
  41. current_line += 1
  42.  
  43. params_block = " ".join(lines[current_line:])
  44. param_pattern = r"([\w\s\+\-]+?):\s*([^,\n]+)"
  45.  
  46. for match in re.finditer(param_pattern, params_block):
  47. key = match.group(1).strip()
  48. value = match.group(2).strip()
  49. params[key] = value
  50.  
  51. return prompt, negative_prompt, params
  52.  
  53. def get_input(prompt, validation_func, error_message):
  54. while True:
  55. value = input(prompt)
  56. if validation_func(value):
  57. return value
  58. print(error_message)
  59.  
  60. def generate_images():
  61. input_dir = get_input(
  62. "Введите путь к папке с исходными картинками: ",
  63. lambda x: os.path.isdir(x),
  64. "Ошибка: директория не существует!"
  65. )
  66.  
  67. output_dir = get_input(
  68. "Введите путь для сохранения новых картинок: ",
  69. lambda x: True,
  70. ""
  71. )
  72.  
  73. num_generations = int(get_input(
  74. "Введите количество генераций (включая исходную): ",
  75. lambda x: x.isdigit() and int(x) > 0,
  76. "Ошибка: введите целое число больше 0!"
  77. ))
  78.  
  79. os.makedirs(output_dir, exist_ok=True)
  80. global_counter = get_next_counter(output_dir)
  81. processed_files = 0
  82.  
  83. for filename in os.listdir(input_dir):
  84. input_path = os.path.join(input_dir, filename)
  85.  
  86. if not os.path.isfile(input_path) or not filename.lower().endswith('.png'):
  87. continue
  88.  
  89. print(f"\n{'='*40}\nProcessing file: {filename}")
  90.  
  91. try:
  92. with Image.open(input_path) as img:
  93. parameters_str = img.info.get('parameters', '')
  94.  
  95. if not parameters_str:
  96. print("Skipped: No parameters found")
  97. continue
  98.  
  99. prompt, negative_prompt, params = parse_parameters(parameters_str)
  100.  
  101. required_params = ['Seed', 'Steps', 'Sampler', 'CFG scale', 'Size']
  102. missing = [p for p in required_params if p not in params]
  103.  
  104. if missing:
  105. raise KeyError(f"Missing parameters: {', '.join(missing)}")
  106.  
  107. original_seed = int(params['Seed'])
  108. steps = int(params['Steps'])
  109. sampler = f"{params['Sampler']} {params.get('Schedule type', '')}".strip()
  110. cfg_scale = float(params['CFG scale'])
  111. width, height = map(int, params['Size'].split('x'))
  112.  
  113. for i in range(num_generations):
  114. current_seed = original_seed + i
  115.  
  116. payload = {
  117. "prompt": prompt,
  118. "negative_prompt": negative_prompt,
  119. "steps": steps,
  120. "sampler_name": sampler,
  121. "cfg_scale": cfg_scale,
  122. "width": width,
  123. "height": height,
  124. "seed": current_seed,
  125. }
  126.  
  127. response = requests.post("http://localhost:7860/sdapi/v1/txt2img", json=payload)
  128. response.raise_for_status()
  129. result = response.json()
  130.  
  131. image_data = base64.b64decode(result['images'][0])
  132. info = json.loads(result.get('info', '{}'))
  133. used_seed = info.get('seed', current_seed)
  134.  
  135. clean_prompt = sanitize_filename(prompt)
  136. output_filename = f"{global_counter:05}-{used_seed}-{clean_prompt}.png"
  137.  
  138. # Финальная проверка длины имени файла
  139. if len(output_filename) > 146:
  140. raise ValueError(f"Слишком длинное имя файла: {len(output_filename)} символов (макс. 146)")
  141.  
  142. output_path = os.path.join(output_dir, output_filename)
  143.  
  144. with open(output_path, 'wb') as f:
  145. f.write(image_data)
  146.  
  147. print(f"Generated: {output_filename} ({len(output_filename)} chars)")
  148. global_counter += 1
  149.  
  150. processed_files += 1
  151.  
  152. except KeyError as e:
  153. print(f"ERROR: {e}")
  154. print("Available parameters:", json.dumps(params, indent=2))
  155. except Exception as e:
  156. print(f"ERROR: {str(e)}")
  157.  
  158. print(f"\n{'='*40}")
  159. print(f"Обработка завершена!")
  160. print(f"Всего обработано файлов: {processed_files}")
  161. print(f"Сгенерировано изображений: {global_counter - get_next_counter(output_dir)}")
  162.  
  163. if __name__ == "__main__":
  164. generate_images()
Add Comment
Please, Sign In to add comment