当前位置: 首页 > 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.dtcms.com/a/309087.html

相关文章:

  • 渗透测试报告通常包含哪些关键内容?
  • redis快速部署、集成、调优
  • Linux通用SPI作为Master——回环测试
  • Redis学习-----Redis的基本数据类型
  • Dify版本升级实操
  • Edge中如何找到原IE浏览器的Internet选项
  • 基于html,css,jquery,django,lstm,cnn,tensorflow,bert,推荐算法,mysql数据库
  • 8月1日RED指令强制生效,您的设备准备好了吗?
  • uniapp 开发微信小程序,获取经纬度(uni.getLocation)并且转化详细地址(‌高德地图逆地理编码API、‌腾讯地图逆地理编码)
  • 【华为机试】127. 单词接龙
  • Python match-case 模式匹配详解
  • 【Mysql】字段隐式转换对where条件和join关联条件的影响
  • 【Java面试题】缓存穿透
  • 什么是doris
  • 优化网站域名的SEO策略指南
  • Qt开发中的安全技术问题详解
  • MySQL(172)如何进行MySQL的全局变量设置?
  • 深度揭秘端口映射:原理、场景、路由映射故障,与内网IP端口映射外网工具的选择
  • 微服务消息队列之RabbitMQ,深入了解
  • 逻辑斯蒂回归的模型优化
  • IO流-文件实例
  • MySQL--组从复制的详解及功能演练
  • 数据赋能(371)——数据挖掘——概述
  • java的冒泡排序算法
  • 从O(n²)到O(n log n):深度剖析快速排序的内存优化与cache-friendly实现
  • Java Map和Set
  • Vue 3.5 defineModel:让组件开发效率提升 10 倍
  • 自行实现log2对数运算
  • Pydantic模块学习
  • TDengine 中 TDgp 中添加机器学习模型