Stable-Diffusion-v1-5-archive多模态延伸结合CLIP特征提取做图像语义检索案例你是不是经常遇到这种情况电脑里存了几百上千张用Stable Diffusion生成的图片想找一张“在森林里穿红裙子的女孩”的图结果只能一张张翻眼睛都看花了也找不到或者作为一个内容创作者你希望从自己庞大的作品库中快速找到风格、主题相似的图片来制作系列内容却苦于没有高效的检索工具。今天我就带你玩点不一样的。我们不只把Stable Diffusion v1.5当成一个单纯的文生图工具而是把它和另一个强大的AI模型——CLIP结合起来打造一个属于你自己的、能“看懂”图片内容的智能图库检索系统。你只需要用文字描述你想找的图片系统就能帮你从海量图片中精准定位。1. 项目思路让图库“听懂人话”传统的图片管理靠的是文件名、文件夹或者手动打标签。这种方法费时费力还不准确——你怎么能用几个关键词完全概括一张富有细节的AI生成图呢我们的思路是“以子之矛攻子之盾”生成利用Stable Diffusion v1.5 Archive生成大量高质量、多样化的图片作为我们的测试图库。理解利用CLIP模型为图库里的每一张图片提取一个“语义特征向量”。这个向量就像图片的“数字指纹”编码了图片的视觉内容和语义信息。检索当你想找图时同样用CLIP模型把你的文字描述如“星空下的孤独骑士”也转换成一个“文本特征向量”。匹配计算你的文本向量和图库中所有图片向量的相似度把最相似的图片找出来给你看。核心优势自然语言检索直接用“雨后初晴的古镇小巷”这样的句子搜图无需记忆文件名。语义级理解系统理解的是概念。搜“快乐的动物”它既可能返回微笑的狗也可能是玩耍的猫。完全私有化你的图片库和检索系统都在自己掌控中无需上传到第三方安全隐私。2. 环境搭建与工具准备在开始动手之前我们需要准备好“武器库”。别担心我会带你一步步来。2.1 核心模型与库我们这个项目主要依赖两个核心Stable Diffusion v1.5 Archive用于生成构建图库所需的图片。我们已经通过CSDN星图镜像广场一键部署好了WebUI服务可以直接使用。CLIP (OpenAI)用于提取图片和文本的特征向量。我们将使用Hugging Facetransformers库中提供的CLIP模型。2.2 安装Python依赖打开你的终端或命令行创建一个新的Python虚拟环境推荐然后安装必要的包# 创建并激活虚拟环境 (可选但推荐) python -m venv sd_clip_search source sd_clip_search/bin/activate # Linux/Mac # sd_clip_search\Scripts\activate # Windows # 安装核心依赖 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 根据你的CUDA版本调整 pip install transformers pillow requests tqdm pip install numpy scikit-learn # 用于向量计算和相似度排序简单解释一下torchPyTorch深度学习框架CLIP模型运行的基础。transformersHugging Face的库提供了便捷的CLIP模型加载和使用接口。pillowPython图像处理库用于读取和预处理图片。requests用于通过HTTP API调用我们部署好的Stable Diffusion服务。tqdm显示进度条让你知道处理到哪了。numpy/scikit-learn进行高效的数学计算特别是向量间的相似度比较。3. 第一步构建你的专属AI图库我们的图库不能空空如也。我们先利用Stable Diffusion服务批量生成一批风格各异的图片。3.1 编写批量图片生成脚本我们写一个Python脚本通过调用Stable Diffusion WebUI的API通常基于Gradio来生成图片。这里假设你的服务地址是https://gpu-xxxx-7860.web.gpu.csdn.net/。创建一个名为generate_image_library.py的文件import requests import json import time from tqdm import tqdm import os # 配置 SD_API_URL https://gpu-你的实例ID-7860.web.gpu.csdn.net/ # 请替换为你的实际地址 OUTPUT_DIR ./sd_generated_images os.makedirs(OUTPUT_DIR, exist_okTrue) # 这是一组用于构建多样化图库的提示词 PROMPT_LIST [ a majestic lion resting on a savanna, golden hour, photorealistic, a cyberpunk city street at night, neon lights, rainy, detailed, an ancient Chinese palace in snow, serene, landscape painting style, a cute cartoon cat astronaut floating in space, simple background, a bowl of ramen on a wooden table, steam rising, food photography, a fantasy elf archer in a enchanted forest, digital art, vibrant colors, a vintage car parked in an autumn forest, path covered with leaves, a minimalist modern living room with large windows, sunny, 3d render, a terrifying monster emerging from fog, dark fantasy, highly detailed, a beautiful woman with red dress in a field of sunflowers, oil painting style, a samurai standing on a cliff overlooking the ocean, sunset, ukiyo-e, a bustling medieval marketplace, many people, fantasy illustration, a lonely lighthouse on a stormy coast, waves crashing, dramatic, a macro photography of a bee on a purple flower, sharp focus, a steampunk flying machine, intricate gears, copper and brass, sketch ] def generate_image(prompt, index): 调用Stable Diffusion API生成单张图片 # 构造API请求负载 (根据你的WebUI API格式调整) payload { prompt: prompt, negative_prompt: lowres, bad anatomy, blurry, duplicate, steps: 25, cfg_scale: 7.5, width: 512, height: 512, seed: -1, # 随机种子 } try: # 注意不同WebUI的API端点可能不同常见的是 /run/predict 或 /api/predict # 你需要查看你部署的WebUI的API文档。这里是一个通用示例。 response requests.post(f{SD_API_URL}run/predict, json{data: [json.dumps(payload)]}) response.raise_for_status() # 解析响应这里需要根据实际API返回结构调整 # 通常API会返回图片的base64编码或直接返回图片文件 # 为了简化我们假设API返回JSON其中包含图片的base64数据 result response.json() # 此处需要你根据实际的API响应格式来提取和保存图片 # 例如如果返回base64: # image_data result[data][0].split(,)[1] # 如果包含data:image前缀 # img Image.open(io.BytesIO(base64.b64decode(image_data))) # img.save(os.path.join(OUTPUT_DIR, fimage_{index:03d}.png)) print(f已生成图片 {index}: {prompt[:50]}...) # 由于API格式不确定这里先模拟保存一个提示文件 with open(os.path.join(OUTPUT_DIR, fprompt_{index:03d}.txt), w) as f: f.write(prompt) time.sleep(2) # 避免请求过于频繁 except Exception as e: print(f生成图片 {index} 时出错: {e}) def main(): print(f开始生成图片到目录: {OUTPUT_DIR}) for i, prompt in enumerate(tqdm(PROMPT_LIST)): generate_image(prompt, i) print(图片生成完成) if __name__ __main__: main()重要提示上面的代码中的API调用部分是一个示例框架。你需要根据你实际部署的Stable Diffusion WebUI的API接口文档来调整payload的格式和解析响应的方法。有些WebUI如Automatic1111有特定的API插件和调用方式。一个更简单可靠的方法是手动操作WebUI生成这15张图并保存到./sd_generated_images文件夹并将对应的提示词保存在同名的txt文件中如image_001.png和image_001.txt。这对于小规模图库构建来说更直接。3.2 生成结果运行脚本或手动操作后你的./sd_generated_images目录下应该有了一批PNG图片和对应的提示词文本文件。我们的图库就有了第一批“居民”。4. 第二步用CLIP为图片办理“身份证”现在我们需要让CLIP模型来“观看”并理解我们图库里的每一张图片为它们生成那个唯一的“语义特征向量”。创建一个名为extract_image_features.py的脚本import torch from PIL import Image from transformers import CLIPProcessor, CLIPModel import os from tqdm import tqdm import numpy as np import pickle # 配置 IMAGE_DIR ./sd_generated_images FEATURE_FILE ./image_features.pkl MODEL_NAME openai/clip-vit-base-patch32 # 使用基础版CLIP速度较快 # 加载CLIP模型和处理器 print(正在加载CLIP模型...) device cuda if torch.cuda.is_available() else cpu model CLIPModel.from_pretrained(MODEL_NAME).to(device) processor CLIPProcessor.from_pretrained(MODEL_NAME) model.eval() # 设置为评估模式 # 获取所有图片文件 image_extensions (.png, .jpg, .jpeg, .bmp, .gif) image_paths [os.path.join(IMAGE_DIR, f) for f in os.listdir(IMAGE_DIR) if f.lower().endswith(image_extensions)] print(f发现 {len(image_paths)} 张图片。) image_features [] image_filenames [] # 批量处理图片提取特征 batch_size 8 for i in tqdm(range(0, len(image_paths), batch_size), desc提取图片特征): batch_paths image_paths[i:ibatch_size] images [] valid_paths [] # 加载图片 for path in batch_paths: try: img Image.open(path).convert(RGB) images.append(img) valid_paths.append(path) except Exception as e: print(f无法加载图片 {path}: {e}) continue if not images: continue # 使用处理器准备模型输入 inputs processor(imagesimages, return_tensorspt, paddingTrue).to(device) # 提取图片特征不计算梯度以节省内存 with torch.no_grad(): image_embeds model.get_image_features(**inputs) # 将特征向量归一化方便后续计算余弦相似度 image_embeds image_embeds / image_embeds.norm(dim-1, keepdimTrue) image_embeds image_embeds.cpu().numpy() # 转移到CPU并转为NumPy数组 # 保存特征和文件名 for emb, path in zip(image_embeds, valid_paths): image_features.append(emb) image_filenames.append(os.path.basename(path)) # 保存特征到文件 with open(FEATURE_FILE, wb) as f: pickle.dump({filenames: image_filenames, features: image_features}, f) print(f图片特征已保存至 {FEATURE_FILE}) print(f特征向量维度: {image_features[0].shape})运行这个脚本它会遍历你的图片目录使用CLIP模型为每张图片计算一个512维对于clip-vit-base-patch32模型的特征向量并保存到一个.pkl文件中。这个文件就是你的图库的“索引数据库”。5. 第三步实现语义检索功能万事俱备只欠检索。现在我们来编写核心的搜索功能。创建一个名为semantic_search.py的脚本import torch import numpy as np from transformers import CLIPProcessor, CLIPModel import pickle from PIL import Image import os from sklearn.metrics.pairwise import cosine_similarity # 配置 FEATURE_FILE ./image_features.pkl IMAGE_DIR ./sd_generated_images MODEL_NAME openai/clip-vit-base-patch32 TOP_K 5 # 返回最相似的前几张图 # 加载之前保存的图片特征 print(正在加载图片特征库...) with open(FEATURE_FILE, rb) as f: data pickle.load(f) all_filenames data[filenames] all_features np.array(data[features]) # 形状为 [图片数量, 特征维度] # 加载CLIP模型用于处理文本查询 device cuda if torch.cuda.is_available() else cpu model CLIPModel.from_pretrained(MODEL_NAME).to(device) processor CLIPProcessor.from_pretrained(MODEL_NAME) model.eval() def search_by_text(query_text): 根据文本描述搜索图片 print(f搜索: {query_text}) # 处理文本输入提取文本特征 inputs processor(text[query_text], return_tensorspt, paddingTrue).to(device) with torch.no_grad(): text_embeds model.get_text_features(**inputs) text_embeds text_embeds / text_embeds.norm(dim-1, keepdimTrue) text_feature text_embeds.cpu().numpy() # 计算文本特征与所有图片特征的余弦相似度 similarities cosine_similarity(text_feature, all_features).flatten() # 获取相似度最高的TOP_K个索引 top_indices np.argsort(similarities)[-TOP_K:][::-1] # 打印并准备结果显示 results [] print(f\n找到 {TOP_K} 个最相关的结果:) for rank, idx in enumerate(top_indices, 1): score similarities[idx] filename all_filenames[idx] print(f {rank}. {filename} (相似度: {score:.4f})) img_path os.path.join(IMAGE_DIR, filename) results.append((img_path, score)) return results def display_results(results): 简单展示结果在实际应用中你可以用Web界面展示 try: from matplotlib import pyplot as plt import matplotlib.image as mpimg fig, axes plt.subplots(1, len(results), figsize(15, 5)) if len(results) 1: axes [axes] for ax, (img_path, score) in zip(axes, results): img mpimg.imread(img_path) ax.imshow(img) ax.set_title(fScore: {score:.3f}) ax.axis(off) plt.tight_layout() plt.show() except ImportError: print(如需可视化结果请安装 matplotlib: pip install matplotlib) for img_path, score in results: print(f 图片路径: {img_path}) # 主循环交互式搜索 if __name__ __main__: print(CLIP语义图像检索系统已启动) print(输入你的描述例如a lion in the wild或输入 quit 退出。) while True: try: query input(\n 请输入搜索描述: ).strip() if query.lower() in [quit, exit, q]: print(再见) break if not query: continue results search_by_text(query) # 取消下面一行的注释以显示图片需要matplotlib # display_results(results) except KeyboardInterrupt: print(\n程序被中断。) break except Exception as e: print(f搜索过程中发生错误: {e})6. 实战演示看看效果如何现在让我们运行python semantic_search.py来体验一下这个系统的魔力。场景一概念搜索你输入“an animal with fur”有毛的动物。系统可能会返回狮子的图片、猫的图片。即使你的提示词里没有“狮子”或“猫”CLIP也能理解“动物”和“毛皮”这个概念找到语义相关的图片。场景二风格和氛围搜索你输入“a peaceful landscape painting”宁静的风景画。系统可能会优先返回那张“雪中中式宫殿”的图片因为CLIP能捕捉到“宁静”、“风景”、“绘画风格”这些语义和视觉特征。场景三具体细节搜索你输入“vehicle in a natural setting”自然环境中的交通工具。系统很可能找到“森林里的复古汽车”和“赛博朋克街道”的图片并对前者给出更高的相似度分数因为它更符合“自然”这个语境。你会发现这种检索方式远比基于文件名的搜索强大和直观。它真正理解了图片的“内容”。7. 总结与进阶思路通过这个案例我们完成了一次有趣的多模态AI实践将Stable Diffusion的生成能力与CLIP的理解能力相结合构建了一个实用的语义图像检索系统原型。7.1 核心回顾生成建库利用SD v1.5快速构建了一个多样化的小型AI图像库。特征提取使用CLIP模型为库中所有图片提取了深层的语义特征向量并建立索引。语义检索将用户的自然语言查询同样转化为特征向量并通过计算余弦相似度从图库中找出最相关的图片。7.2 如何做得更好这只是一个起点你可以从很多方面优化它扩展图库用更丰富的提示词批量生成成千上万张图片或者导入你自己的设计素材、摄影作品库。优化检索使用更强大的CLIP模型变体如clip-vit-large-patch14。引入重排序机制先用CLIP粗筛再用更精细的模型如BLIP对Top结果进行精排。尝试将图片的生成参数如提示词、种子也作为元数据纳入检索考量。打造应用为这个系统做一个简单的Web界面用Gradio或Streamlit上传图片库、输入文字、展示结果一气呵成。开发以图搜图功能上传一张图片找到风格或内容相似的图片。实现混合搜索结合关键词、颜色、形状等多维度过滤。探索方向创意辅助设计师可以从自己的历史作品中快速找到灵感来源。内容管理自媒体工作者可以高效管理海量的配图素材。教育工具根据课文描述快速检索相关的教学图片。技术的乐趣在于将不同的工具像积木一样组合解决实际的问题。希望这个案例能给你带来启发动手试试把你的AI图库变得真正“智能”起来。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。