AIGC|一文揭秘如何利用MYSCALE实现高效图像搜索?

news2024/11/17 16:53:19

图像搜索已成为一种流行且功能强大的能力,使用户能够通过匹配功能或视觉内容来查找相似的图像。随着计算机视觉和深度学习的快速发展,这种能力得到了极大的增强。

本文主要介绍如何基于矢量数据库MYSCALE来实现图像搜索功能。

一、MySCALE简介

MyScale 是一个基于云的数据库,针对 AI 应用程序和解决方案进行了优化,构建在开源 ClickHouse 之上。它有效地管理大量数据,以开发强大的人工智能应用程序。

  • 专为 AI 应用程序构建:在单个平台中管理和支持用于 AI 应用程序的结构化和矢量化数据的分析处理。
  • 专为性能而构建:先进的 OLAP 数据库架构,以令人难以置信的性能对矢量化数据执行操作。
  • 专为通用可访问性而构建:SQL 是 MyScale 所需的唯一编程语言。这使得MyScale与定制API相比更有利,并且适合大型编程社区。

二、实践演示

(一)下载依赖

经过实践python3.7版本可支持后续演示

pip installdatasets clickhouse-connect
pip installrequests transformers torch tqdm

(二)构建数据集

这一步主要是将数据转化为向量数据,最终格式为xxx.parquet文件,构建数据集转化数据这一步骤比较耗时且吃机器配置,可以跳过这一步,后续直接下载现成的转化完成的数据集

//下载和处理数据

下载、解压我们需要转化的数据

wget https://unsplash-datasets.s3.amazonaws.com/lite/latest/unsplash-research-dataset-lite-latest.zip
unzip unsplash-research-dataset-lite-latest.zip -d tmp

读取下载数据并转化为Pandas dataframes

importnumpy asnp
importpandas aspd
importglob

documents = ['photos', 'conversions']
datasets = {}

fordoc indocuments:
files = glob.glob("tmp/"+ doc + ".tsv*")
subsets = []
forfilename infiles:
df = pd.read_csv(filename, sep='\t', header=0)
subsets.append(df)
datasets[doc] = pd.concat(subsets, axis=0, ignore_index=True)

df_photos = datasets['photos']
df_conversions = datasets['conversions']

定义函数extract_image_features,然后从数据框中选择1000个照片ID,下载对应的图像,调用函数来帮助我们从图像中提取他们的图像嵌入

importtorch
fromtransformers importCLIPProcessor, CLIPModel

model = CLIPModel.from_pretrained('openai/clip-vit-base-patch32')
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

defextract_image_features(image):
inputs = processor(images=image, return_tensors="pt")
withtorch.no_grad():
outputs = model.get_image_features(**inputs)
outputs = outputs / outputs.norm(dim=-1, keepdim=True)
returnoutputs.squeeze(0).tolist()

fromPIL importImage
importrequests
fromtqdm.auto importtqdm

# select the first 1000 photo IDs
photo_ids = df_photos['photo_id'][:1000].tolist()

# create a new data frame with only the selected photo IDs
df_photos = df_photos[df_photos['photo_id'].isin(photo_ids)].reset_index(drop=True)

# keep only the columns 'photo_id' and 'photo_image_url' in the data frame
df_photos = df_photos[['photo_id', 'photo_image_url']]

# add a new column 'photo_embed' to the data frame
df_photos['photo_embed'] = None

# download the images and extract their embeddings using the 'extract_image_features' function
fori, row intqdm(df_photos.iterrows(), total=len(df_photos)):
# construct a URL to download an image with a smaller size by modifying the image URL
url = row['photo_image_url'] + "?q=75&fm=jpg&w=200&fit=max"

try:
res = requests.get(url, stream=True).raw
image = Image.open(res)
except:
# remove photo if image download fails
photo_ids.remove(row['photo_id'])
continue

# extract feature embedding
df_photos.at[i, 'photo_embed'] = extract_image_features(image)

//创建数据集

声明两个数据框,一个带有嵌入的照片信息,另一个用于转换信息。

df_photos = df_photos[df_photos['photo_id'].isin(photo_ids)].reset_index().rename(columns={'index': 'id'})

