paint-brush
构建高级视频搜索:帧搜索与多模态嵌入by@datastax
278

构建高级视频搜索:帧搜索与多模态嵌入

DataStax10m2024/07/10
Read on Terminal Reader

深入研究多模态嵌入和帧搜索两种先进的视频搜索技术
featured image - 构建高级视频搜索:帧搜索与多模态嵌入
DataStax HackerNoon profile picture

想象一下,一位数据科学家正在研究野生动物的行为,分析来自偏远森林中摄像机拍摄的数百小时的视频片段。或者一位体育教练需要找出整个赛季比赛中的关键比赛来制定新策略。或者,想象一下一位电影制片人在庞大的视频库中搜索特定场景以拼凑一部纪录片。


传统上,所有这些专家都面临着手动整理数小时的录像的耗时、容易出错且巨大的挑战。


然而,人工智能和机器学习的进步极大地改变了视频搜索应用。这些技术现在使我们能够以令人难以置信的复杂性在大量视频数据集中搜索特定对象和事件。数据科学家和研究人员可以以极高的精度和效率精确定位相关的视频片段。


开放起源开发工具来识别媒体内容的来源,并让用户确定其真实性。为了扩大其产品范围,这家总部位于英国的公司着手开发一个平台,让档案管理员能够快速高效地在数字媒体档案中找到相关视频。


目标是通过提供高级搜索功能来简化研究过程,使用户能够从极大的视频数据集中轻松找到具有特定内容或属性的镜头。


通过使用复杂的搜索算法和用户友好的界面,OpenOrigins 旨在使该平台成为该社区的重要工具。


OpenOrigins 考虑了两种技术方法来构建此视频搜索服务:使用图像嵌入的帧搜索和多模态嵌入。让我们来看看每个选项。

视频内容语义搜索

启用视频语义搜索来回答诸如“有多少分钟的视频内容展示了鹿在其自然栖息地的情况?”之类的复杂问题需要复杂的搜索功能,这些功能可以理解和解释视频内容,而不仅仅是基本的关键字元数据匹配。实现这一目标的关键是什么?多模态嵌入。

多模态嵌入模型和多模态大型语言模型 (LLM) 可能被视为类似的解决方案。CLIP 和 Google 多模态嵌入等模型可为文本、图像和视频等数据类型生成嵌入,从而创建可捕获语义含义的高维向量。这可实现语义搜索、内容检索和相似性检测等应用。


另一方面,GPT-4(具有多模态功能)、Flamingo 和 Gemini 等多模态 LLM 旨在理解和生成不同类型数据的内容。


这些模型通过使用多模式输入(例如文本和图像)并生成多模式输出,在对话式 AI 和内容生成等复杂任务中表现良好,从而产生有意义且上下文丰富的响应。


嵌入模型注重高效搜索和检索,而多模态 LLM 适合生成和理解多样化内容,使其成为聊天机器人、交互式助手和多模态交互的理想选择。


多模式嵌入模型

多模态大型语言模型 (LLM)

主要目的

支持跨文本和图像等不同数据模式进行搜索和检索

生成并理解多种模式的内容

核心用例

语义搜索、内容检索和相似性

对话式人工智能、内容生成和对话系统

示例模型

CLIP,谷歌多模态嵌入模型

GPT-4(具有多模式功能)、Llava、Gemini、Flamingo、LaMDA

搜索和检索

针对快速、准确的搜索和相似性进行了优化

针对不同数据类型的全面理解和生成进行了优化。

应用

内容审核、推荐系统、语义搜索

对话代理、内容创建、多模式交互

方法 1:使用图像嵌入进行帧搜索

OpenOrigins 研究的第一种方法是使用图像嵌入对视频进行逐帧分析。这种方法将视频分解为单独的帧,每个帧通过使用以下方法转换为矢量嵌入:夹子嵌入模型。



图 1:方法图摘要(改编自“从自然语言监督中学习可转移的视觉模型”)。虽然标准图像模型联合训练图像特征提取器和线性分类器来预测某些标签,但 CLIP 联合训练图像编码器和文本编码器来预测一批(图像、文本)训练示例的正确配对。在测试时,学习到的文本编码器通过嵌入目标数据集类别的名称或描述来合成零样本线性分类器。


CLIP,由 OpenAI 开发是一种通过自然语言学习理解图像的人工智能模型,与依赖于特定标记图像的传统模型不同。


通过研究数百万张带有说明的网络图像,CLIP 能够以类似于人类感知和描述世界的方式理解视觉概念。它的训练涉及“对比学习”,即学会将图像与正确的描述相匹配,通过理解我们所看到的内容和我们使用的词语之间的联系,它拥有处理各种任务的独特能力。


这使得 CLIP 具有很强的适应性,对于需要深入理解图像和语言的应用程序非常有用。


