AI漫剧制 | 第 25 天:AI漫画动作场景——战斗与动态效果

第 25/60 天

引言

动作场面是漫画最激动人心的部分,也是 AI 漫剧制中最难啃的骨头。静态的 AI 绘画工具默认生成”摆拍”式画面:人物站得笔直、表情呆滞、毫无冲击力。你输入”两个人在打架”,得到的往往是一个人物悬在空中、肢体扭曲、背景干净得像摄影棚的诡异画面。

为什么动作场景这么难?因为漫画的”动感”根本不是画面内元素的运动,而是视觉符号的编码:速度线、冲击波、动态模糊、透视压缩(foreshortening)、多重残影……这些符号是漫画家用手绘语言”欺骗”眼睛的技法。要让 AI 理解并输出这套符号系统,需要把动作场景拆解为「姿态 → 透视 → 特效 → 合成」四个可控制的环节。

本文覆盖:动作场景的构成原理、ControlNet OpenPose/LibrePose 姿态控制、双人战斗分镜的生成管线、速度线与冲击波的后期叠加方案,以及 5 个实战中最高频的翻车问题与修复方法。读完你将能稳定产出”看起来真的在打架”的 AI 漫画分镜。

核心概念

动作场景的四层控制模型

AI 漫画动作场景之所以难,是因为它叠加了四层控制需求,每一层单独可控、又互相影响:

控制层 主要工具 / 技术 解决什么问题
姿态层 ControlNet OpenPose / LibrePose、3D 姿态参考 人物肢体、重心、攻击/受击姿态的骨架控制
空间层 ControlNet Depth / Canny、透视网格 前后景关系、纵深、镜头角度(俯视/仰视/广角)
表现层 动作 LoRA、风格化模型、动态模糊提示词 肌肉张力、残影、夸张变形等”漫画感”
特效层 后期脚本(速度线/冲击波)、img2img 叠加 速度线、放射线、闪光、碎片等动态符号

关键术语速查

  • OpenPose / LibrePose:ControlNet 的姿态检测模型,从参考图提取骨骼关键点,再把骨架喂给生成模型,让 AI 严格按骨架作画。
  • Foreshortening(透视压缩):拳头朝镜头打来时,前臂因透视变短变粗——这是”冲击力”的核心视觉符号。
  • 速度线(Speed Lines):从人物或画面中心放射的平行线,表示快速移动。
  • 集中线(Concentration Lines):从一点向外放射的直线,用于聚焦注意力或表现冲击瞬间。
  • 动态模糊(Motion Blur):运动方向上的拖影,表示高速位移。
  • 残影(Afterimage):前一帧的半透明重影,表现连续动作。
  • 动作 LoRA:专门训练”动态姿势”或”特写战斗”画风的 LoRA,能让基础模型更擅长画夸张姿势。

提示词层面的动态暗示

基础模型只能”认识”它见过的符号。想让它输出动态感,提示词里要写它认识的动作词和画风词

dynamic action pose, mid-air kick, motion lines, speed lines,
impact frame, manga style, dynamic perspective, foreshortening,
battle scene, debris, dust clouds, dramatic lighting, high contrast

关键词优先级:动作动词(kicking / punching / dodging)> 镜头词(dynamic angle / low angle)> 符号词(speed lines / impact)> 风格词(manga / ink)。

实战步骤

下面搭建一条”分镜 → 骨架 → 底图 → 特效 → 合成”的完整动作场景流水线。以双人近身格斗分镜为例。

步骤 1:准备动作素材与 ControlNet 模型

首先确保 WebUI/ComfyUI 已安装 ControlNet 扩展和姿态模型。

# SD WebUI 的 ControlNet 模型目录
CN_DIR="/home/user/sd-webui/models/ControlNet"
mkdir -p "$CN_DIR"

# 下载 OpenPose 姿态模型(约 2.4GB,注意放对目录)
wget -O "$CN_DIR/control_v11p_sd15_openpose.pth" 
  https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_openpose.pth

# 下载为 SDXL 准备的 Union 版(若使用 SDXL 底模)
wget -O "$CN_DIR/controlnet-union-sdxl-1.0.pth" 
  https://huggingface.co/xinsir/controlnet-union-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors

# 验证文件完整性
ls -lh "$CN_DIR"

姿态参考图哪里来?三种途径:① 用 OpenPose 编辑器(WebUI 插件)手工摆骨架;② 在 3D 软件(Blender/Mixamo)摆好姿势渲染线条图;③ 直接搜”fighting pose reference”素材图让 ControlNet 提取骨架。

步骤 2:手工/程序化摆出双人骨架

推荐用 OpenPose 编辑器插件手工摆骨架。骨架 JSON 通过 API 提交时也可用脚本生成,例如下面的简单姿态配置:

{
  "input_image": "/tmp/scene/fight_scene_01.png",
  "module": "openpose",
  "model": "control_v11p_sd15_openpose [cab867d1]",
  "weight": 0.95,
  "guidance_start": 0.0,
  "guidance_end": 0.6,
  "resize_mode": "Resize and Fill",
  "control_mode": "Balanced",
  "pixel_perfect": true,
  "preprocessor_resolution": 512,
  "save_detected_map": true
}
  • weight 建议 0.85–1.0:动作场景骨架是硬约束,权重太低姿势会飘。
  • guidance_end 设 0.6 左右:让模型在前 60% 采样步数严格跟骨架,后面留出细节自由度,避免手脚僵硬。

