news 2026/9/30 12:53:11

风-水电联合优化运行分析的Matlab复现指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
风-水电联合优化运行分析的Matlab复现指南

做风-水电联合优化的人应该都有同感:单独看风电,随机性、间歇性大到让人头疼;单独看水电,又受来水、水库调节能力和生态流量约束。但把两者放在同一个调度框架里做联合优化运行分析,往往能在几乎不新增硬件投资的情况下,把系统的灵活性和可再生能源消纳空间拉高一大截。用Matlab来做这块的代码复现,是我个人觉得性价比最高的路径。

这篇文章就围绕“风-水电联合优化运行分析”这个标题,把EI论文里常出现的建模思路、目标函数与约束条件怎么落地成Matlab代码、求解器怎么选、结果怎么验证、以及复现过程中最容易踩的坑全部过一遍。适合正在复现论文、做课程设计、或者准备写小论文的电力方向研究生,也适合想快速上手调度优化模型的工程师参考。

1. 先说清楚:风-水电联合优化运行到底在解决什么问题

1.1 为什么风电场要跟水电站“绑”在一起

风电出力靠天吃饭,风速曲线长什么样,出力就长什么样,基本没有太多人工干预的空间。水电则不同,只要水库有足够调节库容,机组出力可以在一定范围内快速调节。

把这两个电源放在一个调度模型里,核心思路是:用可控性好、响应速度快的水电,去平抑风电的波动和预测误差。风电大发的时候,水库少放水、多蓄水;风电小发的时候,水库多放水、补足缺口。这样一来,电网调度看到的是一条更平稳的外送功率曲线,原先不得不弃掉的风电也能被吸收进系统。

这在术语里叫“互补运行”,但你要真去复现论文就会发现,难点不在概念,而在模型。水文过程有水量平衡,风电有预测误差,两者耦合在一起之后,约束条件呈指数级膨胀,调度时段一旦取到96点甚至288点,普通Excel根本算不动,必须依靠Matlab这样的数值计算环境。

1.2 EI论文里最常见的三类模型

我在复现不同文献时,发现风-水电联合优化模型的差别主要在三处:时间尺度、目标函数、不确定性处理方式。给你一个速查表:

模型类型典型时间尺度目标函数常见求解方法
长期调度月/旬发电量最大、蓄能最大DP、逐次逼近
短期调度日/96点运行成本最小、弃风最小MILP、NLP
实时/滚动15min级跟踪计划偏差最小MPC、鲁棒优化

真正的EI复现,绝大多数集中在“短期调度”这一档。再往上,文献会在这个框架里叠加风电不确定性,产生两类变体:

  • 场景法:用蒙特卡洛抽样生成大量风电出力场景,然后用场景削减技术浓缩成几个典型场景,模型变成随机规划。
  • 鲁棒法:不关心具体概率分布,只给风电出力一个波动区间,模型追求最坏情况下的调度可行性。

这两条路线在Matlab里的实现路径差别很大,后文我会分别讲怎么处理。

2. 建模环节:从物理对象到数学表达

2.1 目标函数怎么选

选目标函数首要判断依据是:你复现的论文里,系统调度主体是谁,追求的经济指标是什么。

如果是独立发电企业视角,目标函数通常是“系统运行收益最大”,即水电上网收益加上风电上网收益,减去运行维护成本、弃风惩罚成本。公式上写作:

max F = sum( sum( P_h(i,t) * price_h(t) * dt ) + sum( P_w(i,t) * price_w(t) * dt ) ) - sum( curtail_w(i,t) * penalty * dt )

如果是电网调度视角,目标函数更多写成“系统运行成本最小”,这时水电出力成本用可变成本函数近似,风电成本近似为0(或者说优先消纳),目标则变成减少火电出力和弃风惩罚:

min C = sum( sum( a_i * P_g(i,t)^2 + b_i * P_g(i,t) + c_i ) ) + sum( lambda_cur * curt_w(t) )

复现时要留意,EI论文常把目标函数写成带时间权重的求和形式,你拿到的数据、价格要是以小时为单位,而论文用的是15分钟一个时段,换算错了整个结果曲线都不对。

2.2 水电调度约束组

水电建模里最核心、也最容易写错的就是水量平衡约束。单库单机组的形式:

