使用CLIP构建视频搜索引擎
哈喽!大家好,很高兴又见面了,我是golang学习网的一名作者,今天由我给大家带来一篇《使用CLIP构建视频搜索引擎》,本文主要会讲到等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! 下面就一起来看看吧!
CLIP(Contrastive Language-Image Pre-training)是一种机器学习技术,它可以准确理解和分类图像和自然语言文本,这对图像和语言处理具有深远的影响,并且已经被用作流行的扩散模型DALL-E的底层机制。在这篇文章中,我们将介绍如何调整CLIP来辅助视频搜索。
这篇文章将不深入研究CLIP模型的技术细节,而是展示CLIP的另外一个实际应用(除了扩散模型外)。
首先我们要知道:CLIP使用图像解码器和文本编码器来预测数据集中哪些图像与哪些文本是匹配的。

使用CLIP进行搜索
通过使用来自hugging face的预训练CLIP模型,我们可以构建一个简单而强大的视频搜索引擎,并且具有自然语言能力,而且不需要进行特征工程的处理。
我们需要用到以下的软件
Python≥= 3.8,ffmpeg,opencv
通过文本搜索视频的技术有很多。我们可以将搜索引擎将由两部分组成,索引和搜索。
索引
视频索引通常涉及人工和机器过程的结合。人类通过在标题、标签和描述中添加相关关键字来预处理视频,而自动化过程则是提取视觉和听觉特征,例如物体检测和音频转录。用户交互指标等等,这样可以记录视频的哪些部分是最相关的,以及它们保持相关性的时间。所有这些步骤都有助于创建视频内容的可搜索索引。
索引过程的概述如下
- 将视频分割成多个场景
- 为框架取样场景
- 帧处理后进行像素嵌入
- 索引建立存储

