在数字媒体时代,视频内容的管理和检索变得越来越重要。为了有效地对广告视频集合进行归档和搜索,可以使用CLIP技术对视频进行分类。CLIP(Contrastive Language-Image Pretraining)是一种先进的人工智能模型,能够将视频帧与预定义的类别进行匹配,从而实现视频内容的自动化分类。
本文将介绍如何使用CLIP技术对视频进行分析和分类。将以Roboflow首页上展示的包含五个场景的视频为例,使用CLIP来回答关于视频的三个问题:
- 视频是否包含建筑场景?
- 如果视频包含建筑场景,那么该场景何时开始?
- 建筑场景持续多长时间?
将按照以下步骤进行:
- 安装所需的依赖项
- 将视频分割成帧
- 运行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值将对更多的帧运行推理,因此推理将需要更长的时间。