V(t+1) = V(t) + ( Q_in(t) - Q_release(t) ) * dt - S(t)
  • V是库容,单位立方米;
  • Q_in是天然入库流量,单位立方米每秒;
  • Q_release是出库流量(含发电流量);
  • S是弃水流量。

乘上dt换算成时段水量。这里出库流量和出力之间还有一层转换关系:

P_h(t) = K * Q_turbine(t) * H_eff(t)

K是综合出力系数,H_eff是净水头。问题在于H_eff本身又跟库容V相关。很多初学者第一次写约束,直接把P写成Q的线性函数,拿去跑模型。对于有些论文,这种简化是允许的;但如果审稿人较真,水头变化就必须当作变量处理,这时候就得引入库容-水位曲线,把水头变成一个随库容变化的非线性函数,模型立刻从LP变成NLP/MILP。

除了水量平衡,还有一组常用约束,我列全给你:

  • 库容上下限:V_min ≤ V(t) ≤ V_max,防止出现调度方案让水库干涸或漫坝。
  • 出库流量限值:Q_min ≤ Q_release(t) ≤ Q_max,兼顾下游生态和泄洪能力。
  • 水电出力限值:P_h_min ≤ P_h(t) ≤ P_h_max,受机组技术出力限制。
  • 爬坡约束:| P_h(t) - P_h(t-1) | ≤ ramp_h,水电机组出力调整速率不是无限的。
  • 末库容约束:V(T) = V_target,这是调度周期结束时的控制目标。

梯级水电站还要加“水流滞时”约束,即上游电站的出库,要经过一个时间延迟才能进入下游电站的入库:

Q_in_down(t) = Q_release_up(t - tau) + Q_local(t)

这个滞时一加,约束矩阵就不是简单对角结构了,写Matlab时要注意时序索引别越界。

2.3 风电不确定性的两种处理套路

风电出力最简单的表达是乘以装机容量和预测出力系数:P_w(t) ≤ cap_w * u_w(t),再叠加预测误差。

场景法的处理步骤是:

  1. 对风速预测值加随机扰动,生成N条风电出力样本,常用拉丁超立方采样,比普通的蒙特卡洛效率高得多。
  2. 用场景削减算法把N条聚合成S条典型场景,快进快出的话可以直接用Matlab自带的kmeans,但要跟论文对上的话,还是推荐写同步回代削减算法。
  3. 目标函数变成各场景期望:F_total = sum( prob_s * F_s ),决策变量要满足所有场景下的约束,也就是常说的时间耦合约束。

鲁棒法的处理则不同,它给风电设一个波动范围,把约束改写成:

P_w(t) ∈ [ P_w_pred(t) - delta_down(t), P_w_pred(t) + delta_up(t) ]

模型求解时寻找对任意区间内风电出力都可行的调度方案。这种模型在Matlab里常用“对偶重构”或“列与约束生成”来做,代码量比场景法大,但结果更保守、更贴近电网调度需求。

3. Matlab复现的关键设计与求解器选型

3.1 我为什么推荐“建模层+求解层”分离

很多人第一次做优化调度,喜欢把目标函数和约束全部写进一个巨长的主程序里,然后调fmincon一把梭。代码短的时候还行,一旦约束数量上百、变量上千,排查维度不匹配错误会让人怀疑人生。

我自己复现这类EI论文,用的是分层结构:

  • 数据层:所有物理参数、预测曲线、价格曲线集中在一个脚本里,运行一次生成结构体保存。
  • 模型层:目标函数、约束条件按逻辑分模块编写,每个模块就是一个函数,输入决策变量、输出目标值或约束残差。
  • 求解层:统一调用求解器,并做好求解状态校验(solver status、退出标志、残差分析)。
  • 后处理层:画曲线、计算指标、输出表格。

这样做的最大好处是,论文改了目标函数里的一个惩罚系数,你只需要改模型层一个函数;求解器从linprog换成Gurobi,也不用动其他代码。我实测下来,这个结构在复现“多场景随机优化”时尤其关键,因为要跑的算例多,可复用性直接决定你一个晚上能出几个实验。

3.2 自带linprog与外部求解器的取舍

Matlab自带优化工具箱里,最常用的是:

  • linprog:线性规划,纯LP问题直接用它。
  • intlinprog:混合整数线性规划,处理机组启停、0-1状态变量时用它。
  • fmincon:非线性约束优化,水头变化、非线性运行成本等场景用它。

