+
+

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

+
+

实现过程

+

1. 特征提取:使用预训练的 InceptionV3 模型,从视频的若干帧中提取高维的视觉特征。将每个视频的所有帧特征取平均值,生成一个固定长度的特征向量来表示该视频。

+

2. 聚类:通过 K-Means 的聚类结果,每个视频被分配了一个簇标签,代表该视频与哪些视频在特征上最相似。

+

3. 分类整理:最后根据簇标签,将视频移动到相应的分类文件夹中,每个文件夹对应一个簇。

+

InceptionV3 模型

+

InceptionV3 是一种用于图像分类和特征提取的深度学习模型,它是Inception 系列模型的第三个版本,由 Google 在 2015 年提出。

+

它最初是作为图像分类任务的一个模型,能够将图像分类到 1000 个类别中(如狗、猫、汽车等)。通过去除模型的最后几层(分类部分),可以将 InceptionV3 用作特征提取器。

+

+

簇是聚类算法的核心概念,表示数据中相似的子集,目的是将无标签的数据点分组。

+

K-Means

+

K-Means 是一种常用的无监督聚类算法,它的目标是将数据点分成 K 个簇(Cluster),使得每个簇内的数据点尽可能接近同一个中心(即簇的质心)。

+

算法的核心思想是通过迭代的方式找到 K 个最优的簇质心,并根据这些质心将数据进行分组。

+

源码

+

1. 安装依赖库

+
pip install moviepy scikit-learn tensorflow opencv-python
+

2. 实现代码

+
import os
+import numpy as np
+import cv2
+from moviepy.editor import VideoFileClip
+from sklearn.cluster import KMeans
+from tensorflow.keras.applications import InceptionV3
+from tensorflow.keras.applications.inception_v3 import preprocess_input
+from tensorflow.keras.preprocessing import image
+from tensorflow.keras.models import Model
+from shutil import move
+
+# 提取视频的帧作为特征
+def extract_video_features(video_path, model, frame_interval=30):
+    video = VideoFileClip(video_path)
+    frame_count = 0
+    features = []
+
+    for frame in video.iter_frames(fps=1):  # 以每秒一帧的速度获取帧
+        if frame_count % frame_interval == 0:
+            # Resize frame to match model input size (299x299 for InceptionV3)
+            img = cv2.resize(frame, (299, 299))
+            img = image.img_to_array(img)
+            img = np.expand_dims(img, axis=0)
+            img = preprocess_input(img)
+
+            # 提取特征
+            feature = model.predict(img)
+            features.append(feature.flatten())
+
+        frame_count += 1
+
+    # 取视频的所有帧特征的均值作为视频的最终特征
+    return np.mean(features, axis=0)
+
+# 批量提取目录下所有视频的特征
+def extract_features_for_all_videos(input_dir, model, frame_interval=30):
+    video_features = []
+    video_files = []
+
+    for filename in os.listdir(input_dir):
+        if filename.endswith(".mp4"):  # 你可以根据需要修改文件格式
+            video_path = os.path.join(input_dir, filename)
+            print(f"正在处理视频: {filename}")
+            features = extract_video_features(video_path, model, frame_interval)
+            video_features.append(features)
+            video_files.append(filename)
+
+    return np.array(video_features), video_files
+
+# 对视频进行聚类
+def cluster_videos(video_features, num_clusters=3):
+    kmeans = KMeans(n_clusters=num_clusters, random_state=42)
+    kmeans.fit(video_features)
+    return kmeans.labels_
+
+# 将视频分类到不同的文件夹
+def classify_videos(input_dir, output_dir, video_files, labels):
+    for label, filename in zip(labels, video_files):
+        output_folder = os.path.join(output_dir, f"cluster_{label}")
+        if not os.path.exists(output_folder):
+            os.makedirs(output_folder)
+
+        input_path = os.path.join(input_dir, filename)
+        output_path = os.path.join(output_folder, filename)
+
+        move(input_path, output_path)
+        print(f"已将视频 {filename} 移动到 {output_folder}")
+
+# 主函数
+def main(input_dir, output_dir, num_clusters=3, frame_interval=30):
+    # 加载预训练的InceptionV3模型,并去掉顶层的分类部分,只用来提取特征
+    base_model = InceptionV3(weights='imagenet')
+    model = Model(inputs=base_model.input, outputs=base_model.get_layer('avg_pool').output)
+
+    # 提取所有视频的特征
+    video_features, video_files = extract_features_for_all_videos(input_dir, model, frame_interval)
+
+    # 对视频进行聚类
+    labels = cluster_videos(video_features, num_clusters)
+
+    # 将视频移动到相应的分类文件夹
+    classify_videos(input_dir, output_dir, video_files, labels)
+
+# 示例调用
+input_directory = "path/to/input_videos"
+output_directory = "path/to/output_videos"
+main(input_directory, output_directory, num_clusters=30, frame_interval=30)
+

3. 代码说明

+

1. extract_video_features:从每个视频中提取帧,使用 InceptionV3 模型提取每个帧的特征,并最终取所有帧特征的平均值作为该视频的代表特征。

+

2. extract_features_for_all_videos:批量提取目录中所有视频的特征。

+

3. cluster_videos:使用 K-Means 聚类算法对视频进行分类,将相似的视频聚到一起。

+

4. classify_videos:将视频根据聚类结果移动到不同的分类文件夹。

+

5. main:主函数,负责加载模型、提取特征、聚类以及将视频分类。

+

4. 调用说明

+

1. input_directory: 视频所在的输入文件夹。

+

2. output_directory: 输出文件夹,程序会根据聚类结果创建不同的文件夹,将相似的视频分类进去。

+

3. num_clusters: 要分类的类别数,即希望将视频分为多少类。

+

4. frame_interval: 每隔多少帧提取一次特征帧。值越大,提取帧的间隔越大。

+

源码地址:https://github.com/CYRUS-STUDIO/classify-videos-kmeans-python

+ +