
📝 开篇说明
本人是谷歌云(Google Cloud)的开发人员。本文观点完全代表个人意见。
本文完整源代码(含后续更新)可在此笔记本中获取,遵循Apache 2.0许可证。
文中所有新图像均由Gemini Nano Banana(概念验证模型)生成,原始图像均属于公共领域或可免费使用(代码输出中提供了参考链接)。
你可以在Google AI Studio中免费体验Gemini模型。关于程序化API访问,请注意:部分模型(如可执行对象检测的模型)提供免费试用,但图像生成服务采用按需付费模式。
✨ 概览
传统计算机视觉模型通常被训练为检测固定类别集合的对象,例如“人”“猫”或“汽车”。若要检测训练集中未包含的特定对象(如书籍照片中的“插图”),通常需要收集数据集、手动标注并训练自定义模型——这一过程可能耗时数小时甚至数天。
在本次探索中,我们将测试一种基于Gemini的全新方法。我们将利用其空间理解能力执行开放词汇(open-vocabulary)对象检测。这使我们能够仅通过自然语言描述定位对象,无需任何训练。
检测到视觉对象后,我们将提取它们,然后使用Gemini的图像编辑能力(特别是Nano Banana模型)对其进行修复和创意转换。
🔥 挑战
我们处理的是非结构化数据:书籍、杂志和野外物品的照片。这些图像对传统计算机视觉构成了多重挑战:
多样性:我们要寻找的对象(插图、雕刻画及所有视觉内容)在风格和内容上千差万别。
畸变:书页弯曲、拍摄角度倾斜、光线不均匀。
噪点:旧书存在污渍、纸张纹理、透字等问题。
我们的挑战是构建一个强大的流水线:尽管存在畸变,仍能检测这些对象、清晰提取它们,并编辑为高质量数字资产——全程仅使用简单文本提示。
🏁 环境搭建
🐍 Python依赖包
我们将使用以下包:
google-genai:谷歌生成式AI Python SDK,只需几行代码即可调用Gemini。pillow:图像管理。matplotlib:结果可视化。
同时需安装其依赖包:
pydantic:数据管理。tenacity:请求管理。
pip install --quiet "google-genai>=1.64.0" "pillow>=11.3.0" "matplotlib>=3.10.0"
🔗 Gemini API 接入方式
使用Gemini API主要有两种方式:
通过Vertex AI:关联谷歌云(Google Cloud)项目。
通过Google AI Studio:使用Gemini API密钥。
谷歌生成式AI SDK为这两种API提供统一接口,我们可通过环境变量进行配置。
🔽 定义以下环境检测函数(也可手动配置):
# (此处为代码逻辑,保留原文结构)
def check_environment():
# 环境检查逻辑
pass
def check_configuration(client):
# 配置检查逻辑
pass
🤖 生成式AI SDK 初始化
发送Gemini请求前,创建客户端:
from google import genai
check_environment()
client = genai.Client()
check_configuration(client)
🖼️ 图像测试集
定义测试图像列表:
# (此处为代码逻辑,保留原文结构)
class Source:
incunable = "path/to/incunable.jpg"
museum_guidebook = "path/to/museum_guidebook.jpg"
# 其他图像路径...
🧠 Gemini 模型版本选择
Gemini有多个版本,当前可用版本如下:
对象检测:Gemini 2.5 或 Gemini 3(均提供Flash/Pro版本)。
对象编辑:Gemini 2.5 Flash Image、Gemini 3 Pro Image 或 Gemini 3.1 Flash Image(即Nano Banana🍌、Nano Banana Pro🍌、Nano Banana 2🍌)。
🛠️ 辅助工具
添加核心辅助类和函数:
# (此处为代码逻辑,保留原文结构)
🔍 视觉对象检测
执行视觉对象检测时,精心设计提示词,明确指定要检测的对象及结果返回格式。在同一请求中,还可提取每个检测对象的附加信息——可以是标签(如“家具”“桌子”“椅子”)、更精确的分类(如“哺乳动物”“爬行动物”),或上下文数据(如图像标题、颜色、形状等)。
接下来的测试中,我们将尝试在书籍照片中检测插图。示例提示词如下:
ob ject_DETECTION_PROMPT = """
Detect every illustration within the book photo and extract the following data for each:
- `box_2d`: Bounding box coordinates of the illustration only (ignoring any caption).
- `caption`: Verbatim caption or legend such as "Figure 1". Use "" if not found.
- `label`: Single-word label describing the illustration. Use "" if not found.
"""
注意:
边界框(bounding box)对定位或提取检测对象非常有用。
对于Gemini模型,
box_2d边界框的坐标归一化到(0, 0, 1000, 1000)空间,对应输入图像的(0, 0, width, height)。我们还请求提取标题(参考书中常见的元数据)和标签(动态元数据)。
为自动化响应处理,建议定义一个与提示词匹配的Pydantic类:
import pydantic
class Detectedob ject(pydantic.BaseModel):
box_2d: list[int]
caption: str
label: str
Detectedob jects = list[Detectedob ject]
然后,通过response_mime_type和response_schema字段请求结构化输出:
from google.genai import GenerateContentConfig
config = GenerateContentConfig(
response_mime_type="application/json",
response_schema=Detectedob jects,
)
这将生成JSON响应,SDK可自动解析,让我们直接使用对象实例:
detected_ob jects = client.models.generate_content(
model="gemini-3-flash",
contents=image,
config=config,
)
detected_ob jects = cast(Detectedob jects, detected_ob jects.parsed)
添加对象检测专用类和函数:
# (此处为代码逻辑,保留原文结构)
def detect_ob jects(image_path, prompt=ob ject_DETECTION_PROMPT):
# 检测逻辑
pass
🧪 实战测试
1. 检测单张插图
测试1485年古版书中的单张插图:
detect_ob jects(Source.incunable)
*1485年古版书《Vergaderinge der historien van Troy》*|美国国会图书馆稀有书特藏部馆藏
Gemini检测的视觉对象
💡 效果极佳:边界框非常精确,紧密包围手工上色的木刻插图。
2. 检测多幅视觉内容
测试博物馆指南书中的多幅插图:
detect_ob jects(Source.museum_guidebook)
*1850年《Barnum’s American Museum illustrated》*|美国国会图书馆稀有书特藏部馆藏
Gemini检测的视觉对象
💡 评价:
边界框同样精确。
结果完美:无假阳性(误检)、无假阴性(漏检)。
插图下方的标题未被边界框包围(符合要求)。边界框的粒度可通过修改提示词控制。
3. 检测轻微畸变的视觉内容
测试梵高画作的开放书籍照片:
detect_ob jects(Source.paintings)
开放书籍展示梵高画作|图片由Trung Manh cong在Unsplash发布
Gemini检测的视觉对象
💡 无影响!注意右下角画作被橙色书签部分遮挡——我们将在修复步骤中尝试解决。
4. 检测倾斜的视觉内容
测试丹佛建筑书籍中倾斜的插图:
detect_ob jects(Source.denver_illustrated)
*1893年《Denver illustrated》*|美国国会图书馆“边境会议”馆藏
Gemini检测的视觉对象
💡 每个视觉内容都完美检测:空间理解能力覆盖倾斜对象。
5. 检测严重畸变的书页
测试《爱丽丝梦游仙境》中严重弯曲的书页:
detect_ob jects(Source.alice_drawing)
开放书籍展示《爱丽丝梦游仙境》的插图和文字|图片由Brett Jordan在Unsplash发布
Gemini检测的视觉对象
💡 书页弯曲等畸变不会阻碍非矩形对象的检测。实际上,空间理解在像素级工作——这解释了畸变对象的高精度。若需更精细处理,可在提示词中要求分割掩码(segmentation mask),将获得base64编码的PNG(每个像素给出0-255的概率,代表属于边界框内对象的可能性)。详见分割文档。
🏷️ 文本提取与动态标注
除了用边界框定位每个对象外,我们的提示词还要求提取逐字标题,并在可能时分配单字标签。
添加简单函数以表格形式显示检测数据:
# (此处为代码逻辑,保留原文结构)
def display_detection_data(image_path, show_consolidated=False):
# 显示逻辑
pass
博物馆指南书示例
动态标签根据上下文精确,插图下方的标题完美提取:
display_detection_data(Source.museum_guidebook)
| box_2d | label | caption |
|---|---|---|
| [954, 629, 1338, 1166] | beetle | "The Horned Beetle." |
| [265, 984, 464, 1504] | armor | "Armor of a Man." |
| [737, 984, 915, 1328] | armor | "Horse Armor." |
| [1225, 1244, 1589, 1685] | beetle | "The Goliath Beetle." |
| [264, 1766, 431, 2006] | mask | "The Mask." |
| [937, 1769, 1260, 2087] | butterfly | "Painted Lady Butterfly." |
| [1325, 2170, 1581, 2468] | butterfly | "The Lady Butterfly." |
梵高画作示例
四幅画作的检测结果同样完美:
display_detection_data(Source.paintings)
| box_2d | label | caption |
|---|---|---|
| [378, 203, 837, 575] | painting | "Hái Ô-liu (Olive Picking), tháng 12 năm 1889, sơn dầu trên toan, 28 3/4 x 35 in. [73 x 89 cm]" |
| [913, 207, 1380, 563] | painting | "Hẻm núi Les Peiroulets (Les Peiroulets Ravine), tháng 10 năm 1889, sơn dầu trên toan, 28 3/4 x 36 1/4 in. [73 x 92 cm]" |
| [387, 596, 845, 978] | painting | "Trưa: Nghỉ ngơi (phỏng theo Millet) (Noon: Rest from Work [after Millet]), tháng 1 năm 1890, sơn dầu trên toan, 28 3/4 x 35 7/8 in. [73 x 91 cm]" |
| [921, 611, 1397, 982] | painting | "Hoa hạnh đào (Almond Blossom), tháng 2 năm 1890, sơn dầu trên toan, 28 3/8 x 36 1/4 in. [73 x 92 cm]" |
丹佛建筑书籍示例
四个标题被正确分配给对应的插图——这并非易事:
display_detection_data(Source.denver_illustrated)
| box_2d | label | caption |
|---|---|---|
| [203, 224, 741, 839] | building | "ERNEST AND CRANMER BUILDING." |
| [743, 73, 1192, 758] | building | "PEOPLE’S BANK BUILDING." |
| [1185, 211, 1787, 865] | building | "BOSTON BUILDING." |
| [699, 754, 1238, 1203] | building | "COOPER BUILDING." |
💡 仔细观察输入图像,一眼很难判断哪个标题对应哪个插图。大多数人需要思考(且可能出错)。Gemini的结果是有意设计的,而非纯粹的运气:解读复古排版有点像解谜,但通常存在**“阅读顺序”逻辑**。在此案例中,标题的排列与图像按顺时针或Z字形(从左上角开始)对应。
《爱丽丝梦游仙境》示例
书页上只有一个插图伴随故事文字。如预期,标题为空(无假阳性):
display_detection_data(Source.alice_drawing)
| box_2d | label | caption |
|---|---|---|
| [111, 146, 1008, 593] | illustration | "" |
🔭 泛化到其他对象类型
相同原理可用于检测其他对象类型。通常我们会继续请求边界框以识别图像内对象位置。无需修改当前输出结构(即无需改代码),我们可根据输入类型使用标题和标签提取不同的对象元数据。
🧪 仅修改提示词,保持代码和输出结构不变,检测电子元件:
ELECTRONIC_COMPONENT_DETECTION_PROMPT = """
Exhaustively detect all the individual electronic components in the image and provide the following data for each:
- `box_2d`: bounding box coordinates.
- `caption`: Verbatim alphanumeric text visible on the component (including original line breaks), or "" if no text is present.
- `label`: Specific type of component.
"""
detect_ob jects(
Source.electronics,
ELECTRONIC_COMPONENT_DETECTION_PROMPT,
media_resolution=PartMediaResolutionLevel.MEDIA_RESOLUTION_ULTRA_HIGH,
)
电路板与电子元件|图片由Albert Stoynov在Unsplash发布
Gemini检测的视觉对象
💡 评价:
指令“exhaustively detect...”确保大元件和微小元件均被检测。
使用超高媒体分辨率,确保更多细节被标记,“P”元件(视觉异常值)也被检测到。
检测组件汇总:
display_detection_data(Source.electronics, show_consolidated=True)
| label | count | captions |
|---|---|---|
| integrated circuit | 3 | "49240↩️020S6K" • "8105↩️0:35" • "P4010↩️9NA0" |
| resistor | 4 | "" • "" • "105" • "R020" |
| inductor | 1 | "n1W" |
| diode | 3 | "K" • "L" • "P" |
| capacitor | 6 | "" • "" • "" • "" • "" • "" |
| transistor | 1 | "41" |
| connector | 1 | "" |
💡 评价:
尽管存在三种不同文本方向(正向、侧向、倒置)、模糊和照片噪点,组件及其文本标记仍被准确检测。
提示词中指定包含“原始换行符”,消除了多行文本的
推荐学习书籍 《CDA一级教材》适合CDA一级考生备考,也适合业务及数据分析岗位的从业者提升自我。完整电子版已上线CDA网校,累计已有10万+在读~ !



雷达卡





京公网安备 11010802022788号