先说我的结论:能线性化就线性化,优先用linprog/intlinprog;没有把握就先用fmincon把模型跑通,再考虑升级求解器。

为什么这么建议?因为linprog求解速度快、结果稳定、几乎不会出现数值病态的问题,而且Matlab自带的求解器不需要额外安装工具,复现门槛低。fmincon对初值敏感,初值给不好,结果可能落在局部最优。现在很多EI论文里的风-水电联合调度已经写成MILP形式,我自己拿到代码的第一步就是检查它的约束里有没有整数变量,有就上intlinprog。

如果你有商业求解器,比如Gurobi、CPLEX,建议配合YALMIP一起用。YALMIP是一个Matlab建模工具箱,它把LP、MILP、SDP统一封装,你只需要写符号化的约束,模型层代码能缩短一半。不过用YALMIP要注意版本匹配和路径配置问题,见后文的坑。

3.3 代码模块设计与数据结构

我通常把24小时或96时段的调度问题组织成这样的数据结构:

%% 数据层示例:params.m params.T = 24; % 时段数,1h步长 params.dt = 3600; % 时段长度,单位秒 params.rho_w = 3.5; % 风电上网电价,元/kWh params.rho_h = 2.8; % 水电上网电价,元/kWh params.lambda_curt = 8.0; % 弃风惩罚系数,元/kWh params.P_w_forecast = ...; % 1xT 风电预测出力,MW params.cap_w = 300; % 风电场装机,MW params.V_init = 1.2e8; % 水库初始库容,m3 params.V_max = 2.0e8; params.V_min = 5.0e7; params.V_target = 1.2e8; % 末库容目标 params.Q_in = ...; % 入库流量序列,m3/s params.P_h_max = 120; % 水电最大出力,MW params.P_h_min = 10; params.K = 8.5; % 出力系数,约 MW/(m3/s * m) params.H_ref = 30; % 参考水头,m

把参数集中放的结构,后面调试时改起来方便。再强调一下单位:水头单位米,流量单位立方米每秒,出力单位兆瓦,电价按千瓦时算,这三个量纲之间的系数如果不在一个量级,会导致求解器数值上出现巨大差异,后文专门说。

4. 核心代码模块实现与参数配置实操

4.1 基础数据准备(含参数表)

我自己复现时,最喜欢先把论文里的系统参数表格化,再对照填入Matlab。这里给你一张可以直接抄作业的参数表模板:

参数符号数值单位
调度时段数T24h
风电装机cap_w300MW
风电预测出力均值Pw_avg120MW
风电预测误差比例sigma_w0.15%
水库初始库容V_init1.2亿m3
水库最大库容V_max2.0亿m3
水库最小库容V_min0.5亿m3
天然入库流量Q_in40(随季节变化)m3/s
水电最大出力Ph_max120MW
水电最小出力Ph_min10MW
综合出力系数K8.5-
参考水头H_ref30m
弃风惩罚系数lambda_curt300元/MWh
风电电价rho_w350元/MWh
水电电价rho_h280元/MWh

这里有个细节:弃风惩罚系数如果设得太低,模型会倾向弃风而不调用水电调节能力,结果看着“最优”,实际完全违背联合调度的初衷。我一般先把惩罚系数设成风电电价的2~3倍,确保解出的方案优先消纳风电。

4.2 目标函数与约束的矩阵化写法

假定你已经把问题简化为LP:水头恒定、不引入整数变量,那么目标函数可以写成标准形min f' * x,其中决策变量x包含水电出力序列 P_h(T)、风电实际出力 P_w(T)、弃风量 P_curt(T)。

%% 模型层示例:build_model.m % 决策变量排序:x = [P_h(1..T), P_w(1..T), P_curt(1..T)] n_h = T; n_w = T; n_c = T; xlen = n_h + n_w + n_c; % 目标:最小化运行成本 % 简化:水电成本忽略,目标主要是弃风惩罚 f = zeros(xlen,1); f(n_h+n_w+1 : end) = params.lambda_curt .* ones(T,1);

功率平衡约束写成等号约束:P_h(t) + P_w(t) = load(t),其中负荷场景按论文设置。线性约束统一放到A*x <= b和Aeq*x = beq里:

% 功率平衡约束 Aeq Aeq = zeros(T, xlen); beq = load_profile(:); % T x 1 for t = 1:T Aeq(t, t) = 1; % P_h(t) Aeq(t, n_h+t) = 1; % P_w(t) % P_curt不参与平衡 end % 出力上下限 lb ub lb = [params.P_h_min * ones(T,1); zeros(T,1); zeros(T,1)]; ub = [params.P_h_max * ones(T,1); params.cap_w * ones(T,1); params.cap_w * ones(T,1)];

这里有个很隐蔽的问题:风电实际出力 P_w 被纳入决策变量,但没有限制它与预测值的关系。要加一条约束:实际出力不超过预测值,即 P_w(t) ≤ P_w_forecast(t)。如果不加,模型可能会“凭空”让风电多出力来满足负荷平衡,优化结果完全失真,这是新人最容易犯的错误之一。

水库水量平衡约束如果只靠矩阵拼,你会觉得写起来很痛苦,所以我推荐一个小技巧:用稀疏矩阵构造时间耦合项。

% 水量平衡:V(t+1) - V(t) - Q_rel(t)*dt = Q_in(t)*dt % V是辅助变量时会增加变量维度,简化版本直接把V消去,只保留Q_rel约束 % 上面简化模型已经假设水头恒定,所以 P_h(t) = K*H_ref*Q_turb(t) % 反解得发电流量:Q_turb = P_h / (K*H_ref),单位换算后代入平衡约束

其实在做纯LP快速复现时,我不建议直接引入库容变量,而是把水量平衡约束转换为“水电日发电水量总数限制”:

sum(P_h(t)) / (K * H_ref) * dt = some_total_energy

这样就将水量平衡变成了对水电全天发电量的整体约束,相当于约束发电用水总量等于可用水量,适合调度周期内水位变化不大的场景。当然这只是一种近似,完整论文里你要保留逐时段库容约束,那就得把V(t)也作为决策变量加进去,并配合V_MIN、V_MAX上下限。具体哪种合适,取决于原论文有没有考虑库容动态变化。稳妥起见,我强烈建议第一次复现先跑通整体水量约束,出结果后再升级到逐时段库容模型。

4.3 主程序循环与结果输出

主程序负责把上述模块串起来,并做求解状态判断。我的主程序往往这样写:

%% 主程序:run_scheduling.m params = data_init(); % 构造模型矩阵 [f, A, b, Aeq, beq, lb, ub] = build_model(params); % 求解 options = optimoptions('linprog', 'Algorithm', 'dual-simplex', 'Display', 'iter'); [x_opt, fval, exitflag] = linprog(f, A, b, Aeq, beq, lb, ub, options); if exitflag ~= 1 error('求解失败,exitflag = %d', exitflag); end % 提取结果 P_h_opt = x_opt(1:T); P_w_opt = x_opt(T+1:2*T); P_curt_opt = x_opt(2*T+1:3*T); % 后处理 plot_schedule(P_h_opt, P_w_opt, P_curt_opt); compute_metrics(P_h_opt, P_w_opt, P_curt_opt);

如果报错“Linprog stopped because it exceeded its iteration limit”,加一行:

options = optimoptions('linprog', 'MaxIterations', 10000, 'OptimalityTolerance', 1e-8);

求解器默认的迭代限制是针对标准规模问题的,你加了288个时段、几千个变量之后,迭代上限经常不够用。

5. 结果解读与验证方法

5.1 先跑一个确定性基线

拿到代码,第一步不是马上加随机性,而是先把风电预测设为一条确定性曲线,跑一遍纯确定性调度。这一步的目的是验证模型本身对不对。

验证点有三个:

  • 功率平衡是否全时段满足,输出每个时段的误差,应该小于1e-6。
  • 水电出力是否在可行域内,不会出现负值或者越过装机上限。
  • 水库水量是否守恒,把各时段的发电流量对时间积分,对比可用水量,误差应该在可接受范围内。

我通常会画一张调度图,横轴是24小时,纵轴是功率,把水电出力、风电出力、负荷和弃风量画在同一张图里。如果看到弃风集中在风电大发而负荷低谷时段,说明模型逻辑正确;如果弃风遍地都是,那大概率是约束写错了,比如忘了加“实际出力不超预测”那条限制。

