ofa_image-caption代码实例:扩展支持WebP格式与EXIF元数据保留功能

ofa_image-caption代码实例:扩展支持WebP格式与EXIF元数据保留功能

1. 引言

你有没有遇到过这种情况?从手机或相机里导出一堆照片,想快速整理归档,却要一张张手动写描述,费时又费力。或者,在做内容创作时,需要为大量图片配上精准的英文说明,人工处理效率极低。

今天要介绍的这个工具,就是来解决这个痛点的。它叫 ofa_image-caption,是一个纯本地运行的图像描述生成工具。简单来说,你给它一张图,它就能用英文告诉你这张图里有什么。

这个工具的核心是基于一个叫 OFA 的模型,这个模型在图像描述生成领域表现很不错。我们之前发布的版本已经能很好地处理 JPG、PNG 这些常见格式了。但最近,越来越多的用户开始使用 WebP 这种更高效的图片格式,同时,很多摄影师和内容创作者也希望生成的描述能保留图片拍摄时的原始信息(比如拍摄时间、相机型号)。

所以,我们对这个工具进行了一次重要的升级。这篇文章,我就带你手把手看看,我们是如何在原有代码基础上,扩展了对 WebP 格式的支持,并实现了 EXIF 元数据的保留功能。整个过程就像给一个工具加上了两个非常实用的“配件”,让它能适应更多场景,更好用。

2. 项目回顾与升级目标

在开始动手改代码之前,我们先快速回顾一下这个工具原本是干什么的,以及我们这次想让它变得多能干。

2.1 原有工具的核心功能

这个工具本质上是一个本地化的“看图说话”小助手。它的工作流程非常清晰:

  1. 你上传一张图片(之前支持 JPG, PNG, JPEG)。
  2. 工具在后台调用 OFA 模型,这个模型是专门在 COCO 英文数据集上训练过的,所以它“说”的是英文。
  3. 工具把模型生成的英文描述,通过一个简洁的网页界面展示给你看。

整个工具基于 ModelScope 和 Streamlit 搭建,最大的优点就是纯本地运行,你的图片数据不会上传到任何服务器,隐私有保障,而且如果电脑有独立显卡(GPU),推理速度会非常快。

2.2 本次升级要解决的两个问题

随着用户增多,我们收到了两类反馈:

  1. 格式支持问题:“我有很多网站截图和素材是 WebP 格式的,上传不了,还得先转换,太麻烦了。”
  2. 信息关联问题:“生成的描述很好,但如果能和我照片自带的拍摄信息(EXIF)一起保存下来,对我后续整理和归档就太有帮助了。”

因此,我们这次代码升级的目标非常明确:

  • 目标一:让工具能直接读取和处理 WebP 格式的图片。
  • 目标二:在生成描述的同时,把图片原始的 EXIF 元数据(如果有的话)提取并保留下来,方便后续使用。

下面,我们就进入实战环节,看看代码具体是怎么改的。

3. 代码实战:扩展WebP格式支持

原来工具里,限制图片格式的代码可能长这样(在文件上传组件处):

