LLM + 图像处理的第一步:用自然语言驱动调色逻辑

一、起因:调色不该这么复杂

图像调色虽然看似只是微调一些滑块,实际上涉及多个关联参数:色温、亮度、对比度、饱和度、阴影、高光等等。对于普通用户来说,这些名词本身就不够直观,更别说理解它们之间的相互影响。即便是熟悉图像处理的用户,调出理想效果也往往需要多次尝试与回退。

我在开发图像编辑器 Monica(github.com/fengzhizi71...) 的过程中,一直希望降低调色门槛。于是,我开始尝试一个思路:能否用自然语言来驱动参数,让用户说一句话,比如"让肤色冷一点",系统就能自动完成一系列合理的参数调整?

随着近年来大模型(LLM)在语言理解和结构化输出方面的能力逐渐成熟,这个目标不再只是想象。我尝试接入一个 LLM 模型,为 Monica 增加一个「自然语言调色助手」。

二、我的方案:LLM + 参数结构

为了让大模型具备调色能力,我使用了 DeepSeek 提供的 API 接口。它支持中文自然语言输入,并且能够输出结构化 JSON 格式,便于程序直接解析使用。

用户每次输入一句自然语言指令,比如"肤色偏黄,冷一点",我会将当前的调色参数作为上下文信息,一起发送给模型。模型返回的结果是一组结构化的参数调整结果,例如:

json 复制代码
{
  "temperature": 200,
  "status": 5
}

其中各项参数值直接对应 Monica 的定义好的调色参数结构 ColorCorrectionSettings:

kotlin 复制代码
data class ColorCorrectionSettings(
    val contrast:Int = 255,     // 对比度,范围 0-510
    val hue:Int = 180,          // 色调,范围 0-360
    val saturation:Int = 255,   // 饱和度,范围 0-510
    val lightness:Int = 255,    // 亮度,范围 0-510
    val temperature:Int = 255,  // 色温,范围 0-510
    val highlight:Int = 255,    // 高光,范围 0-510
    val shadow:Int = 255,       // 阴影,范围 0-510
    val sharpen:Int = 0,        // 锐化,范围 0-255
    val corner:Int = 0,         // 暗角,范围 0-255

    val status:Int = 0 // 1 contrast, 2 hue, 3 saturation, 4 lightness, 5 temperature, 6 highlight, 7 shadow, 8 sharpen, 9 corner
)

所以每次调用后,模型会返回完整参数对象,我只需用返回的调色参数来更新图像效果。为了便于 UI 提示用户「这次改了什么」,ColorCorrectionSettings 恰好有一个辅助字段 status,用来标识当前轮被重点修改的参数,例如 status=5 表示"色温"发生了变化。

这套机制简单、稳定,并且可以自然支持"多轮会话",是后续构建交互式调色系统的基础。

三、关键实现点

3.1 Prompt 设计:构造有上下文的对话输入

为了让大模型理解并正确生成调色参数,我构造了一个包含当前参数上下文的 prompt。请求结构分为两部分:

  • system 消息:定义模型角色。例如:
swift 复制代码
"你是一个图像调色助手。用户会输入一句话,你需要将这句话转换为一组 JSON 格式的调色参数,字段说明如下:\\n\\n- contrast: 对比度,整数,范围 0 - 510,默认值 255。\\n- hue: 色调,整数,范围 0 - 360,默认值 180。\\n- saturation: 饱和度,整数,范围 0 - 510,默认值 255。\\n- lightness: 亮度,整数,范围 0 - 510,默认值 255。\\n- temperature: 色温,整数,范围 0 - 510,默认值 255。\\n- highlight: 高光,整数,范围 0 - 510,默认值 255。\\n- shadow: 阴影,整数,范围 0 - 510,默认值 255。\\n- sharpen: 锐化,整数,范围 0 - 255,默认值 0。\\n- corner: 暗角,整数,范围 0 - 255,默认值 0。\\n- status: 表示用户意图主要修改了哪一项(用于前端高亮显示),值如下:\\n  - 1 表示 contrast\\n  - 2 表示 hue\\n  - 3 表示 saturation\\n  - 4 表示 lightness\\n  - 5 表示 temperature\\n  - 6 表示 highlight\\n  - 7 表示 shadow\\n  - 8 表示 sharpen\\n  - 9 表示 corner\\n\\n要求:\\n- 不要输出解释。\\n- 严格输出 JSON 格式,字段顺序与上方一致。\\n- 如果用户输入不涉及某些参数,请保留默认值。\\n- 请根据语义合理推测用户意图。"
  • user 消息:拼接当前调色参数 + 用户输入的自然语言指令,格式如下:
makefile 复制代码
当前调色参数如下:
contrast: 255
hue: 180
...
用户指令:"让肤色冷一点"

这种组合方式可以让模型理解当前状态,并生成"增量式"的调整结果,避免从头生成。

3.2 多轮对话:基于当前参数持续调整

每次用户提交一句新指令,我会把上一次生成的参数作为"当前状态"传入下一轮请求中,实现连续调色。例如用户可以连续说:

  • "再亮一点"
  • "肤色更自然一点"
  • "暗角加重一些"

