阿里云PAI-Stable Diffusion开源代码浅析之(二)我的png info怎么有乱码

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
实时计算 Flink 版,5000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 阿里云PAI-Stable Diffusion开源代码浅析之(二)我的png info怎么有乱码

1. 问题

阿里云PAI平台官方Stable Diffusion(以下简称sd)镜像EAS服务上传PNG图片调用/sdapi/v1/png-info接口返回乱码。

镜像版本:eas-registry-vpc.cn-shanghai.cr.aliyuncs.com/pai-eas/stable-diffusion-webui:4.2

./webui.sh --listen --port 8000 --skip-version-check --no-hashing --skip-prepare-environment --api-log --time-log --nowebui --xformers --enable-extensions stable-diffusion-webui-wd14-tagger multidiffusion-upscaler-for-automatic1111 adetailer sd-webui-3d-open-pose-editor  --embeddings-dir /code/stable-diffusion-webui/data-oss-api/embeddings

请求异常返回截图:

image.png

测试图片用例:

📎客户图片.png

2. 系列文档传送门

https://developer.aliyun.com/article/1574263

3. 环境搭建与问题复现

3.1. webui测试用例图片生成

同是sd问题,我们通过sd的webui界面配合中英文的promt和相关参数来生成测试用例的png图片尝试调用API

promt:a cute dog

Negative prompt: 不要屋内的景色

其余参数保持默认(见下图)

image.png

生成测试用例PNG图片:

📎cute_dog.png

3.2. webui png图片信息测试

image.png

3.3. api请求本地测试与问题复现

3.3.1. 测试代码

这里用相同的镜像拉了一个EAS的服务,测试代码由于涉及多个path的请求所以自己通过requests构建了自定义http请求,相关代码说明见注释。

import json
import requests
import io
import base64
from pprint import pprint
from PIL import Image, PngImagePlugin
from PIL.PngImagePlugin import PngInfo
# eas服务请求的endpoint
url = "http://1623027246845796.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/sunyf_sd_test02.sunyf_sd_test02_9245177a"
if __name__ == '__main__':
    # 打开测试用例图片,二进制读
    with open('/Users/adamsun/Downloads/cute_dog.png', 'rb') as image_file:
        # 采用base64编码
        encoded_string = base64.b64encode(image_file.read())
    # 根据编码后的string构建请求的png信息
    png_payload = {
        "image": "data:image/png;base64," + encoded_string.decode('utf-8')
    }
    # headers中包含认证的token
    headers = {"Authorization": 'xxx=='}
    # api请求
    response2 = requests.post(url=f'{url}/sdapi/v1/png-info'
                              ,json=png_payload
                              ,headers=headers
                              )
    pprint(response2.json())

3.3.2. 本地测试用例(正常)

image.png

3.3.3. 客户部分代码节选

可以看到客户代码中对于http请求的header以及entity以及png图像的都通过charset的方式指定了utf-8(与eas底层所在系统保持一致)

(image客户采用的是

data:image/png;base64,<编码图像数据>

的方式进行数据传输和接口请求)

注:base64编码后decode的charset也是utf-8

image.png

3.3.4. 本地测试客户图例(乱码)

image.png

4. 源码浅析

通过登录eas的容器我们可以找到当前eas内置的sd服务4.2版本的Dockerfile

image.png

对应源码地址:https://gitee.com/stable_diffusion/stable-diffusion-webui/tree/v1.6.0/。我们通过git clone的方式将源码下载到本地。

书接上文,api的请求都是通过fastapi做的封装,如下是入口类

from modules.api.api import Api

通过调用的api path我们可以看到

self.add_api_route("/sdapi/v1/png-info", self.pnginfoapi, methods=["POST"], response_model=models.PNGInfoResponse)

/sdapi/v1/png-info对应的handler方法是pnginfoapi,对应的返回体是models.PNGInfoResponse

image.png

对应方法pnginfoapi中,比较关键的是如下三个方法的调用:

  1. decode_base64_to_image(req.image.strip())
  2. images.read_info_from_image(image)
  3. infotext_utils.parse_generation_parameters(geninfo)

image.png

decode_base64_to_image方法的输入是api请求的request对象,将json string中的image作为入参。根据入参的样式分成两部分:

  1. https和http开头的连接会通过请求的方式获取图片并转换成BytesIO
  2. data:image/开头的会取data:image/png;base64,<编码图像数据>后面编码后的数据转换成BytesIO

随后通过sd项目中实现的./stable-diffusion-webui/modules/images.py 的modules.images.read方法封装成pillow库的Image.Image对象

image.png

images.read_info_from_image(image)方法对读入的Image对象做信息提取

items取的就是Image对象的info属性

geninfo取info属性字段中parameters的信息

后续代码还涉及了EXIF、GIF、pop掉忽略的kv以及NovelAI类型图像的信息处理

image.png

infotext_utils.parse_generation_parameters(geninfo)方法以前面提取出的图像中的info作为输入,返回的是api返回体中parameters的部分,这里主要是解析与图像生成相关参数的部分,包含promt、negative prompt、steps、sampler等,没有字符集相关的特殊处理。

return models.PNGInfoResponse(info=geninfo, items=items, parameters=params)

后续pnginfoapi方法返回的response继承自BaseModel的基础数据类,提供数据验证以及序列化支持,charset也都是utf-8。

可以判断的是从接收到请求到api接口处理完成对于png图片info均没有不合预期的编码行为。

5. 本地调试与问题原因

请求客户端、服务端处理逻辑以及服务端所在机器默认charset均没有异常的情况下尝试本地调试。

根据源码读取请求图片数据以及转换成Image对象的逻辑,本地直接采用

Image.open

的方法读取客户提供的图片,根据read_info_from_image的逻辑来看图片本身的info信息中就已经含有乱码,与客户侧验证后确认也确实仅有这一张第三方图片解析乱码异常,猜测应该是图片保存时环境或其他因素存在编码异常,非PAI平台侧问题

image.png

相关文章
|
2天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1519 4
|
29天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
5天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
502 19
|
2天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
179 1
|
8天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
21天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
9天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
457 5
|
7天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
314 2
|
23天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
25天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2608 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析

热门文章

最新文章