当前位置: 首页 > news >正文

【智能协同云图库】第七期:基于AI调用阿里云百炼大模型,实现AI图片编辑功能

摘要:AI 高速发展赋能传统业务,图库网站亦有诸多 AI 应用空间。以 AI 扩图功؜能为例,让我们来学习如何在项目⁠中快速接入 AI 绘图大模型。‏用户可以选择一张已上传的图片,‌通过 AI 扩图得到新的图片,希望可以帮到大家。

AI绘图大模型两次扩图效果

本节思维导图:

方案设计

1、AI 绘图大模型选择

控制台 也能看到对应的图像画面扩展模型

2、调用方式

点击对应的API参考,我们发现,API 只支持异步方式调用

这是因为 AI 绘画任务计؜算量大且耗时长,同步调用会导致服务器线程长时间被单个⁠任务占用,限制了并发处理能力,增加了超时和系统崩溃的‏风险。通过异步调用,服务器可以将任务放入队列中,合理‌调度资源,避免阻塞主线程,从而更高效地服务多个用户请‏求,提升整体系统的稳定性和可扩展性。

同步调用如下,好处是客户⁠端可以直接获取到结‏果,调用更方便:

异步调用如下,客户端需要在提交任务后⁠,不断轮询请求,来检查任务‏是否执行完成:

                                          ‏             

由于 AI 接口؜已经选择了异步调用,所以我们作⁠为要调用 AI 接口的客户端,‏要使用轮询的方式来检查任务状态‌是否为 “已完成”,如果完成了‏,才可以获取到生成的图片。

那么是前端轮询还是后端轮询呢?让我们来对比一下

1)前端轮询

前端调用后؜端提交任务后得到任⁠务 ID,然后通过‏定时器轮询请求查询‌任务状态接口,直到‏任务完成或失败。

// 提交任务
async function submitTask() {const response = await fetch('/api/createTask', { method: 'POST' });const { taskId } = await response.json();checkTaskStatus(taskId);
}// 调用
submitTask();// 检查任务状态
async function checkTaskStatus(taskId) {const intervalId = setInterval(async () => {const response = await fetch(`/api/taskStatus?taskId=${taskId}`);const { status, result } = await response.json();if (status === 'success') {console.log('Task completed:', result);clearInterval(intervalId); // 停止轮询} else if (status === 'failed') {console.error('Task failed');clearInterval(intervalId); // 停止轮询}}, 2000); // 每隔 2 秒轮询
}

2)后端轮询

后端通过循؜环或定时任务检测任⁠务状态,接口阻‏塞,直到任务完成或‌失败,直接返回结‏果给前端。

@RestController
public class TaskController {@PostMapping("/createTask")public String createTask() {String taskId = taskService.submitTask();return taskId;}@GetMapping("/waitForTask")public ResponseEntity<String> waitForTask(@RequestParam String taskId) {while (true) {String status = taskService.checkTaskStatus(taskId);if ("success".equals(status)) {return ResponseEntity.ok("Task completed");} else if ("failed".equals(status)) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Task failed");}try {Thread.sleep(2000); // 等待 2 秒后重试} catch (InterruptedException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error occurred");}}}
}

显然,后端轮询容易因为任务阻塞导致资源耗尽,所以通常推荐 前端轮询。除非有明确的需求要求时,才考虑后端轮询,比如任务结果需实时返回且对网络请求数敏感。


在配置文件中填写获取到的 apiKey:

# 阿里云 AI 配置
aliYunAi:apiKey: xxxx

新建数据模型类

api 包下新建 aliyunai 包,存放阿里云 AI 相关代码。

aliyunai.model 包下新建数据模型类,可以让 AI 根据官方文档中的请求响应信息自动生成

AI生成代码小技巧1:

第一步,将请求信息交给AI整理

