基于语义搜索假装图像生成
经过一个月的休息,我回来了。我一直在刚果完成一个石油天然气项目。在这段休息时间里,我有了一些想法,现在我有时间把它们写下来分享给大家。
在这篇文章中,我将继续之前开始的内容。
我将向你展示如何调整一个已发布的现有项目。
它叫做Fake Image Generation(伪造图像生成)
这个名字可能会产生误导:我们并不是在创建伪造的图像……我们是在模拟图像生成过程,而不是真正地进行生成!
我是一个PoorGPUguy,所以图像生成是可行的,但生成一张1024x640像素的图片大约需要30分钟。
但是,如果我们能使用一个足够大的图像数据集,然后在我们期望的提示词和现有提示词(来自图像数据集)之间使用余弦相似度搜索呢?
我们将获得许多与我们需求足够接近的结果!同时,我们还可以从新的提示词(它们的风格、颜色、构图、相机角度)中获得一些灵感。
如果你感兴趣……让我们继续吧!
1、前提条件
阅读我之前的文章(这里没有付费墙):
Fake Image Generator Model — part 1 — 如何使用数据集来模拟图像生成并获得灵感。
Fake image generator model — part 2 — 图书管理员和表演者:AI搜索如何假装魔术。从相似度搜索到图像检索。
阅读并测试之后……回到这里。
我将向你展示如何使用不同的图像数据集(来自HuggingFace)并做同样的事情。
下周我们将介绍合并初始的kaupane/nano-banana-pro-gen和今天博文中的新数据集open-image-preferences-v1-binarized的过程。
这是我的硬件配置……不是很好对吧?
注意:我在一台旧的Lenovo X260上测试所有项目,Intel Core i5,16GB内存。如果我能做到,你也能做到!
1、准备工具
如果你已经跟进了Medium上的文章……你几乎已经拥有了所需的一切。如果你直接跳到这里,让我们回顾一下。
1.1 Python虚拟环境
创建一个新的项目目录(我的叫FIG2)。在终端中打开它并创建一个新的虚拟环境
python -m venv venv然后激活它:
# in powershell .\venv\Scripts\activate # in CMD venv\Scripts\activate.bat现在我们需要安装一些Python包:我已经移除了对重型包(如torch)的需求,因为我们将使用numpy来计算余弦相似度,而不是sentence-transformers库。
pip install datasets requests tqdm huggingface_hub ipython pandas pyarrow gradio numpy faiss-cpu注意这次我添加了ipython:我们将使用这个有用的交互式Python shell在步骤1中探索数据集。
接下来是llama.cpp二进制文件:我们使用llama-server来托管我们将通过requests库调用的嵌入端点。嵌入模型是一样的:BAAI/bge-m3,它是完美的、轻量级的,而且支持多语言。
在同一个主目录中下载llama.cpp的ZIP存档,然后在那里解压。
下载llama.cpp二进制文件
在同一个目录中下载嵌入模型的GGUF(量化权重)文件。下载bge-m3-q8_0.gguf
一切就绪。
额外建议:还可以下载一个模型来帮助你调整现有项目,使其适应新的数据集。我建议下载Qwen_Qwen3.5–2B-Q5_K_L.gguf。这是最新的Qwen 3.5模型,20亿参数,在CPU上运行速度快,同时几乎保持与原始模型相同的精度。
Qwen_Qwen3.5–2B-Q5_K_L.gguf
这个模型是Qwen的推理/非推理模型,以小格式打包了惊人的能力!
稍后我将向你展示如何将其用作编程助手。
图片来自HF仓库## 3、探索数据集
这是必不可少的部分。
并非所有数据集都是一样的。不同仓库之间的表头和记录可能会有很大差异。
你可以在Hugging Face上通过模态 = image来筛选数据集进行探索:
链接在这里浏览了一页又一页之后,我找到了open-image-preferences-v1-binarized。
- Goal: This project aims to create 10K text-to-image preference pairs. These pairs can be used to evaluate the performance of image generation models across a wide variety of common image categories, based on prompt with varying levels of difficulty. - How: We use the prompts from fal/imgsys-results, these prompts are evolved based on complexity and quality for various image categories. We then asked the community to annotate the preference between two generated images for each prompt. - Result: We achieved to annotate 10K preference pairs.尽管数据集的目标与我们的目标不一致……我们仍然获得了数千张生成的图像(来自不同的模型)及其初始提示词。
而这正是我们需要的!
要查看仓库的结构,你可以:
- 在Hugging Face上探索数据集
- 下载一个小样本到本地以了解如何使用
我们将选择方案2,使用ipython。
在终端中,激活venv后,运行:
ipythonIpython是一个令人惊叹的交互式shell。你可以按单元格运行代码(如果你听说过Google Colab Notebooks或Jupyter Notebook……它们都来自ipython)。好处是每个单元格可以多次运行或修改。如果你打错了什么,不必从头运行整个Python程序。跟着我来:
你可以在这里免费获取iPython速查表
回到探索:我们将使用文章第一部分中相同的代码:
from datasets import load_dataset import pandas as pd from PIL import Image import io # Load just a small sample def explore_sample_streaming(dataset_name, split_name="train", num_samples=100): """Stream a small sample of the dataset""" print(f"Loading {num_samples} samples from {dataset_name}...") # Use streaming to avoid downloading everything dataset = load_dataset(dataset_name, split=split_name, streaming=True) # Take a small sample sample_data = [] for i, example in enumerate(dataset.take(num_samples)): sample_data.append(example) if i % 10 == 0: print(f"Loaded {i+1} samples...") # Convert to DataFrame for exploration df = pd.DataFrame(sample_data) print(f"\nDataset Schema:") print(f"Columns: {list(df.columns)}") print(f"Sample size: {len(df)}") print("\nFirst few rows:") print(df.head()) return df # Use it repo = input("Paste the repo name: ") #e.g. cerealt/open-image-preferences-v1-binarized samples = input("Num of samples: ") num_sample = int(samples) #ex 50 sample_df = explore_sample_streaming(repo, num_samples=num_sample)将此代码粘贴到ipython中,当被要求输入仓库名称时,使用新的:cerealt/open-image-preferences-v1-binarized
在这个例子中我只放了10个样本:结果需要理解……
我们可以看到一个叫做prompt的字段,这很好。但是图像呢?
在在线仓库中,它们在chosen和rejected字段中。
让我们探索这些字段,了解它们是什么数据类型(字符串、URL还是PIL图像对象):
first_sample = sample_df.iloc[1] first_sample看起来chosen/rejected是字节对象(文件)。让我们看看是否可以用Pillow加载它们。
image_data = first_sample['chosen']['bytes'] image = Image.open(io.BytesIO(image_data)) image.show()你应该会看到爱丽丝梦游仙境的图像 😂
注意:顺便说一句,被拒绝的图像也可以显示
image_data1 = first_sample['chosen']['bytes'] image_data2 = first_sample['rejected']['bytes'] image1 = Image.open(io.BytesIO(image_data1)) image2 = Image.open(io.BytesIO(image_data2)) image1.show() image2.show()现在我们知道:
- 提示词在
prompt字段中 - 图像在
chosen字段中,它是一个可以用Pillow加载的字节对象
我们现在可以继续从仓库下载.parquet文件了。
文件在Files and versions标签下的data子文件夹中## 4、下载图像和提示词
在这里,我们要构建我们的json数据库,包含新图像,准备好在本地计算机上使用。
在我这个项目的原始仓库中,我有一个脚本来完成这个任务。但那个Python应用程序是为初始的kaupane/nano-banana-pro-gen数据集量身定制的。
你可以在我的GitHub仓库中找到原始文件
https://github.com/fabiomatricardi/Fake-Image-Generator如何修复它?
让我们看看原始文件1.big_dset_parquet_Ask.py,找出需要修改的地方。
到第164行,我们有了下载数据集的辅助函数。我们需要在主脚本中找到,我们读取统一parquet文件并提取提示词和图像的位置。
在第271行,我们从统一的parquet文件加载数据集:我们要找的就是那之后的部分!
在第320行,我们找到了关键位置:
我们之前已经测试了如何访问图像:它不在一个叫做’image’的字段中。我们还知道这是一个字节对象,而不是PIL实例(就像原始数据集中那样)。
让我们结合我们的知识来修复这个问题:
try: # Save image for new dataset cerealt/open-image-preferences-v1-binarized ######################################################################## if 'chosen' in example and example['chosen']['bytes'] is not None: image_data1 = example['chosen']['bytes'] image1 = Image.open(io.BytesIO(image_data1)) image1.save(full_path) # Get prompt prompt = example.get('prompt', '') if not prompt and 'json' in example and isinstance(example['json'], dict): prompt = example['json'].get('prompt') or example['json'].get('caption') or str(example['json'])我们验证chosen字段存在且bytes对象不为空:然后我们使用与之前完全相同的代码来读取字节流并保存它。
注意:在我们的原始文件中,io库没有被导入。记得在顶部添加导入
5、更改编号策略
如果我们按原样运行代码,即使做了这些小修改,我们也会遇到另一个问题:新图像将从0开始编号。
但我们已经有了这些数字(至少在nano-banana数据集中有):如果将来我们想把图像合并到一个文件夹中怎么办?
许多图像将被覆盖。
我们需要添加一个增量,一个不同的起始点,这样不同的json索引在合并时不会冲突。
我是这样做的:
我们可以创建一个从2000开始的起始点(我们的原始数据集大约有1k张图像,所以我们可以避免重叠)。
mydelta = 2000然后我们将mydelta数字添加到所有相关项目:
- 图像
filename* 最终JSON文件中的ID - 最终JSON文件中的
index
有了这些小技巧,我们可以在将来(下周)合并不同的
.json索引时使用新的数据集。
我们将借助AI助手的帮助来完成(我真的不知道如何自己做)
如果你迷路了或代码在某处出错,我把新文件命名为11.new_dataset.py,你可以从我的GitHub仓库下载
- 下载11.new_dataset.py
让我们运行新的Python应用程序,指向新仓库cerealt/open-image-preferences-v1-binarized
在终端中,激活venv后,运行
python .\11.new_dataset.py这是我的运行结果
6、测试生成模拟
下一步是验证生成模拟。按照文章第一部分,我们将使用一个随机函数(使用我们新的范围……)。
我把新的Python Gradio应用命名为12.FAKE_Image_Generator.py:你需要调整的原始文件是2.FAKE_Image_Generator.py
我们的图像(如果你按照视频中的相同设置)从2800开始,到3699结束。
让我们调整代码:从原始文件来看,修改非常直观
在第21行,我们需要将randint函数的起始/终止改为类似这样:
# Open the image file random_int = random.randint(2800, 3699) # Random int between 2800 and 3699保存文件,然后在终端中激活venv后运行:
gradio .\12.FAKE_Image_Generator.py7、结束语
希望到目前为止你喜欢这些内容。
调整现有的应用很酷,因为你需要理解代码以及在哪里修改它。
有时候AI生成代码的最大问题……是你根本不知道那里发生了什么。如果你不得不亲自动手修复它,那就变成了一项不可能完成的任务。
下次我们将调整最终应用并为新数据集生成FAISS数据库。
接下来,如何合并现有图像和json索引以增加我们伪造生成的样本量。
原文链接:基于语义搜索假装图像生成 - 汇智网