5.2 随机场景下的对比指标

确定性模型通过后再上随机性。场景法的结果处理有固定的套路:

  • 生成500~1000条风电场景,用同步回代削减到10~20个代表场景。
  • 求解多场景随机优化模型,得到第一阶段的调度计划。
  • 用这个计划去回代测试所有原始场景,统计平均弃风率、失负荷率等指标。

注意:这里有个“阶段”的概念。如果模型假设所有决策都在看到风电出力之前就定好,属于完全前瞻性的调度,过于乐观;如果允许水电在每个时段根据风电实时出力滚动调整,则结果更贴近实际。论文里叫“非预期性约束”,复现时务必看清原文属于哪一种。

计算指标时,我建议输出四个核心指标:

指标公式意义
弃风率弃风量 / 风电可发总量衡量风电消纳水平
水电利用率水电发电量 / 水电可发电量衡量水量利用程度
运行成本目标函数值经济性
爬坡次数统计水电出力方向变化的次数衡量调节压力

这四个指标放在对比表格里,基本能满足课程作业、学位论文里“算例分析”一节的需要,也能支撑你写完一篇数据扎实的复现笔记。

6. 复现中高频踩坑与排查实录

6.1 求解器数值异常

先说我最常遇到的:linprog报“The dual-simplex algorithm exhausted its options”或者“Unable to find a feasible solution”。

这种问题的原因比例大概是:约束本身相矛盾占30%,数值尺度差异过大占50%,模型数据错误占20%。

数值尺度差异是最隐蔽的。库容是亿立方米,电价是几百元每兆瓦时,出力是几十到几百兆瓦,三个量级放在一起,约束矩阵的条件数会非常差。解法很简单:把所有物理量折算到统一量纲。比如库容改用百万立方米,流量改用百万立方米每小时,电价改成元每兆瓦时,你会发现收敛速度提升非常明显。

再者,约束矛盾常见于水量平衡和末库容约束之间。比如天然来水很少,但你又要求调度期末库容回到一个很高的目标值,同时还要保证水电全天大出力,这组约束在物理上就是无解的。排查方法:先注释末库容约束跑一遍,看水电出力上限是否被顶格,再决定调整来水数据还是放宽末库容。

fmincon场景下,最常见报错是“Objective function returned NaN”。十有八九是决策变量超出可行域导致计算了负数的平方根或者除零。我会在目标函数最前面加一行:

if any(x <= 0) fval = 1e10; return; end

用罚函数快速把搜索拉回可行域。

6.2 约束维度与单位换算

另一个高频坑是矩阵维度对不上。linprog的约束矩阵要求是A * x <= b,其中A的行数等于约束条数,列数等于变量数。一旦你中途改了时段数、加了变量,忘记同步扩容A,就会出现“Matrix dimensions must agree”或者“Linprog received the incorrect number and/or types of parameters.”。

我的习惯是,每次修改模型之后,先跑一段自动检查:

assert(size(A,2) == xlen, 'A列数%d不等于变量数%d', size(A,2), xlen); assert(size(Aeq,2) == xlen, 'Aeq列数与变量数不一致'); assert(length(lb) == xlen && length(ub) == xlen, '边界维度错误');

这段代码能省下大量低级排错时间。

单位换算的问题前面反复提过,这里再给一个具体例子。入库流量40 m³/s,如果直接乘dt=3600,得到的是144000 m³,这个数跟库容一亿立方米放在一起做水量平衡,精度上没问题。但如果你用linprog默认的容差,很容易把这个小量直接忽略掉,导致水量平衡约束形同虚设。解决办法是给水量平衡约束单独配置容差,或者在建模时把水量单位从立方米放大到百万立方米。

6.3 YALMIP与求解器配置问题

如果你选择用YALMIP加外部求解器,最常见的坑是:YALMIP安装后找不到求解器。原因大多是没有把安装目录添加到Matlab路径,或者是Gurobi的许可证没有正确设置。启动时先跑yalmiptest,它会自动检测可用求解器,看到输出的汇总表格里出现了你要用的求解器就说明配置成功。

如果提示“No suitable solver for this problem type”,则是你建的模型里有变量类型或约束类型当前求解器不支持。排查思路:先确认问题是LP还是MILP,再确认是否出现了非线性项。很多时候YALMIP会把约束判断为非线性,实际只是你在写约束时用了sdpvar变量的二次项,比如写成了x(1)^2,其实应该是线性化后的变量。