创建任务获取任务ID
请求方式:POST
URL:https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/out-paintingcURL示例:bash
curl --location --request POST 'https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/out-painting' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'X-DashScope-Async: enable' \
--header 'Content-Type: application/json' \
--data '{"model": "image-out-painting","input": {"image_url": "http://xxx/image.jpg"},"parameters":{"x_scale":2,"y_scale":2,"best_quality":false,"limit_image_size":true}
}'
请求头(Headers):参数	类型	必选	说明
Content-Type	string	是	必须设置为 application/json
Authorization	string	是	身份认证(示例:Bearer d1xxx2a)
X-DashScope-Async	string	是	必须设置为 enable
请求体(Request Body)
顶层参数:字段	类型	必选	说明	示例值
model	string	是	模型名称	image-out-painting
input	object	是	输入图像信息	
parameters	object	是	图像处理参数	
input对象属性:字段	类型	必选	说明	限制条件
image_url	string	是	图像URL或base64数据	格式:JPG/JPEG/PNG/HEIF/WEBP
大小:≤10MB
分辨率:512×512 ~ 4096×4096像素
单边长度:[512, 4096]像素
parameters对象属性:字段	类型	必选	说明	默认值	取值范围/可选值	示例
angle	integer	否	逆时针旋转角度(度)	0	[0, 359]	-
output_ratio	string	否	输出图像宽高比	""	["", "1:1", "3:4", "4:3", "9:16", "16:9"]	-
x_scale	float	否	水平方向扩展比例	1.0	[1.0, 3.0]	输入1000×1000 → 设置2.0 → 输出2000×1000
y_scale	float	否	垂直方向扩展比例	1.0	[1.0, 3.0]	输入1000×1000 → 设置2.0 → 输出1000×2000
top_offset	integer	否	图像上方添加像素	0	top_offset + bottom_offset < 3×原图高度	输入1000×1000 → 设置500 → 输出1000×1500
bottom_offset	integer	否	图像下方添加像素	0	top_offset + bottom_offset < 3×原图高度	输入1000×1000 → 设置500 → 输出1000×1500
left_offset	integer	否	图像左侧添加像素	0	left_offset + right_offset < 3×原图宽度	输入1000×1000 → 设置500 → 输出1500×1000
right_offset	integer	否	图像右侧添加像素	0	left_offset + right_offset < 3×原图宽度	输入1000×1000 → 设置500 → 输出1500×1000
best_quality	boolean	否	开启最佳质量模式	false	true/false	true:耗时增加但细节更丰富
limit_image_size	boolean	否	限制输出图像大小	true	true/false	建议保持true(输出≤5MB)
add_watermark	boolean	否	添加AI水印	true	true/false	在左下角添加"Generated by AI"

第二步,让AI生成对应的请求类代码

@Data
public class CreateOutPaintingTaskRequest implements Serializable {/*** 模型,例如 "image-out-painting"*/private String model = "image-out-painting";/*** 输入图像信息*/private Input input;/*** 图像处理参数*/private Parameters parameters;@Datapublic static class Input {/*** 必选,图像 URL*/@Alias("image_url")private String imageUrl;}@Datapublic static class Parameters implements Serializable {/*** 可选,逆时针旋转角度,默认值 0,取值范围 [0, 359]*/private Integer angle;/*** 可选,输出图像的宽高比,默认空字符串,不设置宽高比* 可选值:["", "1:1", "3:4", "4:3", "9:16", "16:9"]*/@Alias("output_ratio")private String outputRatio;/*** 可选,图像居中,在水平方向上按比例扩展,默认值 1.0,范围 [1.0, 3.0]*/@Alias("x_scale")@JsonProperty("xScale")private Float xScale;/*** 可选,图像居中,在垂直方向上按比例扩展,默认值 1.0,范围 [1.0, 3.0]*/@Alias("y_scale")@JsonProperty("yScale")private Float yScale;/*** 可选,在图像上方添加像素,默认值 0*/@Alias("top_offset")private Integer topOffset;/*** 可选,在图像下方添加像素,默认值 0*/@Alias("bottom_offset")private Integer bottomOffset;/*** 可选,在图像左侧添加像素,默认值 0*/@Alias("left_offset")private Integer leftOffset;/*** 可选,在图像右侧添加像素,默认值 0*/@Alias("right_offset")private Integer rightOffset;/*** 可选,开启图像最佳质量模式,默认值 false* 若为 true,耗时会成倍增加*/@Alias("best_quality")private Boolean bestQuality;/*** 可选,限制模型生成的图像文件大小,默认值 true* - 单边长度 <= 10000:输出图像文件大小限制为 5MB 以下* - 单边长度 > 10000:输出图像文件大小限制为 10MB 以下*/@Alias("limit_image_size")private Boolean limitImageSize;/*** 可选,添加 "Generated by AI" 水印,默认值 true*/@Alias("add_watermark")private Boolean addWatermark = false;}
}