这些嵌入存储在矢量数据库中,通过基于语义相似性将文本与文本、文本与图像或图像与图像进行匹配,实现快速准确的搜索。


帧提取将视频分解为指定间隔的帧。每帧通过图像嵌入模型处理以生成高维向量表示。这些向量存储在 DataStax Astra DB 等向量存储中,从而实现高效的相似性搜索。


该方法在多模态语义搜索中具有较高的准确率,非常适合搜索特定对象或场景。但是,该方法计算量大,尤其是对于长视频,并且可能会遗漏时间上下文或帧间变化。

方法 2:使用 Google 多模态嵌入节点进行多模态嵌入

第二种方法利用最新的生成式人工智能技术与多模态嵌入,具体来说是使用谷歌的多模态嵌入模型。这种创新方法使用户能够使用图像、文本或视频搜索视频,将所有输入转换为公共嵌入空间。该模型为各种输入类型生成嵌入并将其映射到共享向量空间。用户可以使用转换为相同维度嵌入的不同模态进行搜索。

Google MultiModal 嵌入模型:1048* 维度

用于视频的 Google Cloud Vertex AI 多模式嵌入

Google Cloud 的 Vertex AI提供强大的多模态嵌入,包括将视频内容转换为高维向量的复杂视频嵌入。这些 1408 维嵌入支持多种应用,例如内容审核、语义搜索和视频分类。


通过以数字方式表示视频,这些嵌入可以实现高级机器学习任务,使搜索、分析和分类视频内容变得更加容易。


将这些嵌入与数据Stax Astra 数据库确保高效处理大型数据集,并为有效检索提供强大的后端支持。此方法通过支持多种搜索查询输入类型并应用高级 AI 功能来提高搜索相关性和准确性。此方法可高效管理具有时间上下文的大型数据集,使其成为复杂搜索场景的绝佳选择。


Google 的多模态嵌入和 CLIP 方法均将多模态数据嵌入到公共嵌入空间中。主要区别在于 Google 的多模态嵌入支持视频,而 CLIP 不支持。

技术概述

我们汇集了以下存储库,以阐明和应用帧搜索视频分析和多模态嵌入的示例。这些示例提供了实际演示和详细说明,以帮助有效地实施和评估每种方法。

方法 1:使用图像嵌入进行框架搜索

在这种方法中,我们引入了一个Colab 笔记本旨在演示使用图像嵌入进行帧搜索视频分析。该笔记本提供了将视频内容分解为单个帧并使用 CLIP 嵌入模型分析每个帧的分步指南。这种方法允许在视频数据中对特定对象或场景进行高精度搜索。


get_single_frame_from_scene函数计算帧 ID,并将视频捕获设置为该帧并读取它:


 def get_single_frame_from_scene(scene, video_capture): frame_id = (scene[1] - scene[0]).frame_num // 2 + scene[0].frame_num video_capture.set(cv2.CAP_PROP_POS_FRAMES, frame_id) _, frame = video_capture.read() return Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))


get_frames_from_video函数处理视频,使用 AdaptiveDetector 检测场景,并通过调用 get_single_frame_from_scene 从每个场景中提取单帧,并将这些帧存储在列表中:


 def get_frames_from_video(video_path): res = [] video_capture = cv2.VideoCapture(video_path) content_list = detect(video_path, AdaptiveDetector()) for scene in content_list: res.append(get_single_frame_from_scene(scene, video_capture)) return res


get_image_embedding 函数使用CLIP 模型为给定图像生成嵌入,将其传递给模型,并将结果的特征向量作为浮点数列表返回:


 def get_image_embedding(image): inputs = clip_processor(images=image, return_tensors="pt") image_embeddings = model.get_image_features(**inputs) return list(image_embeddings[0].detach().numpy().astype(float))


此代码连接到 Astra DB 数据库,创建具有矢量嵌入的 JSON 对象集合,并将这些对象插入到数据库中的“视频”集合中:


 import json from astrapy import DataAPIClient client = DataAPIClient(ASTRA_DB_TOKEN) database = client.get_database(ASTRA_DB_API_ENDPOINT) collectiondb = database.video json_embedding = [ {"id": f"{i+1}", "$vector": values} for i, values in enumerate(image_embeddings) ] response = collectiondb.insert_many(json_embedding)


使用 OpenAI Clip 嵌入搜索特定文本:


 query_text = "men with white hair" query_embedding = get_text_embedding(query_text) result = collectiondb.find_one({}, vector=query_embedding)


方法 2:使用 Google 多模态嵌入模型进行多模态嵌入