6.4 结果合理性检查

最后分享几个我复现完以后必做的合理性检查项,也是写论文时审稿人最爱问的点:

  • 全时段功率平衡误差小于1e-5,否则说明约束漏写。
  • 任何弃风时段,前面应该堆积了水库蓄水或者水电出力下限顶格的情况,弃风不会无缘无故出现。
  • 末库容约束是否满足,如果水库蓄水大量用光,但未来几天没有来水数据,调度结果就很危险。
  • 水电爬坡出力要符合机组实际调节速率,不要出现15分钟内从10 MW跳到120 MW的“神仙调度”。

我个人体会是,这条检查清单比我第一次看论文时以为的更重要。很多论文复现失败,往往不是算法不对,而是这些基础物理约束没满足,导致结果曲线看上去“很漂亮、但没法解释”。

写在最后的实操建议

如果只能给你一条建议,那就是:先把只含水电的单库优化跑通,再叠加风电,最后才处理不确定性。我见过太多人一上来就直奔随机规划,结果模型线性化、场景削减、非预期性约束叠在一起,出问题了根本不知道是哪一层的锅。

以我自己的经验,一篇典型的EI论文风电-水电联合调度复现,正常节奏是:第一天搭数据层加确定性模型,第二天加场景生成和削减,第三天补后处理和算例对比。三天能完成大部分工作,剩下时间都花在排查约束和调参上。

等你这套代码跑顺之后,后面扩展空间很大。把水电换成抽水蓄能,模型结构几乎不用大改;把目标函数从发电收益换成系统备用容量最大化,也只是多几个约束的事。Matlab这套环境的优势就在这儿:建模灵活,代码复用率高,换个场景就是一篇新的算例分析。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 12:52:45

SpringBoot+Vue数学题库组卷系统:从组卷算法到PDF导出实战

一个数学老师说要出一套期中考试卷&#xff0c;从前几天就在后台选题、排版、调格式&#xff0c;直到考试前一天晚上才定稿。我就是在那个时候意识到&#xff0c;一个能自动组卷的web系统&#xff0c;并不是把题目堆在一起那么简单。它要把题库、知识点、难度系数、题型分布、重…

作者头像 李华
网站建设 2026/9/30 12:52:42

航拍人体检测数据集与YOLO训练全流程实战指南

1. 航拍人体检测数据集到底解决什么问题1.1 从操场航拍这个场景说起航拍视角下的人体检测&#xff0c;和咱们平时拿手机拍人、做常规目标检测&#xff0c;完全是两码事。我最早接触这类需求&#xff0c;是帮一个做校园体育分析的朋友处理操场俯拍视频&#xff0c;当时想当然地拿…

作者头像 李华
网站建设 2026/9/30 12:51:32

CCNA中版PDF:网络工程师的实操排错参照系

简介&#xff1a;本资源是一份面向CCNA初学者与备考者的中文学习笔记PDF&#xff0c;系统梳理OSI七层模型、网络设备原理&#xff08;HUB/交换机/路由器&#xff09;、CSMA/CD机制、ISDN DDR拨号配置、子网划分&#xff08;FLSM&#xff09;及思科命令实践等核心考点。内容源自…

作者头像 李华
网站建设 2026/9/30 12:50:44

大模型预训练数据集构建全流程实战清单

我这些年陪着不少团队从零搭预训练管线&#xff0c;发现大家一上来最容易压缩时间的环节&#xff0c;反而是最不该压缩的——大模型预训练数据集构建。模型结构可以抄开源&#xff0c;训练框架可以现装&#xff0c;唯独数据&#xff0c;必须自己一点一点抠出来。这篇是“大模型…

作者头像 李华
网站建设 2026/9/30 12:48:59

ComfyUI+PS商业AI绘画工作流:从可控生成到精细交付

上个月接了一个咖啡品牌的电商海报单子&#xff0c;客户丢来一句话&#xff1a;夏日清凉感&#xff0c;人物和产品都要高清&#xff0c;玻璃瓶上的水珠要有层次。前一个工作室用在线工具出的图被他们打回来三回——背景里多长了一只手&#xff0c;瓶身 logo 全是乱码&#xff0…

作者头像 李华