首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MJ + SD 双引擎工程实践:从审美探索到可控交付的完整管线

MJ + SD 双引擎工程实践:从审美探索到可控交付的完整管线

原创
作者头像
资源大佬 jzit-top
发布于 2026-10-16 17:39:22
发布于 2026-10-16 17:39:22
260
举报

Midjourney 和 Stable Diffusion 常被放在一起比较,但专业团队从不二选一。MJ 强在审美先验、构图直觉和出图速度;SD 强在可控性、局部编辑和批量自动化。真正的生产力,是把两者放进同一条管线:MJ 做创意探索与氛围定调,SD 做精修、一致性与规模化输出。

一、双引擎分工逻辑

环节

推荐工具

原因

概念探索

Midjourney

风格多样、构图大胆、迭代快

角色/风格锁定

SD + LoRA

可训练、可复现、一致性强

构图控制

SD + ControlNet

姿态、线稿、深度精确控制

局部修改

SD Inpainting

蒙版级重绘,不破坏整体

批量放大

SD + ESRGAN

本地免费、可脚本化

核心原则:MJ 产出参考图,SD 产出可交付资产。

二、MJ 侧:参数化探索与缓存

Midjourney 官方无公开 API,专业团队通常通过第三方网关调用。生产管线的核心是任务提交 → 轮询 → 结果落盘,并保留提示词与种子以便复现:

代码语言:javascript
复制
import os, time, requests, json, hashlib, pathlib

BASE = "https://api.goapi.ai/mj/v2"
H = {"X-API-Secret": os.getenv("MJ_KEY"), "Content-Type": "application/json"}

def mj_run(prompt, aspect="1:1", version="6.1", mode="relax"):
    r = requests.post(f"{BASE}/imagine", headers=H, json={
        "prompt": prompt, "aspect_ratio": aspect,
        "version": version, "process_mode": mode,
    }).json()
    tid = r["task_id"]
    while True:
        s = requests.get(f"{BASE}/fetch", headers=H,
                         params={"task_id": tid}).json()
        if s["status"] == "finished":
            return s["task_result"]["image_urls"]
        if s["status"] == "failed":
            raise RuntimeError(s.get("message"))
        time.sleep(5)

def cache_prompt(prompt, urls, out="mj_cache"):
    pathlib.Path(out).mkdir(exist_ok=True)
    key = hashlib.md5(prompt.encode()).hexdigest()[:10]
    for i, u in enumerate(urls):
        p = f"{out}/{key}_{i}.png"
        if not os.path.exists(p):
            open(p, "wb").write(requests.get(u).content)
    json.dump({"prompt": prompt, "urls": urls},
              open(f"{out}/{key}.json", "w"), ensure_ascii=False)
    return f"{out}/{key}_0.png"

要点:--style raw 降低默认美化,--sref 做风格迁移,--cref 做角色一致性。V8.2 在参数面上与 V8.1 完全一致,迁移只需替换版本号。

三、SD 侧:LoRA 风格锁定

确定方向后,用 SD 锁定风格。LoRA 的价值在于:同一个触发词,跨批次产出高度一致的视觉语言,这是 MJ 难以稳定做到的:

代码语言:javascript
复制
import requests, base64

API = "http://127.0.0.1:7860"

def txt2img(prompt, negative, lora, seed=42, steps=30):
    payload = {
        "prompt": f"{prompt}, <lora:{lora}:0.8>",
        "negative_prompt": negative,
        "seed": seed, "steps": steps,
        "width": 1024, "height": 576,
        "cfg_scale": 6.5,
        "sampler_name": "DPM++ 2M Karras",
    }
    r = requests.post(f"{API}/sdapi/v1/txt2img",
                      json=payload, timeout=300)
    r.raise_for_status()
    img = r.json()["images"][0]
    with open("sd_output.png", "wb") as f:
        f.write(base64.b64decode(img.split(",", 1)[-1]))

四、桥梁:IP-Adapter 与 ControlNet 双重约束

MJ 与 SD 的协同不是简单接力,而是一次能力解耦:MJ 作为“视觉语义引擎”提供高审美参考,SD 作为“可控渲染引擎”完成像素级交付。

IP-Adapter 负责风格注入——把 MJ 参考图编码为 image embedding,拼接到文本 embedding 后送入 UNet:

代码语言:javascript
复制
import torch
from PIL import Image
from diffusers import StableDiffusionXLPipeline, DDIMScheduler
from transformers import CLIPVisionModelWithProjection

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    torch_dtype=torch.float16,
    image_encoder=CLIPVisionModelWithProjection.from_pretrained(
        "h94/IP-Adapter", subfolder="models/image_encoder",
        torch_dtype=torch.float16),
).to("cuda")

pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models",
                     weight_name="ip-adapter_sdxl.bin")
pipe.set_ip_adapter_scale(0.6)  # 0.4~0.7 为常用区间

ref = Image.open("mj_cache/style_0.png").convert("RGB")
out = pipe(
    prompt="luxury perfume bottle, marble, studio lighting, 8k",
    negative_prompt="text, watermark, deformed",
    ip_adapter_image=ref,
    num_inference_steps=30, guidance_scale=7.5,
).images[0]

ControlNet 负责结构约束——从 MJ 图提取 Canny 边缘或深度图,锁定空间结构:

代码语言:javascript
复制
import cv2, numpy as np
from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel

cn = ControlNetModel.from_pretrained(
    "diffusers/controlnet-depth-sdxl-1.0", torch_dtype=torch.float16)
pipe2 = StableDiffusionXLControlNetPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    controlnet=cn, torch_dtype=torch.float16).to("cuda")
pipe2.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models",
                      weight_name="ip-adapter_sdxl.bin")
pipe2.set_ip_adapter_scale(0.5)

edges = cv2.Canny(np.array(ref), 100, 200)
cond = np.stack([edges] * 3, axis=-1)

final = pipe2(
    prompt="premium product shot, brand style, soft light",
    image=cond, ip_adapter_image=Image.fromarray(np.array(ref)),
    controlnet_conditioning_scale=0.7,
    num_inference_steps=30, guidance_scale=7.5,
).images[0]

ip_adapter_scale 过高会照抄参考图,过低则风格漂移,0.6 是经验起点。双适配器叠加时,通常风格 0.5、结构 0.7,避免互相压制。

五、生产管线:可追溯与幂等

把 MJ prompt、SD prompt、LoRA、ControlNet 权重、种子全部纳入版本管理:

代码语言:javascript
复制
import hashlib, json
from dataclasses import dataclass, asdict

@dataclass
class Job:
    mj_prompt: str
    sd_prompt: str
    ip_scale: float
    cn_scale: float
    seed: int

def jid(j):
    return hashlib.md5(json.dumps(asdict(j), sort_keys=True)
                       .encode()).hexdigest()[:12]

每一次生成都记录 job id,任何一张输出都能回放。MJ 负责“想到”,SD 负责“做到”,把两者纳入同一条可复现的管线,AI 绘画才能从灵感游戏变成可规模化的生产力。

六、合规底线

确认模型许可证与训练数据来源,商用前核查;不得模仿受保护 IP 与真人肖像;AI 生成内容按平台要求标注;客户素材需获得授权,禁止未授权图生图。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、双引擎分工逻辑
  • 二、MJ 侧:参数化探索与缓存
  • 三、SD 侧:LoRA 风格锁定
  • 四、桥梁:IP-Adapter 与 ControlNet 双重约束
  • 五、生产管线:可追溯与幂等
  • 六、合规底线
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档