df_conversions = df_conversions[df_conversions['photo_id'].isin(photo_ids)].reset_index(drop=True)
df_conversions = df_conversions[['photo_id', 'keyword']].reset_index().rename(columns={'index': 'id'})

最后将数据帧转化为parquet文件

importpyarrow aspa
importpyarrow.parquet aspq
importnumpy asnp

# create a Table object from the data and schema
photos_table = pa.Table.from_pandas(df_photos)
conversion_table = pa.Table.from_pandas(df_conversions)

# write the table to a Parquet file
pq.write_table(photos_table, 'photos.parquet')
pq.write_table(conversion_table, 'conversions.parquet')

(三)将数据填充到MYSCALE数据库

前面讲到我们可以跳过构建数据集这一步骤,下载已经处理完成的数据集 "https://datasets-server.huggingface.co/splits?dataset=myscale%2Funsplash-examples"

//创建表

在 MyScale 中创建两个表,一个用于照片信息,另一个用于转换信息。

importclickhouse_connect

# initialize client
client = clickhouse_connect.get_client(host='YOUR_CLUSTER_HOST', port=8443, username='YOUR_USERNAME', password='YOUR_CLUSTER_PASSWORD')

# drop table if existed
client.command("DROP TABLE IF EXISTS default.myscale_photos")
client.command("DROP TABLE IF EXISTS default.myscale_conversions")

# create table for photos
client.command("""
CREATE TABLE default.myscale_photos
(
id UInt64,
photo_id String,
photo_image_url String,
photo_embed Array(Float32),
CONSTRAINT vector_len CHECK length(photo_embed) = 512
)
ORDER BY id
""")

# create table for conversions
client.command("""
CREATE TABLE default.myscale_conversions
(
id UInt64,
photo_id String,
keyword String
)
ORDER BY id
""")

上传数据

fromdatasets importload_dataset

photos = load_dataset("myscale/unsplash-examples", data_files="photos-all.parquet", split="train")
conversions = load_dataset("myscale/unsplash-examples", data_files="conversions-all.parquet", split="train")

# transform datasets to panda Dataframe
photo_df = photos.to_pandas()
conversion_df = conversions.to_pandas()

# convert photo_embed from np array to list
photo_df['photo_embed'] = photo_df['photo_embed'].apply(lambdax: x.tolist())


# initialize client
client = clickhouse_connect.get_client(host='YOUR_CLUSTER_HOST', port=8443, username='YOUR_USERNAME', password='YOUR_CLUSTER_PASSWORD')


# upload data from datasets
client.insert("default.myscale_photos", photo_df.to_records(index=False).tolist(),
column_names=photo_df.columns.tolist())
client.insert("default.myscale_conversions", conversion_df.to_records(index=False).tolist(),
column_names=conversion_df.columns.tolist())

# check count of inserted data
print(f"photos count: {client.command('SELECT count(*) FROM default.myscale_photos')}")
print(f"conversions count: {client.command('SELECT count(*) FROM default.myscale_conversions')}")

# create vector index with cosine
client.command("""
ALTER TABLE default.myscale_photos 
ADD VECTOR INDEX photo_embed_index photo_embed
TYPE MSTG
('metric_type=Cosine')
""")

# check the status of the vector index, make sure vector index is ready with 'Built' status
get_index_status="SELECT status FROM system.vector_indices WHERE name='photo_embed_index'"
print(f"index build status: {client.command(get_index_status)}")

基于本地指定的图片查找前K个相似的图像(当前k=10)

fromdatasets importload_dataset
importclickhouse_connect
importrequests
importmatplotlib.pyplot asplt
fromPIL importImage
fromio importBytesIO
importtorch
fromtransformers importCLIPProcessor, CLIPModel

model = CLIPModel.from_pretrained(r'C:\Users\16439\Desktop\clip-vit-base-patch32')
processor = CLIPProcessor.from_pretrained(r"C:\Users\16439\Desktop\clip-vit-base-patch32")

client = clickhouse_connect.get_client(
host='msc-cab0c439.us-east-1.aws.myscale.com',
port=8443,
username='chenzmn',
password='#隐藏'
)




defshow_search(image_embed):
# download image with its url
defdownload(url):
response = requests.get(url)
returnImage.open(BytesIO(response.content))