uploaded_file = st.file_uploader( " 上传图片", type=['jpg', 'jpeg', 'png'] # 这里只定义了三种格式 ) 

看到问题了吗?type 列表里没有 webp。所以用户上传 WebP 文件时,会被直接过滤掉,根本选不中。

解决方案非常简单,只需要加一个后缀名:

uploaded_file = st.file_uploader( " 上传图片", type=['jpg', 'jpeg', 'png', 'webp'] # 新增 ‘webp’ ) 

但是,故事还没完。 Streamlit 的 file_uploader 只是前端的“门卫”,它放行了 WebP 文件。文件传到后台 Python 代码里,我们需要用 PIL(Python 图像处理库)来打开它。如果 PIL 版本太旧,可能不认识 WebP。

所以,我们需要确保开发环境和部署环境里的 PIL(或其社区维护的活跃分支 Pillow)支持 WebP。这通常不是大问题,因为现代版本的 Pillow 基本都支持。不过,为了万无一失,我们可以在项目的依赖文件(如 requirements.txt)里明确一下 Pillow 的版本。

# requirements.txt 示例 streamlit>=1.28.0 modelscope>=1.9.0 pillow>=9.0.0 # 确保使用一个较新且稳定支持WebP的版本 

这样一来,从上传到打开,整个通路就对 WebP 格式畅通无阻了。用户现在可以直接上传 .webp 文件,工具会像处理 JPG 一样处理它。

4. 代码实战:提取与保留EXIF元数据

EXIF 是嵌入在图片文件里的一串信息,就像图片的“身份证”,记录着拍摄设备、时间、光圈、快门甚至 GPS 位置等。保留这些信息对摄影爱好者、内容管理非常有价值。

4.1 如何提取EXIF信息

我们继续使用 Pillow 库。一张图片被 PIL 打开后,我们可以通过 _getexif() 方法来尝试获取其 EXIF 数据。

下面是一个简单的函数示例,我们把它加到工具的核心代码里:

from PIL import Image import PIL.ExifTags def extract_exif(image_path): """ 提取图片的EXIF元数据。 参数: image_path: 图片文件的路径。 返回: 一个字典,包含可读的EXIF标签和值;如果无EXIF或读取失败,返回空字典。 """ exif_data = {} try: img = Image.open(image_path) # 获取原始的EXIF数据 info = img._getexif() if info: # 将数字标签码转换为可读的字符串标签 for tag, value in info.items(): decoded_tag = PIL.ExifTags.TAGS.get(tag, tag) exif_data[decoded_tag] = value except Exception as e: # 记录错误或忽略(对于没有EXIF的图片是正常的) print(f"读取EXIF时出错: {e}") return exif_data 

这个函数做了几件事:

  1. 尝试用 PIL 打开图片。
  2. 调用 _getexif() 获取原始数据。
  3. 将枯燥的数字标签(如 36867)转换成我们能看懂的文字(如 DateTimeOriginal)。
  4. 把所有信息存到一个字典里返回。

4.2 如何与描述结果一起展示

光提取出来还不够,我们需要让用户看到它。一个直观的做法是,在 Streamlit 界面上生成描述后,新增一个展示区域来显示 EXIF。

假设我们原来的结果显示是这样的:

if caption: st.success("生成成功!") st.markdown(f"**生成描述:** {caption}") 

现在我们可以升级一下:

if caption: st.success("生成成功!") st.markdown(f"**生成描述:** {caption}") # 新增:提取并显示EXIF信息 exif_info = extract_exif(temp_image_path) # temp_image_path是工具保存的临时图片路径 if exif_info: with st.expander("📸 查看图片EXIF元数据"): # 用一个可折叠区域,保持界面整洁 # 展示一些最常见、最有用的EXIF字段 if 'DateTimeOriginal' in exif_info: st.text(f"拍摄时间: {exif_info['DateTimeOriginal']}") if 'Make' in exif_info and 'Model' in exif_info: st.text(f"拍摄设备: {exif_info['Make']} {exif_info['Model']}") if 'ExposureTime' in exif_info: st.text(f"曝光时间: {exif_info['ExposureTime']} 秒") if 'FNumber' in exif_info: st.text(f"光圈值: f/{exif_info['FNumber']}") if 'ISOSpeedRatings' in exif_info: st.text(f"ISO感光度: {exif_info['ISOSpeedRatings']}") # 用户可以选择查看所有EXIF数据 if st.checkbox("显示全部EXIF信息"): st.json(exif_info) # 用JSON格式美观地展示 else: st.info("此图片未包含EXIF元数据。") 

这样一来,工具在生成英文描述后,如果图片有 EXIF,用户就能一目了然地看到关键的拍摄信息,并且可以展开查看全部详情。这对于需要根据拍摄信息来分类或描述图片的用户来说,功能就完整多了。

5. 完整功能演示与效果

让我们把上面所有的代码片段组合起来,看看升级后的工具实际运行效果如何。

5.1 操作流程演示

  1. 启动工具:在命令行运行 streamlit run app.py,打开浏览器。
  2. 上传混合格式图片:你可以同时尝试上传 test.jpg, screenshot.png, 和 photo.webp。你会发现,现在所有格式都能被成功选中并上传。
  3. 生成描述与查看EXIF
    • 上传一张用单反或手机拍摄的、带有EXIF的JPG照片(比如你相机里的原图)。
    • 点击“生成描述”。稍等片刻,界面首先会弹出绿色的成功提示,并显示生成的英文描述,例如 “生成描述: a person is riding a skateboard on a street.”
    • 在描述下方,会出现一个写着 “📸 查看图片EXIF元数据” 的可点击区域。点击展开,你就能看到拍摄时间、相机型号等具体信息。
    • 如果上传的是一张从网络下载的、已剥离EXIF的PNG图片,或者是一张简单的截图,那么工具会友好地提示“此图片未包含EXIF元数据”。

5.2 升级带来的价值

通过这两项看似不大的升级,这个本地图像描述工具的能力边界得到了有效拓展:

  • 格式兼容性更强:无缝支持WebP,覆盖了更广泛的图片来源,特别是互联网内容。
  • 信息维度更丰富:从单一的“视觉内容描述”升级为“视觉内容+拍摄元数据”的复合信息输出。这使得生成的结果不再是孤立的文本,而是能与原始资产(照片)紧密关联的结构化信息。
  • 应用场景更广:对于摄影师,可以快速批量为照片库生成描述并附带拍摄参数;对于内容管理者,可以更好地对图片素材进行自动化打标和归档。

6. 总结

回顾一下我们这次对 ofa_image-caption 工具的升级之旅。整个过程就像是一次精准的“外科手术”:

  1. 诊断需求:我们发现了用户在处理 WebP 格式和需要 EXIF 信息时的痛点。
  2. 实施改造
    • 通过修改 file_uploadertype 列表,轻松扩展了 WebP 格式支持
    • 通过编写 extract_exif 函数并集成到结果展示界面,优雅地实现了 EXIF 元数据的提取与展示
  3. 验证效果:升级后的工具,在保持原有核心功能(快速、本地、英文描述)的同时,显著提升了实用性和用户体验。

这个案例也告诉我们,一个好的工具并非一成不变。围绕用户真实的使用场景,通过一些针对性的、轻量级的代码改进,就能让工具焕发新的活力,解决更实际的问题。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 ZEEKLOG星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Read more

2026款网页版AI Chat对话|Vite7+Vue3+DeepSeek-R1纯手搓web版流式ai聊天系统

2026款网页版AI Chat对话|Vite7+Vue3+DeepSeek-R1纯手搓web版流式ai聊天系统

最新原创vite7.2集成deepseek-v3.2聊天大模型搭建本地网页版Ai对话。 deepseek-vue3-webai:运用vite7.2+vue3.5+arco-design集成deepseek-v3.2打造网页版ai系统。提供浅色/暗黑两种主题、深度思考R1、代码高亮/复制、Latex数学公式、Mermaid图表渲染。 技术栈 * 编辑器:VScode * 前端框架:vite7.2.4+vue3.5.24+vue-router^4.6.4 * 大模型框架:DeepSeek-R1 + OpenAI * 组件库:arco-design^2.57.0 (字节桌面端组件库) * 状态管理:pinia^3.0.4 * 本地存储:pinia-plugin-persistedstate^4.7.1

Android集成WebRTC与VAD的AI辅助开发实战:从选型到性能优化

快速体验 在开始今天关于 Android集成WebRTC与VAD的AI辅助开发实战:从选型到性能优化 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 Android集成WebRTC与VAD的AI辅助开发实战:从选型到性能优化 移动端实时语音处理一直是个技术难点。根据实测数据,普通Android设备处理16kHz采样率的音频流时,仅WebRTC基础通话就会占用12-15%的CPU资源,如果再加上VAD检测,CPU占用可能飙升到25%以上。更棘手的是,从麦克风采集到

高性能OCR落地利器|DeepSeek-OCR-WEBUI开源实践

高性能OCR落地利器|DeepSeek-OCR-WEBUI开源实践 1. 引言:OCR技术的工程化挑战与新解法 在数字化转型加速的背景下,光学字符识别(OCR)已成为文档自动化、信息提取和智能审核等场景的核心技术。然而,传统OCR方案在面对复杂版面、模糊图像或多语言混合文本时,往往表现不佳,且部署流程繁琐,严重制约了其在实际业务中的广泛应用。 DeepSeek-OCR 的出现为这一难题提供了全新思路。作为一款基于深度学习的大模型驱动OCR系统,它不仅具备高精度、强鲁棒性的识别能力,更通过 DeepSeek-OCR-WEBUI 这一开源项目实现了“零代码+网页端交互”的极简使用模式。本文将围绕该镜像的技术特性、部署流程与核心功能展开详细解析,帮助开发者快速掌握其工程化落地方法。 2. 技术架构解析:DeepSeek-OCR的核心优势 2.1 模型设计原理 DeepSeek-OCR 采用 CNN + Transformer注意力机制 的混合架构: * 前端卷积网络(CNN) 负责图像特征提取,对倾斜、模糊、低分辨率等退化图像具有良好的适应性; * 中段序列建模模块 利

JWT 技术(JSON Web Token) 全解:原理、应用与生产级避坑指南

笔者阅读很多 JWT 技术的博文,发现大多只是讲 “JWT 是什么”,而这篇文章重点介绍它为什么出现、结构细节、以及生产环境中最棘手的“注销与续签”问题。 在前后端分离、微服务架构大行其道的今天,JWT(JSON Web Token)几乎成为了身份认证的代名词。 很多开发者只知道它是一个“长长的字符串”,用来做登录校验,但并不清楚它内部的运作机制,以及它在安全性上的潜在风险。本文将从原理、结构、流程、以及最核心的生产陷阱四个维度进行详细拆解。 一、为什么需要 JWT?(Session vs Token) 在 JWT 出现之前,我们主要使用 Session + Cookie 的方式。 1.传统Session的认证痛点 * 服务端有状态:服务端需要保存 Session 数据(内存或Redis)。 * 扩展性差:集群环境下,必须做