野生動物の行動を研究し、人里離れた森にカメラを設置して撮影した何百時間ものビデオ映像を分析するデータ サイエンティストを想像してみてください。あるいは、新しい戦略を立てるために、シーズン全体の試合から重要なプレーを特定する必要のあるスポーツ コーチを想像してみてください。あるいは、ドキュメンタリーをまとめるために、膨大なビデオ ギャラリー内の特定のシーンを検索する映画製作者を想像してみてください。
従来、これらの専門家は皆、何時間にも及ぶ映像を手作業で整理するという、時間がかかり、エラーが発生しやすく、圧倒的な課題に直面しています。
しかし、人工知能と機械学習の進歩により、ビデオ検索アプリケーションは劇的に変化しました。これらのテクノロジーにより、膨大なビデオデータセット内の特定のオブジェクトやイベントを驚くほど精巧に検索できるようになりました。データ サイエンティストや研究者は、非常に高い精度と効率で関連するビデオ セグメントを特定できます。
目的は、高度な検索機能を提供して研究プロセスを簡素化し、ユーザーが非常に大規模なビデオ データセットから特定のコンテンツやプロパティを持つ映像を簡単に見つけられるようにすることでした。
OpenOrigins は、洗練された検索アルゴリズムとユーザーフレンドリーなインターフェースを使用することで、このコミュニティにとってプラットフォームを重要なツールにすることを目指しました。
OpenOrigins は、このビデオ検索サービスを構築するために、画像埋め込みを使用したフレーム検索とマルチモーダル埋め込みという 2 つの技術的アプローチを検討しました。それぞれのオプションを見てみましょう。
「自然の生息地にいる鹿を映したビデオコンテンツは何分あるか」などの複雑な質問に答えるためにビデオのセマンティック検索を有効にするには、基本的なキーワード メタデータのマッチングを超えてビデオのコンテンツを理解し、解釈できる高度な検索機能が必要です。これを実現するための鍵は、マルチモーダル埋め込みです。
マルチモーダル埋め込みモデルとマルチモーダル大規模言語モデル (LLM) は、同様のソリューションとして考えることができます。CLIP や Google マルチモーダル埋め込みなどのモデルは、テキスト、画像、ビデオなどのデータ タイプに対して埋め込みを生成し、意味論的意味を捉える高次元ベクトルを作成します。これにより、セマンティック検索、コンテンツ検索、類似性検出などのアプリケーションが可能になります。
一方、GPT-4 (マルチモーダル機能付き)、Flamingo、Gemini などのマルチモーダル LLM は、さまざまな種類のデータにわたってコンテンツを理解および生成するように設計されています。
これらのモデルは、マルチモーダル入力(テキストや画像など)を使用してマルチモーダル出力を生成することで、会話型 AI やコンテンツ生成などの複雑なタスクで優れたパフォーマンスを発揮し、意味のあるコンテキスト豊富な応答を生み出します。
埋め込みモデルは効率的な検索と取得に重点を置いていますが、マルチモーダル LLM は多様なコンテンツの生成と理解に適しているため、チャットボット、インタラクティブ アシスタント、マルチモーダル インタラクションに最適です。
| マルチモーダル埋め込みモデル | マルチモーダル大規模言語モデル (LLM) |
---|---|---|
主目的 | テキストや画像などのさまざまなデータ形式にわたる検索と取得を可能にする | 複数のモダリティにわたるコンテンツを生成し理解する |
コアユースケース | セマンティック検索、コンテンツ検索、類似性 | 会話型AI、コンテンツ生成、対話システム |
サンプルモデル | CLIP、Google マルチモーダル埋め込みモデル | GPT-4(マルチモーダル機能付き)、Llava、Gemini、Flamingo、LaMDA |
検索と取得 | 高速かつ正確な検索と類似性のために最適化 | さまざまなデータ タイプにわたる包括的な理解と生成のために最適化されています。 |
アプリケーション | コンテンツモデレーション、推奨システム、セマンティック検索 | 会話エージェント、コンテンツ作成、マルチモーダルインタラクション |
OpenOriginsが最初に検討した方法は、画像埋め込みを使用してビデオをフレームごとに分析するというものでした。このアプローチでは、ビデオを個々のフレームに分解し、それぞれをベクター埋め込みに変換します。
CLIP は、何百万もの Web 画像とその説明を学習することで、人間が世界を認識して説明するのと同じような方法で視覚概念を理解します。トレーニングには「対照学習」が含まれ、画像と正しい説明を一致させることを学習します。これにより、私たちが見るものと使用する言葉のつながりを理解することで、さまざまなタスクを処理する独自の能力が得られます。
これにより、CLIP は適応性が高くなり、画像と言語の両方を深く理解する必要があるアプリケーションに役立ちます。
これらの埋め込みはベクター データベースに保存され、意味の類似性に基づいてテキストとテキスト、テキストと画像、画像と画像を一致させることで、高速かつ正確な検索が可能になります。
フレーム抽出は、指定された間隔でビデオをフレームに分解します。各フレームは画像埋め込みモデルを通じて処理され、高次元のベクトル表現が生成されます。これらのベクトルは、効率的な類似性検索を可能にする DataStax Astra DB などのベクトル ストアに保存されます。
この方法は、マルチモーダルなセマンティック検索において高い精度を提供し、特定のオブジェクトやシーンの検索に適しています。ただし、特に長いビデオの場合は計算量が多く、時間的なコンテキストやフレーム間の変化を見逃す可能性があります。
2つ目のアプローチは、マルチモーダル埋め込みを備えた最新の生成AI技術を活用し、具体的にはGoogleの
これらの埋め込みにより、ビデオを数値で表現することで高度な機械学習タスクが可能になり、ビデオ コンテンツの検索、分析、分類が容易になります。
これらの埋め込みを統合すると
Google のマルチモーダル埋め込みと CLIP メソッドは、それぞれマルチモーダル データを共通の埋め込みスペースに埋め込みます。主な違いは、Google のマルチモーダル埋め込みはビデオをサポートするのに対し、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 を呼び出して各シーンから 1 つのフレームを抽出し、これらのフレームをリストに保存します。
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関数は、
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)
ここでは、Googleのマルチモーダル埋め込みモデルを使用してビデオ埋め込みを作成し、start_offset_secやend_offset_secなどのメタデータ情報を含めてAstra DBに保存する方法を説明します(
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)
ここでは、
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)
結果は次のようになります。
これら 2 つのアプローチを調査すると、ビデオ検索アプリケーションにおける最新の AI 技術の大きな可能性が明らかになります。画像埋め込みによるフレーム検索は特定の視覚検索に高い精度を提供しますが、マルチモーダル埋め込みの柔軟性とパワーにより、複雑なマルチモーダル検索の要件には最適な選択肢となります。
Astra DB を使用することで、ビデオ検索プラットフォームはユーザーに高度な検索機能を提供し、大規模なデータセットから特定のビデオ コンテンツを正確かつ効率的に取得できるようになります。これにより、ビデオ データの分析と解釈の能力が大幅に向上し、より迅速かつ正確な洞察が得られます。
今後、継続的な研究開発により、ビデオ検索の未来は明るいものになるでしょう。AI と機械学習の進歩により、これらの技術は今後も改善され、よりアクセスしやすく、効率的になるでしょう。拡張現実やリアルタイム ビデオ分析などの他の新興技術との統合により、その機能はさらに拡大するでしょう。
OpenOrigins エンジニアリング責任者Matthew Pendleburyと DataStax ソリューション アーキテクトBetul O'Reillyによる記事