将视频分成多个场景
为什么场景检测很重要?视频由场景组成,而场景由相似的帧组成。如果我们只对视频中的任意场景进行采样,可能会错过整个视频中的关键帧。
所以我们就需要准确地识别和定位视频中的特定事件或动作。例如,如果我搜索“公园里的狗”,而我正在搜索的视频包含多个场景,例如一个男人骑自行车的场景和一个公园里的狗的场景,场景检测可以让我识别出与搜索查询最接近的场景。
可以使用“scene detect”python包来进行这个操作。
mport scenedetect as sd video_path = '' # path to video on machine video = sd.open_video(video_path) sm = sd.SceneManager() sm.add_detector(sd.ContentDetector(threshold=27.0)) sm.detect_scenes(video) scenes = sm.get_scene_list()
对场景的帧进行采样
然后就需要使用cv2对视频进行帧采样。
import cv2 cap = cv2.VideoCapture(video_path) every_n = 2 # number of samples per scene scenes_frame_samples = [] for scene_idx in range(len(scenes)): scene_length = abs(scenes[scene_idx][0].frame_num - scenes[scene_idx][1].frame_num) every_n = round(scene_length/no_of_samples) local_samples = [(every_n * n) + scenes[scene_idx][0].frame_num for n in range(3)] scenes_frame_samples.append(local_samples)
将帧转换为像素嵌入
在收集样本之后,我们需要将它们计算成CLIP模型可用的东西。
首先需要将每个样本转换为图像张量嵌入。
from transformers import CLIPProcessor
from PIL import Image
clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
def clip_embeddings(image):
inputs = clip_processor(images=image, return_tensors="pt", padding=True)
input_tokens = {
k: v for k, v in inputs.items()
}
return input_tokens['pixel_values']
# ...
scene_clip_embeddings = [] # to hold the scene embeddings in the next step
for scene_idx in range(len(scenes_frame_samples)):
scene_samples = scenes_frame_samples[scene_idx]
pixel_tensors = [] # holds all of the clip embeddings for each of the samples
for frame_sample in scene_samples:
cap.set(1, frame_sample)
ret, frame = cap.read()
if not ret:
print('failed to read', ret, frame_sample, scene_idx, frame)
break
pil_image = Image.fromarray(frame)
clip_pixel_values = clip_embeddings(pil_image)
pixel_tensors.append(clip_pixel_values)下一步就是平均同一场景中的所有样本,这样可以降低样本的维数,而且还可以解决单个样本中存在噪声的问题。
import torch
import uuid
def save_tensor(t):
path = f'/tmp/{uuid.uuid4()}'
torch.save(t, path)
return path
# ..
avg_tensor = torch.mean(torch.stack(pixel_tensors), dim=0)
scene_clip_embeddings.append(save_tensor(avg_tensor))这样就获得了一个CLIP嵌入的表示视频内容的的张量列表。
存储索引
对于底层索引存储,我们使用LevelDB(LevelDB是由谷歌维护的键/值库)。我们搜索引擎的架构将包括 3 个独立的索引:
- 视频场景索引:哪些场景属于特定视频
- 场景嵌入索引:保存特定的场景数据
- 视频元数据索引:保存视频的元数据。
我们将首先将视频中所有计算出的元数据以及视频的唯一标识符,插入到元数据索引中,这一步都是现成的,非常简单。
import leveldb
import uuid
def insert_video_metadata(videoID, data):
b = json.dumps(data)
level_instance = leveldb.LevelDB('./dbs/videometadata_index')
level_instance.Put(videoID.encode('utf-8'), b.encode('utf-8'))
# ...
video_id = str(uuid.uuid4())
insert_video_metadata(video_id, {
'VideoURI': video_path,
})然后在场景嵌入索引中创建一个新条目保存视频中的每个像素嵌入,还需要一个唯一的标识符来识别每个场景。
import leveldb
import uuid
def insert_scene_embeddings(sceneID, data):
level_instance = leveldb.LevelDB('./dbs/scene_embedding_index')
level_instance.Put(sceneID.encode('utf-8'), data)
# ...
for f in scene_clip_embeddings:
scene_id = str(uuid.uuid4())
with open(f, mode='rb') as file:
content = file.read()
insert_scene_embeddings(scene_id, content)最后,我们需要保存哪些场景属于哪个视频。
import leveldb
import uuid
def insert_video_scene(videoID, sceneIds):
b = ",".join(sceneIds)
level_instance = leveldb.LevelDB('./dbs/scene_index')
level_instance.Put(videoID.encode('utf-8'), b.encode('utf-8'))
# ...
scene_ids = []
for f in scene_clip_embeddings:
# .. as shown in previous step
scene_ids.append(scene_id)
scene_embedding_index.insert(scene_id, content)
scene_index.insert(video_id, scene_ids)搜索
现在我们有了一种将视频的索引,下面就可以根据模型输出对它们进行搜索和排序。
第一步需要遍历场景索引中的所有记录。然后,创建一个视频中所有视频和匹配场景id的列表。
records = []
level_instance = leveldb.LevelDB('./dbs/scene_index')
for k, v in level_instance.RangeIter():
record = (k.decode('utf-8'), str(v.decode('utf-8')).split(','))
records.append(record)下一步需要收集每个视频中存在的所有场景嵌入张量。
import leveldb
def get_tensor_by_scene_id(id):
level_instance = leveldb.LevelDB('./dbs/scene_embedding_index')
b = level_instance.Get(bytes(id,'utf-8'))
return BytesIO(b)
for r in records:
tensors = [get_tensor_by_scene_id(id) for id in r[1]]在我们有了组成视频的所有张量之后,我们可以把它传递到模型中。该模型的输入是“pixel_values”,表示视频场景的张量。
import torch
from transformers import CLIPProcessor, CLIPModel
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
inputs = processor(text=text, return_tensors="pt", padding=True)
for tensor in tensors:
image_tensor = torch.load(tensor)
inputs['pixel_values'] = image_tensor
outputs = model(**inputs)然后访问模型输出中的“logits_per_image”获得模型的输出。
Logits本质上是对网络的原始非标准化预测。由于我们只提供一个文本字符串和一个表示视频中的场景的张量,所以logit的结构将是一个单值预测。
logits_per_image = outputs.logits_per_image probs = logits_per_image.squeeze() prob_for_tensor = probs.item()
将每次迭代的概率相加,并在运算结束时将其除以张量的总数来获得视频的平均概率。
def clip_scenes_avg(tensors, text): avg_sum = 0.0 for tensor in tensors: # ... previous code snippets probs = probs.item() avg_sum += probs.item() return avg_sum / len(tensors)
最后在得到每个视频的概率并对概率进行排序后,返回请求的搜索结果数目。
import leveldb
import json
top_n = 1 # number of search results we want back
def video_metadata_by_id(id):
level_instance = leveldb.LevelDB('./dbs/videometadata_index')
b = level_instance.Get(bytes(id,'utf-8'))
return json.loads(b.decode('utf-8'))
results = []
for r in records:
# .. collect scene tensors
# r[0]: video id
return (clip_scenes_avg, r[0])
sorted = list(results)
sorted.sort(key=lambda x: x[0], reverse=True)
results = []
for s in sorted[:top_n]:
data = video_metadata_by_id(s[1])
results.append({
'video_id': s[1],
'score': s[0],
'video_uri': data['VideoURI']
})就是这样!现在就可以输入一些视频并测试搜索结果。
总结
通过CLIP可以轻松地创建一个频搜索引擎。使用预训练的CLIP模型和谷歌的LevelDB,我们可以对视频进行索引和处理,并使用自然语言输入进行搜索。通过这个搜索引擎使用户可以轻松地找到相关的视频,最主要的是我们并不需要大量的预处理或特征工程。
那么我们还能有什么改进呢?
- 使用场景的时间戳来确定最佳场景。
- 修改预测让他在计算集群上运行。
- 使用向量搜索引擎,例如Milvus 替代LevelDB
- 在索引的基础上建立推荐系统
- 等等
可以在这里找到本文的代码:https://github.com/GuyARoss/CLIP-video-search/tree/article-01。
以及这个修改版本:https://github.com/GuyARoss/CLIP-video-search。
本篇关于《使用CLIP构建视频搜索引擎》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于科技周边的相关知识,请关注golang学习网公众号!
英特尔为量子计算开发者发布软件平台,帮助构建量子算法
- 上一篇
- 英特尔为量子计算开发者发布软件平台,帮助构建量子算法
- 下一篇
- 下任推特CEO是他?为马斯克工作20年,带全家睡办公室!
-
- 科技周边 · 人工智能 | 56分钟前 | 豆包AI
- 豆包AI多语言翻译设置技巧
- 117浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 夸克AI
- 夸克AI搜索怎么开启?详细设置方法
- 282浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- Forecaster.biz:AI交易与趋势预测工具
- 122浏览 收藏
-
- 科技周边 · 人工智能 | 2小时前 |
- 2025女子板球世界杯AI预测分析
- 147浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 |
- 用ChatGPT写代码的高效技巧分享
- 384浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 | DeepSeek
- Deepseek平台入口及登录方法2026
- 158浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 |
- 即梦训练数据来源全解析
- 158浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 |
- Kling生成高清视频方法解析
- 368浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 | 老照片修复Ai软件
- 老照片修复AI解析与使用教程
- 207浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 |
- 文心一言注册教程:手机快速登录指南
- 432浏览 收藏
-
- 科技周边 · 人工智能 | 4小时前 |
- Gemini2.5图像分割技术详解与应用
- 288浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3345次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3557次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3589次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4714次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3962次使用
-
- GPT-4王者加冕!读图做题性能炸天,凭自己就能考上斯坦福
- 2023-04-25 501浏览
-
- 单块V100训练模型提速72倍!尤洋团队新成果获AAAI 2023杰出论文奖
- 2023-04-24 501浏览
-
- ChatGPT 真的会接管世界吗?
- 2023-04-13 501浏览
-
- VR的终极形态是「假眼」?Neuralink前联合创始人掏出新产品:科学之眼!
- 2023-04-30 501浏览
-
- 实现实时制造可视性优势有哪些?
- 2023-04-15 501浏览