# define a method to display an online image with a URL
defshow_image(url, title=None):
img = download(url)
fig = plt.figure(figsize=(4, 4))
plt.imshow(img)
plt.show()



# query the database to find the top K similar images to the given image
top_k = 10
results = client.query(f"""
SELECT photo_id, photo_image_url, distance(photo_embed, {image_embed}) as dist
FROM default.myscale_photos
ORDER BY dist
LIMIT {top_k}
""")
# WHERE photo_id != '{target_image_id}'

# download the images and add them to a list
images_url = []
forr inresults.named_results():
# construct a URL to download an image with a smaller size by modifying the image URL
url = r['photo_image_url'] + "?q=75&fm=jpg&w=200&fit=max"
images_url.append(download(url))

# display candidate images
print("Loading candidate images...")
forrow inrange(int(top_k / 5)):
fig, axs = plt.subplots(1, 5, figsize=(20, 4))
fori, img inenumerate(images_url[row * 5:row * 5+ 5]):
axs[i % 5].imshow(img)
plt.show()


defextract_image_features(image):
inputs = processor(images=image, return_tensors="pt")
withtorch.no_grad():
outputs = model.get_image_features(**inputs)
outputs = outputs / outputs.norm(dim=-1, keepdim=True)
returnoutputs.squeeze(0).tolist()


if__name__ == '__main__':

image = Image.open(r'C:\Users\16439\Desktop\OIP-C.jpg')
target_image_embed = extract_image_features(image)
show_search(target_image_embed)

我本地的一张图片:

找到的10张最相似的图片:

这就是全部的演示效果了,感兴趣的朋友也可以自己尝试一下。

作者:陈卓敏 | 后端开发工程师

版权声明:本文由神州数码云基地团队整理撰写,若转载请注明出处。

公众号搜索神州数码云基地,了解更多AI相关技术干货。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1113257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

win10下yolov6 tensorrt模型部署

TensorRT系列之 Win10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速部署…

uniapp\ taro 如何使用 UnoCSS 原子化css