然后重复操作,生成响应类即可


创建扩图任务请求类:

@Data
public class CreateOutPaintingTaskRequest implements Serializable {/*** 模型,例如 "image-out-painting"*/private String model = "image-out-painting";/*** 输入图像信息*/private Input input;/*** 图像处理参数*/private Parameters parameters;@Datapublic static class Input {/*** 必选,图像 URL*/@Alias("image_url")private String imageUrl;}@Datapublic static class Parameters implements Serializable {/*** 可选,逆时针旋转角度,默认值 0,取值范围 [0, 359]*/private Integer angle;/*** 可选,输出图像的宽高比,默认空字符串,不设置宽高比* 可选值:["", "1:1", "3:4", "4:3", "9:16", "16:9"]*/@Alias("output_ratio")private String outputRatio;/*** 可选,图像居中,在水平方向上按比例扩展,默认值 1.0,范围 [1.0, 3.0]*/@Alias("x_scale")@JsonProperty("xScale")private Float xScale;/*** 可选,图像居中,在垂直方向上按比例扩展,默认值 1.0,范围 [1.0, 3.0]*/@Alias("y_scale")@JsonProperty("yScale")private Float yScale;/*** 可选,在图像上方添加像素,默认值 0*/@Alias("top_offset")private Integer topOffset;/*** 可选,在图像下方添加像素,默认值 0*/@Alias("bottom_offset")private Integer bottomOffset;/*** 可选,在图像左侧添加像素,默认值 0*/@Alias("left_offset")private Integer leftOffset;/*** 可选,在图像右侧添加像素,默认值 0*/@Alias("right_offset")private Integer rightOffset;/*** 可选,开启图像最佳质量模式,默认值 false* 若为 true,耗时会成倍增加*/@Alias("best_quality")private Boolean bestQuality;/*** 可选,限制模型生成的图像文件大小,默认值 true* - 单边长度 <= 10000:输出图像文件大小限制为 5MB 以下* - 单边长度 > 10000:输出图像文件大小限制为 10MB 以下*/@Alias("limit_image_size")private Boolean limitImageSize;/*** 可选,添加 "Generated by AI" 水印,默认值 true*/@Alias("add_watermark")private Boolean addWatermark = false;}
}

创建扩图任务响应类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreateOutPaintingTaskResponse {private Output output;/*** 表示任务的输出信息*/@Datapublic static class Output {/*** 任务 ID*/private String taskId;/*** 任务状态* <ul>*     <li>PENDING:排队中</li>*     <li>RUNNING:处理中</li>*     <li>SUSPENDED:挂起</li>*     <li>SUCCEEDED:执行成功</li>*     <li>FAILED:执行失败</li>*     <li>UNKNOWN:任务不存在或状态未知</li>* </ul>*/private String taskStatus;}/*** 接口错误码。* <p>接口成功请求不会返回该参数。</p>*/private String code;/*** 接口错误信息。* <p>接口成功请求不会返回该参数。</p>*/private String message;/*** 请求唯一标识。* <p>可用于请求明细溯源和问题排查。</p>*/private String requestId;}

查询任务响应类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GetOutPaintingTaskResponse {/*** 请求唯一标识*/private String requestId;/*** 输出信息*/private Output output;/*** 表示任务的输出信息*/@Datapublic static class Output {/*** 任务 ID*/private String taskId;/*** 任务状态* <ul>*     <li>PENDING:排队中</li>*     <li>RUNNING:处理中</li>*     <li>SUSPENDED:挂起</li>*     <li>SUCCEEDED:执行成功</li>*     <li>FAILED:执行失败</li>*     <li>UNKNOWN:任务不存在或状态未知</li>* </ul>*/private String taskStatus;/*** 提交时间* 格式:YYYY-MM-DD HH:mm:ss.SSS*/private String submitTime;/*** 调度时间* 格式:YYYY-MM-DD HH:mm:ss.SSS*/private String scheduledTime;/*** 结束时间* 格式:YYYY-MM-DD HH:mm:ss.SSS*/private String endTime;/*** 输出图像的 URL*/private String outputImageUrl;/*** 接口错误码* <p>接口成功请求不会返回该参数</p>*/private String code;/*** 接口错误信息* <p>接口成功请求不会返回该参数</p>*/private String message;/*** 任务指标信息*/private TaskMetrics taskMetrics;}/*** 表示任务的统计信息*/@Datapublic static class TaskMetrics {/*** 总任务数*/private Integer total;/*** 成功任务数*/private Integer succeeded;/*** 失败任务数*/private Integer failed;}
}