每轮模型输出的结果都会被解析为新的 ColorCorrectionSettings,并作为下一轮上下文继续参与交互。这种机制模拟了"连续对话中的状态记忆",用户无需重复说明所有内容。

我在客户端维护了一个 DialogSession 会话状态对象,这种方式避免了用户重复描述,也使模型具备了"记忆能力",调色过程更加连贯自然。

kotlin 复制代码
data class DialogSession(
    val systemPrompt: String,
    var currentSettings: ColorCorrectionSettings,
    val history: MutableList<Pair<String, ColorCorrectionSettings>> = mutableListOf()
)

3.3 Compose 弹窗组件:对话式调色界面

在 UI 层,我基于 Kotlin Compose 实现了一个轻量级的弹出对话框组件。主要功能包括:

  • 输入自然语言指令;
  • 调用 DeepSeek API 并异步等待响应;
  • 显示当前会话的历史记录(用户输入 + 模型响应);
  • 将参数更新实时传回图像处理模块,触发图像调整。

用户只需和"调色助手"对话,不再需要直接操作一堆滑块。

下面的代码展示了如何通过跟 DeepSeek 的 API 进行多轮对话,获取对应的调色参数,并把用户指令和调色参数保存。(省略了网络请求和解析 json 对象)

替换成其他的大模型也是类似的,比如换成 OpenAI 的 API 只要改少许代码即可。

kotlin 复制代码
/**
 * 每次根据当前参数和新指令拼 prompt, 支持多轮对话
 */
@Throws(MonicaException::class)
suspend fun applyInstructionWithLLM(
    session: DialogSession,
    instruction: String,
    apiKey: String
): ColorCorrectionSettings? {
    val prompt = buildString {
        append("当前图像的参数如下:\n")
        append(GsonUtils.toJson(session.currentSettings))
        append("\n\n")
        append("用户指令:$instruction")
    }
    val messages = mutableListOf<DeepSeekMessage>().apply {
        this.add(DeepSeekMessage(role = "system", content = systemPromptForColorCorrection))
        this.add(DeepSeekMessage(role = "user", content = prompt))
    }
    val deepSeekRequest = DeepSeekRequest("deepseek-chat", messages, false)
    val payload = GsonUtils.toJson(deepSeekRequest)

    val responseJson = sendPostJson(
        url = "https://api.deepseek.com/chat/completions",
        headers = mapOf("Content-Type" to "application/json",
            "Authorization" to "Bearer $apiKey"),
        body = payload
    )

    try {
        val json = extractJson(responseJson)
        val responseObj = GsonUtils.fromJson<ColorCorrectionSettings>(json, ColorCorrectionSettings::class.java)

        session.currentSettings = responseObj
        session.history.add(Pair(instruction, responseObj)) // 保存用户指令、调色参数
        return responseObj
    } catch (e: Exception) {
        logger.error("responseJson = $responseJson")
        logger.error(e.message, e)
        throw MonicaException("无法获取调色的参数")
    }
}

效果演示:

四、小结与展望

这次尝试只是一个起点,我用最简单的方式让 Monica 图像编辑器具备了自然语言调色的能力。借助大模型对中文语义的理解能力,用户无需理解"色温"、"对比度"等专业术语,只需要一句话就能驱动参数调整。

从技术实现上看,结构化参数 + prompt 工程 + 多轮上下文状态,是搭建语言驱动交互的关键几个要素。它也证明了传统图像处理工具完全可以与 LLM 接轨,提升交互体验,而不一定非要端到端"全自动"。

下一步,我可能会尝试接入更丰富的视觉模型,实现更多的功能,继续探索「自然语言 × 图像编辑」的边界。我也可能会考虑在本地部署 LLM,以提升响应速度和可控性。

图像编辑器 Monica 的地址:github.com/fengzhizi71...

相关推荐
冬奇Lab4 小时前
Agent 系列(13):Agent 安全与防护——提示词注入、工具滥用、数据泄露怎么防
人工智能·llm·agent
_不会dp不改名_7 小时前
python-opencv环境搭建
开发语言·python·opencv
北暮城南7 小时前
使用 Claude Code 高效实现图像边缘检测:多算法对比与工程实践
python·opencv·numpy·matplotlib·边缘检测·claude code
装不满的克莱因瓶7 小时前
学习并掌握 LangChain 检索器的作用,实现让 LLM 动态调用知识库功能
人工智能·python·ai·langchain·llm·agent·智能体
惟愿光怪陆离8 小时前
OpenCode 注意事项
llm
初旭save12 小时前
Agent Skill 不是写 Prompt,是给 LLM 做存储分层
llm·agent·claude
AINative软件工程15 小时前
LLM 应用的 Rate Limiting 工程实战:Per-User Token 配额、滑动窗口限流与优先级队列的生产落地
llm
盼小辉丶17 小时前
OpenCV-Python实战(25)——基于深度传感器与凸性分析打造实时手势识别系统
人工智能·python·opencv·计算机视觉
晨欣1 天前
Claude Opus 4.8:模型小幅升级,平台大步向前
llm·claude·anthropic·claude code·harness
AI浩1 天前
OpenCV 检测流程中损坏 JPEG 图片的定位与清理
人工智能·opencv·计算机视觉