步骤 3:用 Python 批量生成战斗分镜

写一个 Python 脚本调用 WebUI 的 API,用”同一角色 LoRA + 固定颜色 prompt + 不同骨架图”批量出图,保证多格战斗的分镜连续性。

#!/usr/bin/env python3
"""批量生成战斗分镜:同一角色、多个骨架图"""
import base64
import json
import time
import urllib.request

WEBUI_URL = "http://127.0.0.1:7860/sdapi/v1/img2img"
BONES = ["/tmp/scene/punch_a.png", "/tmp/scene/dodge_b.png", "/tmp/scene/kick_c.png"]

def b64(path: str) -> str:
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode()

def gen_panel(bone_path: str, out_path: str, panel_no: int):
    payload = {
        "init_images": [b64(bone_path)],
        "prompt": (
            "1boy, black haired martial artist, dynamic punch, motion lines, "
            "speed lines, manga style, ink, dynamic perspective, " 
            "lora:action_pose_v1:0.8, <lora:myhero:0.9>"
        ),
        "negative_prompt": "blurry, deformed hands, extra limbs, static pose, photorealistic",
        "steps": 28,
        "cfg_scale": 7,
        "width": 768,
        "height": 1080,
        "batch_size": 2,
        "seed": 20260819,          # 固定种子,跨格风格更稳
        "override_settings": {"sd_model_checkpoint": "counterfeitXL_v25.safetensors"},
        "alwayson_scripts": {
            "controlnet": {"args": [{"input_image": b64(bone_path),
                                     "module": "openpose", "weight": 0.95}]}
        },
    }
    req = urllib.request.Request(WEBUI_URL, data=json.dumps(payload).encode(),
                                 headers={"Content-Type": "application/json"})
    resp = json.loads(urllib.request.urlopen(req).read())
    for i, img_b64 in enumerate(resp["images"]):
        with open(f"{out_path}_p{panel_no}_{i}.png", "wb") as f:
            f.write(base64.b64decode(img_b64))
    time.sleep(1.5)

for idx, bone in enumerate(BONES, 1):
    gen_panel(bone, "/tmp/scene/output", idx)
    print(f"panel {idx} done")

要点:固定 seed + 固定角色 LoRA + 相同的画风 prompt,三管齐下保证跨格角色一致;每张骨架图出 2 张候选,便于挑选。

步骤 4:用 ComfyUI 工作流串联(YAML 片段)

ComfyUI 场景下用节点图实现同样的管线。以下是工作流关键节点的配置片段(可导入 ComfyUI 后调整):

workflow: 战斗分镜_双人_标准
nodes:
  - id: 1
    type: CheckpointLoaderSimple
    params: { ckpt_name: "counterfeitXL_v25.safetensors" }
  - id: 2
    type: LoraLoader
    params: { lora_name: "myhero.safetensors", strength_model: 0.9, strength_clip: 0.8 }
  - id: 3
    type: ControlNetLoader
    params: { control_net_name: "control_v11p_sd15_openpose.pth" }
  - id: 4
    type: ControlNetApply
    params: { strength: 0.95, start_percent: 0.0, end_percent: 0.65 }
  - id: 5
    type: KSampler
    params: { seed: 20260819, steps: 28, cfg: 7, sampler_name: "dpmpp_2m", scheduler: "karras" }
  - id: 6
    type: SaveImage
    params: { filename_prefix: "fight_panel" }

ComfyUI 的优势是可以用 Batch 节点一次处理多张骨架图,连接 LoadImage (batch)ControlNetApplyKSampler,一次跑完全部分镜。

步骤 5:用 Python (PIL) 叠加速度线与冲击波

AI 生成的速度线往往不够”炸”。最可靠的做法是后期程序化叠加:放射集中线 + 冲击波圆环 + 拖影。

#!/usr/bin/env python3
"""给静态分镜叠加动态符号:集中线 + 冲击波 + 拖影"""
from PIL import Image, ImageDraw, ImageFilter
import math, random

SRC, DST = "/tmp/scene/output_p1_0.png", "/tmp/scene/panel_final.png"
img = Image.open(SRC).convert("RGBA")
W, H = img.size
overlay = Image.new("RGBA", img.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(overlay)

cx, cy = 380, 540   # 冲击中心(拳头的落点)

# 1. 集中线:从中心向外放射的细线
for _ in range(120):
    ang = random.uniform(0, 2 * math.pi)
    r1 = random.uniform(20, 60)
    r2 = random.uniform(150, 900)
    x1, y1 = cx + r1 * math.cos(ang), cy + r1 * math.sin(ang)
    x2, y2 = cx + r2 * math.cos(ang), cy + r2 * math.sin(ang)
    draw.line([x1, y1, x2, y2], fill=(0, 0, 0, 110), width=2)

# 2. 冲击波圆环
for r, w, alpha in [(90, 10, 160), (130, 6, 110), (170, 4, 70)]:
    draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=(255, 255, 255, alpha), width=w)