在这里,您可以看到如何使用 Google 的多模式嵌入模型创建视频嵌入并将其存储在 Astra DB 中,包括 start_offset_sec 和 end_offset_sec 等元数据信息(查看GitHub 仓库)。


 import vertexai from vertexai.vision_models import MultiModalEmbeddingModel, Video from astrapy import DataAPIClient import streamlit as st # Initialize Vertex AI vertexai.init(project=st.secrets['PROJECT'], location=st.secrets['REGION']) # Initialize the client client = DataAPIClient(st.secrets['ASTRA_TOKEN']) database = client.get_database(st.secrets['ASTRA_API_ENDPOINT']) my_collection = database.create_collection( "videosearch", dimension=1408, metric=astrapy.constants.VectorMetric.COSINE, ) collectiondb = database.videosearch # Load the pre-trained model and video model = MultiModalEmbeddingModel.from_pretrained("multimodalembedding") video = Video.load_from_file(st.secrets['PATH']) # Get embeddings with the specified contextual text embeddings = model.get_embeddings( video=video, contextual_text="Mixed Content", dimension=1408, ) # Video Embeddings are segmented based on the video_segment_config. for video_embedding in embeddings.video_embeddings: # Check if embedding is a numpy array or a tensor and convert accordingly if isinstance(video_embedding.embedding, (list, tuple)): embedding_list = video_embedding.embedding else: embedding_list = video_embedding.embedding.tolist() embedding_data = { "metadata": { "start_offset_sec": video_embedding.start_offset_sec, "end_offset_sec": video_embedding.end_offset_sec }, "$vector": embedding_list # Ensure embedding is in list format } response = collectiondb.insert_one(embedding_data)


在这里,我们设置Streamlit UI ,一款功能强大的工具,利用 Python 的简单性和强大功能,以最少的努力创建交互式、数据驱动的 Web 应用程序。此外,我们还在以下代码中启用了特定文本或图像的搜索功能:


 import vertexai from vertexai.vision_models import MultiModalEmbeddingModel, Video from vertexai.vision_models import Image as img from astrapy import DataAPIClient import streamlit as st from PIL import Image st.title("Video Search App") user_input_placeholder = st.empty() user_input = user_input_placeholder.text_input( "Describe the content you're looking for:", key="user_input" ) uploaded_file = st.file_uploader("Choose an image file that is similar you're looking for", type="png") if uploaded_file is not None: image = Image.open(uploaded_file) image_path = st.secrets['IMAGE_PATH'] image.save(image_path) saved_image = Image.open(image_path) st.image(saved_image, caption='', use_column_width=True) # Initialize Vertex AI vertexai.init(project=st.secrets['PROJECT'], location=st.secrets['REGION']) # Initialize the client client = DataAPIClient(st.secrets['ASTRA_TOKEN']) database = client.get_database(st.secrets['ASTRA_API_ENDPOINT']) collectiondb = database.videosearch # Load the pre-trained model and video model = MultiModalEmbeddingModel.from_pretrained("multimodalembedding") video = Video.load_from_file(st.secrets['PATH']) # Search action trigger if st.button("Search"): if user_input: embeddings = model.get_embeddings( contextual_text=user_input ) result = collectiondb.find_one({}, vector=embeddings.text_embedding) start_offset_value = result['metadata']['start_offset_sec'] end_offset_value = result['metadata']['end_offset_sec'] st.write("Text input result found between: " + str(start_offset_value) + "-" + str(end_offset_value)) video_file = open(st.secrets['PATH'], 'rb') video_bytes = video_file.read() st.video(video_bytes, start_time=start_offset_value) if uploaded_file is not None: embimage = img.load_from_file(image_path) embeddingsimg = model.get_embeddings( image=embimage ) imgresult = collectiondb.find_one({}, vector=embeddingsimg.image_embedding) start_offset_value = imgresult['metadata']['start_offset_sec'] end_offset_value = imgresult['metadata']['end_offset_sec'] st.write("Image input result found between: " + str(start_offset_value) + "-" + str(end_offset_value)) video_file = open(st.secrets['PATH'], 'rb') video_bytes = video_file.read() st.video(video_bytes, start_time=start_offset_value)


结果如下:

结论

探索这两种方法凸显了现代人工智能技术在视频搜索应用中的巨大潜力。虽然使用图像嵌入的帧搜索可以为特定的视觉搜索提供高精度,但多模态嵌入的灵活性和强大功能使其成为满足复杂多模态搜索需求的最佳选择。


通过使用 Astra DB,视频搜索平台可以为用户提供高级搜索功能,从而能够从大型数据集中精准高效地检索特定视频内容。这显著提高了分析和解释视频数据的能力,从而获得更快、更准确的洞察。


展望未来,随着研究和开发的不断推进,视频搜索的未来一片光明。人工智能和机器学习的进步将继续改进这些技术,使其更易于使用和高效运行。与增强现实和实时视频分析等其他新兴技术的结合将进一步扩展其功能。


作者:OpenOrigins 工程主管Matthew Pendlebury和 DataStax 解决方案架构师Betul O'Reilly