使用CLIP进行视频分类分析

在数字媒体时代,视频内容的管理和检索变得越来越重要。为了有效地对广告视频集合进行归档和搜索,可以使用CLIP技术对视频进行分类。CLIP(Contrastive Language-Image Pretraining)是一种先进的人工智能模型,能够将视频帧与预定义的类别进行匹配,从而实现视频内容的自动化分类。

本文将介绍如何使用CLIP技术对视频进行分析和分类。将以Roboflow首页上展示的包含五个场景的视频为例,使用CLIP来回答关于视频的三个问题:

  1. 视频是否包含建筑场景?
  2. 如果视频包含建筑场景,那么该场景何时开始?
  3. 建筑场景持续多长时间?

将按照以下步骤进行:

  1. 安装所需的依赖项
  2. 将视频分割成帧
  3. 运行CLIP对有限的帧集进行分类

首先,需要安装Roboflow Python包和supervision,这两个工具将分别用于运行推理和处理视频。

pip install roboflow supervision

接下来,将编写代码来使用CLIP。首先,需要导入依赖项并设置一些将在脚本中使用的变量:

import requests import base64 from PIL import Image from io import BytesIO import os INFERENCE_ENDPOINT = "https://infer.roboflow.com" API_KEY = "API_KEY" VIDEO = "./video.mov" prompts = [ "construction site", "something else" ] ACTIVE_PROMPT = "construction site"

在上述代码中,需要替换API_KEY为Roboflow API密钥,VIDEO为要分析和分类的视频文件名,prompts为每个视频帧应该分类的类别列表,ACTIVE_PROMPT为想要计算分析的提示。

然后,需要定义一个函数,该函数可以对视频中的每一帧运行推理:

def classify_image(image: str) -> dict: image_data = Image.fromarray(image) buffer = BytesIO() image_data.save(buffer, format="JPEG") image_data = base64.b64encode(buffer.getvalue()).decode("utf-8") payload = { "api_key": API_KEY, "subject": { "type": "base64", "value": image_data }, "prompt": prompts, } data = requests.post(INFERENCE_ENDPOINT + "/clip/compare?api_key=" + API_KEY, json=payload) response = data.json() highest_prediction = 0 highest_prediction_index = 0 for i, prediction in enumerate(response["similarity"]): if prediction > highest_prediction: highest_prediction = prediction highest_prediction_index = i return prompts[highest_prediction_index]

这个函数将接收一个视频帧,使用CLIP和Roboflow推理服务器运行推理,然后返回之前设置的提示的分类结果。

最后,需要在视频的帧上调用这个函数。为此,将使用supervision将视频分割成帧,然后对每一帧运行CLIP:

results = [] for i, frame in enumerate(sv.get_video_frames_generator(source_path=VIDEO, stride=10)): print("Frame", i) label = classify_image(frame) results.append(label) video_length = 10 * len(results) video_length = video_length / 24 print(f"Does this video contain a {ACTIVE_PROMPT}?", "yes" if ACTIVE_PROMPT in results else "no") if ACTIVE_PROMPT in results: print(f"When does the {ACTIVE_PROMPT} first appear?", round(results.index(ACTIVE_PROMPT) * 10 / 24, 0), "seconds") print(f"For how long is the {ACTIVE_PROMPT} visible?", round(results.count(ACTIVE_PROMPT) * 10 / 24, 0), "seconds")

上述代码设置了stride值为10,这意味着每10帧视频中将收集一帧用于分类。为了更快的结果,可以设置更高的stride值。为了更精确的结果,可以将stride设置为更低的值。stride值为10意味着大约每秒钟收集2帧(假设视频为24帧/秒)。

运行上述代码后,代码将找到:

  • 视频是否包含建筑工地;
  • 建筑场景何时开始;
  • 建筑场景持续多长时间。

让运行代码并看看结果:

Does this video contain a construction site? yes When does the construction site first appear? 7 seconds For how long is the construction site visible? 6 seconds

代码成功地识别出视频中包含建筑场景,确定了场景开始的时间,以及场景的持续时间。然而,CLIP确实将造船厂场景也归类为建筑。

这就是为什么“建筑工地可见”的指标是6秒而不是实际建筑工地可见的大约3秒。CLIP可能将移动的重型车辆和造船厂的一般环境解释为建筑,尽管实际上并没有进行建筑活动。

CLIP并不完美:模型可能无法捕捉到对人类来说显而易见的事物。如果CLIP在用例中表现不佳,值得探索如何为项目创建定制的分类模型。可以使用Roboflow来训练自定义分类模型。

注意:由于设置了stride值为10,返回的时间戳并不完全精确。为了获得更精确的时间戳,可以设置更低的stride值。更低的stride值将对更多的帧运行推理,因此推理将需要更长的时间。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485