5)开发 ؜API 调用类,通⁠过 Hutool ‏的 HTTP 请求‌工具类来调用阿里云‏百炼的 API:

AI生成代码小技巧2:

第一步,把发送请求样例传递给AI

第二步,让AI利用Hutool包发送请求生成代码

@Component
public class AliyunAiApi {@Value("${aliyunAi.apiKey}")private String apiKey;//创建任务// 创建任务地址public static final String CREATE_OUT_PAINTING_TASK_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/out-painting";// 查询任务状态public static final String GET_OUT_PAINTING_TASK_URL = "https://dashscope.aliyuncs.com/api/v1/tasks/%s";public CreateOutPaintingTaskResponse createPaintingTask(CreateOutPaintingTaskRequest request) {//1.异常判断ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);// 2. 构建JSON请求体String jsonBody = JSONUtil.toJsonStr(request);// 3. 发送HTTP请求try (HttpResponse response = HttpRequest.post(CREATE_OUT_PAINTING_TASK_URL).header("Authorization", "Bearer " + apiKey).header("X-DashScope-Async", "enable").header("Content-Type", "application/json").body(jsonBody).execute()) {// 4. 检查响应状态if (!response.isOk()) {throw new RuntimeException("请求失败,状态码: " + response.getStatus());}// 5. 解析响应体String body = response.body();return JSONUtil.toBean(body, CreateOutPaintingTaskResponse.class);} catch (Exception e) {throw new RuntimeException("创建扩图任务失败", e);}}/*** 查询创建的任务** @param taskId* @return*/public GetOutPaintingTaskResponse getOutPaintingTask(String taskId) {if (StrUtil.isBlank(taskId)) {throw new BusinessException(ErrorCode.OPERATION_ERROR, "任务 id 不能为空");}try (HttpResponse httpResponse = HttpRequest.get(String.format(GET_OUT_PAINTING_TASK_URL, taskId)).header(Header.AUTHORIZATION, "Bearer " + apiKey).execute()) {if (!httpResponse.isOk()) {throw new BusinessException(ErrorCode.OPERATION_ERROR, "获取任务失败");}return JSONUtil.toBean(httpResponse.body(), GetOutPaintingTaskResponse.class);}}
}
2、扩图服务

model.dto.picture 包下新建 AI 扩图请求类,用于接受前端传来的参数并传递给 Service 服务层。字段包括图片 id 和扩图参数:

@Data
public class CreatePictureOutPaintingTaskRequest implements Serializable {/*** 图片 id*/private Long pictureId;/*** 扩图参数*/private CreateOutPaintingTaskRequest.Parameters parameters;private static final long serialVersionUID = 1L;
}

在图片服务中编写创؜建扩图任务方法,从数据库中获取图片⁠信息和 url 地址,构造请求参数‏后调用 api 创建扩图任务。注意‌,如果图片有空间 id,则需要校验‏权限,直接复用以前的权限校验方法。

@Override
public CreateOutPaintingTaskResponse createPictureOutPaintingTask(CreatePictureOutPaintingTaskRequest createPictureOutPaintingTaskRequest, User loginUser) {// 获取图片信息Long pictureId = createPictureOutPaintingTaskRequest.getPictureId();Picture picture = Optional.ofNullable(this.getById(pictureId)).orElseThrow(() -> new BusinessException(ErrorCode.NOT_FOUND_ERROR));// 权限校验checkPictureAuth(loginUser, picture);// 构造请求参数CreateOutPaintingTaskRequest taskRequest = new CreateOutPaintingTaskRequest();CreateOutPaintingTaskRequest.Input input = new CreateOutPaintingTaskRequest.Input();input.setImageUrl(picture.getUrl());taskRequest.setInput(input);BeanUtil.copyProperties(createPictureOutPaintingTaskRequest, taskRequest);// 创建任务return aliYunAiApi.createOutPaintingTask(taskRequest);
}