unocss-preset-weapp 相较于 tailwindcss 和 windicss, unocss的性能和可扩展性都优于它们 UnoCSS小程序预设 unocss-preset-weapp 内置 transformer 用于兼容小程序 transformerClass 转换转义类名,解决小程序不支持\\,\:,\[,…

瞬态抑制二极管TVS的工作原理?|深圳比创达电子EMC(下)

TVS二极管与Zener二极管同样作为过压保护, TVS着重浪涌电压的钳位保护,具有抗大电流冲击的能力;Zener管着重于稳压效果,具有浪涌电流小,保护电压稳的特点,两者在原理与保护特性有所区别,同时在个别应用领域…

回收站删除的文件怎么恢复?快来学习这3个方法!

“有时候我会先将一些不重要的文件放入回收站中,等需要用到时再将它还原。但是我刚刚不小心把回收站清空了,还有方法可以帮我找回我的数据吗?” 在使用电脑时,如果我们删除文件,这些文件会被先收入回收站中。如果我们是…

MODBUS-TCP转MODBUS-RTU通信应用(S7-1200和串口服务器通信)

在学习本博客之前,大家需要熟悉MODBUS-TCP和MODBUS-RTU通信,这2个通信的编程应用,大家可以查看下面文章链接: MODBUS-RTU通信 MODBUS-RTU通信协议功能码+数据帧解读(博途PLC梯形图代码)-CSDN博客MODBUS通信详细代码编写,请查看下面相关链接,这篇博客主要和大家介绍MODB…

商用工程运输车辆智能交通精细数字化管理中的大数据应用

在物联网蓬勃发展的今天,智能交通、智能工业控制、远程控制汽车基本不是什么难题,在集团、企业、都会涉及用车及安全管理,就拿车队管理系统来说,它的主要作用是进行车辆定位、机械诊断、驾驶员行为监测等,并能及时发现…

ubuntu18.04 RTX3060 rangnet++训练 bonnetal语义分割

代码链接: https://github.com/PRBonn/lidar-bonnetal 安装anaconda环境为 CUDA 11.0(11.1也可以) anaconda环境如下 numpy1.17.2 torchvision0.2.2 matplotlib2.2.3 tensorflow1.13.1 scipy0.19.1 pytorch1.7.1 vispy0.5.3 opencv_python…

工业高频读写器和超高频读写器怎么选?

在工业领域中,RFID技术是常用的信息采集和传输的方式之一,RFID根据频段还可以分为低频、高频和超高频等,在选择具体的频段应用时,很多企业却毫无头绪。接下来本文就高频RFID和超高频RFID读写器的特点进行分析,帮助企业…

Python综合练习题

题目 创建一个系统,里面可以添加学生、添加班级、查看班级里的学生,在控制台输出 效果图 关键代码 完整代码 # -*- coding: UTF-8 -*-#功能 Functionality0 #学生 Student [刘榕榕0, 秦英姿1, 王家乐0, 孟德赫3, 门子伟4, 明展宇5] #班级 Class [大…

景联文数据标注平台助力标注效率翻倍,年处理图像数据过亿

图像标注是指为图像添加文字描述或标签,包括物体、场景、情感、活动等多种内容,以帮助计算机更好地理解和处理图像信息的过程,提高图像处理的自动化程度和准确性,常用于计算机视觉、图像识别等领域。 选择图像标注工具时&#xff…

思必驰:离线语音识别芯片简介

一.使用场景 夏天某个凉爽的早晨,当你躺在床上玩着手机,突然一阵困意袭来,原来已经中午了,此时你一个侧身准备休息,突然发现一阵酷热袭来,你定睛一看,原来是风扇没有打开&#xff0c…

工业以太网RFID设备有哪些部分组成?

随着近年来物联网不断发展,RFID技术已经逐渐成为物联网中的关键技术,利用RFID技术可以实现实时数据采集、物流自动化、远程设备管理等功能,大大提高了物联网提取数据和物体识别能力的智能化水平。 工业RFID读写器作为数据采集最关键的一个设备…

使用Pytorch Geometric 进行链接预测代码示例

PyTorch Geometric (PyG)是构建图神经网络模型和实验各种图卷积的主要工具。在本文中我们将通过链接预测来对其进行介绍。 链接预测答了一个问题:哪两个节点应该相互链接?我们将通过执行“转换分割”,为建模准备数据。为批处理准备专用的图数据加载器。在Torch Ge…

书客护眼台灯好用吗?书客、柏曼、飞利浦多维度测评

护眼台灯作为一种辅助照明设备,旨在提供舒适的光线环境,以减轻眼睛疲劳和保护视力健康。它通常采用柔和的光线、调节亮度和色温的功能,以及一些附加的设计特点,如可调节灯颈、遮光罩等。虽然护眼台灯并不能完全解决眼部问题&#…

YOLOv8改进实战 | 更换主干网络Backbone(一)之轻量化模型Ghostnet

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…

应用在冷链运输中的数字温度传感芯片

冷链运输(Cold-chain transportation)是指在运输全过程中,无论是装卸搬运、变更运输方式、更换包装设备等环节,都使所运输货物始终保持一定温度的运输。冷链运输要求在中、长途运输及短途配送等运输环节的低温状态。它主要涉及铁路…

论文笔记:Multi-Concept Customization of Text-to-Image Diffusion

0 概述 论文:Multi-Concept Customization of Text-to-Image Diffusion 源代码和数据:https://www.cs.cmu.edu/~custom-diffusion/ 当生成模型生成从大规模数据库中学习的概念的高质量图像时,用户通常希望合成他们自己的概念的实例(例如&…

Python技能树练习——python字符串转列表

一、题目与解 把下列字符串转为列表格式输出 top_ide_trend """ Rank Change IDE Share Trend 1 Visual Studio 29.24 % 3.5 % 2 Eclipse 13.91 % -2.9 % 3 Visual Studio Code 12.07 % 3.3 % 4 Android Studio 9.13 % -2.5 % 5 pyCharm 8.43 % 0.7 % 6 …

【设计模式】设计模式概述

😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!&#x1f4…

中文编程工具开发软件实际案例:酒店饭店餐饮点餐管理系统软件编程实例

中文编程工具开发软件实际案例:酒店饭店餐饮点餐管理系统软件编程实例图片如下 软件的安装方法: 软件绿色免安装,压缩包文件解压后,将文件夹复制到电脑的D或E盘里,将软件目录下的红色程序图标按右键发送到桌面快捷方式…