# 3. 拖影:把原图沿运动方向微移并叠加半透明层
ghost = img.copy().transform(img.size, Image.AFFINE, (1, 0, -40, 0, 1, 0))
ghost.putalpha(90)
ghost = ghost.filter(ImageFilter.GaussianBlur(6))

final = Image.alpha_composite(ghost, img)
final = Image.alpha_composite(final, overlay)
final.convert("RGB").save(DST)
print(f"saved: {DST}")

参数随镜头语言调整:横向闪避用平行速度线(水平方向拉线),爆发冲击用集中线与圆环叠加,高速冲刺则把拖影位移加大到 60–100px。

步骤 6:批处理与出片

最后统一尺寸、加网点/出血框、导出 PNG 序列给排版脚本:

# 统一 768x1080 裁切并转为灰度线稿风格测试(可选)
mkdir -p /tmp/scene/final
for f in /tmp/scene/output_*.png; do
  convert "$f" -resize 786x1104^ -gravity center -extent 768x1080 
    -unsharp 0x1.5 /tmp/scene/final/$(basename "$f")
done

# 生成接触表(contact sheet)供挑选分镜
montage /tmp/scene/final/*.png -tile 3x2 -geometry +8+8 /tmp/scene/contact_sheet.jpg
echo "批量处理完成: $(ls /tmp/scene/final | wc -l) 张分镜"

常见问题

Q1:AI 生成的打斗姿势总是扭曲、手部崩坏怎么办?
动作姿势越夸张,模型越容易崩。三个对策:① ControlNet 的 weight 提到 0.95+,guidance_end 降到 0.5–0.6,让骨架约束占主导;② 给动态姿势装动作 LoRA,专门拯救”模型没见过的高难度姿势”;③ 把手部动作拆成独立步骤——先用骨架图层生成全景,再对含手的区域用 inpaint 局部重绘(提示词 perfect hands, dynamic fist)。

Q2:同一角色在打架时”换了个人”?
动作幅度大时角色特征最容易漂移。核心理由是姿态变化导致面部特征采样不稳定。修复组合拳:固定 seed + 角色 LoRA(权重 0.8–1.0)+ IP-Adapter 绑定角色参考图 + 提示词里固定发色/服装描述词。四者缺一不可,尤其 IP-Adapter 对大幅度姿态变化下的身份保持效果显著。

Q3:速度线、冲击波画不出来,或生成后像”贴在照片上的贴纸”?
提示词可以尝试,但别指望它稳定。把动态符号当成后期层:用本文步骤 5 的脚本程序化生成,或者准备一套速度线/网点 PNG 素材(网上有大量透明底素材),用 PS/图像合成叠上去。后期叠加的另一个好处是线条方向可控——AI 生成的速度线经常方向混乱。

Q4:多人战斗场景两个人”融在一起”、分不开?
一张图里两个角色靠骨架图是不够的,模型分不清谁是谁。推荐方案:分角色分层生成——先单独生成角色 A 的动作图,再单独生成角色 B,最后用合成/深度图拼场景,或用 Segment Anything 分割后合成。进阶做法:用 Photoshop 的 AI 填充或 inpaint 把两个角色分别放在画面左右 1/3 处(构图避让),中间留出”对撞空间”放冲击特效,既清晰又有张力。

Q5:做出来的战斗分镜没有”镜头感”,像摆拍?
摆拍感的根源是缺乏透视张力。检查三点:① 有没有用仰角/俯角(提示词加 low angle shotbird's eye view);② 有没有透视压缩——向前出拳的角色前臂应该短而粗(foreshortening),不行就手动修;③ 画面是否缺少速度感符号——哪怕姿势对,没有速度线/拖影就看起来像静止摆拍。后期层(速度线+拖影)永远是兜底的”动感保险”。

总结

  • 动作场景 = 姿态控制 + 镜头透视 + 动态符号,三者缺一不可;AI 能做好前两项,最后一项(速度线、冲击波)建议后期程序化叠加,稳定又可控。
  • ControlNet OpenPose 是动作分镜的地基,权重 0.9+、结束步数 0.6 是经过验证的”硬约束”参数组合,防止姿势漂移。
  • 固定 seed + 角色 LoRA + IP-Adapter + 固定的人物描述词是跨格战斗分镜角色一致性的四件套,缺一个就”换人”。
  • AI 生成建议”出图优先、特效后置”:先生成干净的姿态底图,再用脚本/PS 叠加速度线、集中线、冲击波和拖影,后期层完全可控,还能随意调整方向与强度。
  • 多人打斗按”分角色分层生成 → 合成“进行,比让 AI 一次画两个人失败率低得多;对撞空间留给特效层,画面既清晰又充满张力。

动作场景一旦掌握了这条流水线,你的 AI 漫画就能从”人物插画集”升级为”真正的漫画”——下一期我们将继续攻克第 26 天:AI漫画色彩风格统一,让整部作品的颜色体系牢固而高级。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容