3、扩图接口

在 Pictu؜reController 添⁠加 AI 扩图接口,包括创建‏任务和查询任务状态接口:  ‌

/*** 创建 AI 扩图任务*/
@PostMapping("/out_painting/create_task")
public BaseResponse<CreateOutPaintingTaskResponse> createPictureOutPaintingTask(@RequestBody CreatePictureOutPaintingTaskRequest createPictureOutPaintingTaskRequest,HttpServletRequest request) {if (createPictureOutPaintingTaskRequest == null || createPictureOutPaintingTaskRequest.getPictureId() == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}User loginUser = userService.getLoginUser(request);CreateOutPaintingTaskResponse response = pictureService.createPictureOutPaintingTask(createPictureOutPaintingTaskRequest, loginUser);return ResultUtils.success(response);
}/*** 查询 AI 扩图任务*/
@GetMapping("/out_painting/get_task")
public BaseResponse<GetOutPaintingTaskResponse> getPictureOutPaintingTask(String taskId) {ThrowUtils.throwIf(StrUtil.isBlank(taskId), ErrorCode.PARAMS_ERROR);GetOutPaintingTaskResponse task = aliYunAiApi.getOutPaintingTask(taskId);return ResultUtils.success(task);
}

使用Swagger接口进行测试,成功!

http://www.lryc.cn/news/607297.html

相关文章:

  • 【AI 加持下的 Python 编程实战 2_12】第九章:繁琐任务的自动化(上)——自动清理电子邮件文本
  • 【Linux学习|黑马笔记|Day1】Linux初识、安装VMware Workstation、安装CentOS7、远程连接、虚拟机快照
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现围栏羊驼的检测识别(C#代码,UI界面版)
  • 标准项目-----网页五子棋(4)-----游戏大厅+匹配+房间代码
  • AJAX快速入门 - 四个核心步骤
  • HTML无尽射击小游戏包含源码,纯HTML+CSS+JS
  • 【Flutter】内存泄漏总结
  • 【数据可视化-78】2025年上半年广东省各市GDP排名深度解析与可视化:Python + Pyecharts 深度洞察(含完整数据、代码)
  • OpenVLA: 论文阅读 -- 开源视觉-语言-行动模型
  • ZKmall开源商城微服务架构电商平台:服务注册与配置中心设计
  • Spring Boot 整合量子密钥分发(QKD)实验方案
  • Linux---make和makefile
  • 分布在背侧海马体CA1区域的位置细胞(place cells)对NLP中的深层语义分析的积极影响和启示
  • 面试题:怎么理解 OSI 参考模型(开放式系统互联参考模型) 和 TCP/IP 模型(传输控制协议 / 网际协议模型 )
  • 【vue】Vue 项目创建工具对比:vue create 与 create-vue 的核心区别
  • RAGFLOW~knowledge graph
  • k8s部署mysql
  • 【数论】P8954 「VUSC」Math Game|普及+
  • SpringBoot3.x入门到精通系列:1.5 配置文件详解
  • QT6 源,十章绘图(2)画刷 QBrush:刷子只涉及填充颜色,线型,填充图片,以及变换矩阵这几个属性,附源代码带注释。
  • 京东零售在智能供应链领域的前沿探索与技术实践
  • 【Kubernetes 指南】基础入门——Kubernetes 集群(二)
  • Java抽象类与接口深度解析:核心区别与应用场景全指南
  • 四类屏幕录制方案的技术选型指南
  • 神经网络学习笔记
  • 流式编程的中间操作
  • 带root权限_中国移动创维DT541_S905L3融合机器改机顶盒刷机教程 当贝纯净版安卓9.0系统线刷包 刷机包
  • Rockchip RK3568J +FPGA边缘智能系统及储能网关
  • 【数据结构入门】顺序表
  • 了解Reddit自动化 社区营销更精准