diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/44.iml b/.idea/44.iml new file mode 100644 index 0000000..1a0be46 --- /dev/null +++ b/.idea/44.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..c2bb027 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,20 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:D:\code\python\44\i3d.db + $ProjectFileDir$ + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..837d06b --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,31 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..afd2615 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e4cde36 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/1.py b/1.py new file mode 100644 index 0000000..fc19040 --- /dev/null +++ b/1.py @@ -0,0 +1,49 @@ +import os +import subprocess +import tempfile +import shutil + +# 根目录 +input_dir = r"D:\DESKTOP\2025\44\a1\dataset" # 替换为你的视频根目录 +video_exts = {".avi", ".mov", ".mkv", ".flv", ".webm", ".wmv", ".mp4",".m4s"} + +def convert_and_replace(filepath): + ext = os.path.splitext(filepath)[1].lower() + if ext not in video_exts: + return + + print(f"处理文件: {filepath}") + + # 创建临时输出文件 + temp_fd, temp_path = tempfile.mkstemp(suffix=".mp4") + os.close(temp_fd) # 不使用 open 的文件描述符 + + # ffmpeg 转换命令(保留前30秒,360p,输出mp4) + cmd = [ + "ffmpeg", + "-y", + "-i", filepath, + "-t", "30", + "-vf", "scale=-2:480", + "-c:v", "libx264", # 改为 libx265 可使用 H.265 + "-preset", "slow", + "-crf", "18", + "-c:a", "aac", + "-b:a", "64k", + temp_path + ] + + try: + subprocess.run(cmd, check=True) + shutil.move(temp_path, filepath) + print(f"已替换: {filepath}") + except subprocess.CalledProcessError as e: + print(f"失败: {filepath}\n{e}") + if os.path.exists(temp_path): + os.remove(temp_path) + +# 递归遍历处理 +for root, _, files in os.walk(input_dir): + for name in files: + file_path = os.path.join(root, name) + convert_and_replace(file_path) \ No newline at end of file diff --git a/I3D.py b/I3D.py new file mode 100644 index 0000000..c9cf6a1 --- /dev/null +++ b/I3D.py @@ -0,0 +1,52 @@ +import torch +import torch.nn.functional as F +import torchvision.transforms as transforms +from pytorchvideo.models.hub import i3d_r50 +import cv2 +import numpy as np +from PIL import Image + +model = i3d_r50(pretrained=True).eval() +feature_extractor = torch.nn.Sequential(*model.blocks[:-1]) + +def preprocess_video(video_path, num_frames=32, size=224): + cap = cv2.VideoCapture(video_path) + frames = [] + transform = transforms.Compose([ + transforms.Resize((size, size)), + transforms.ToTensor(), + transforms.Normalize(mean=[0.45, 0.45, 0.45], std=[0.225, 0.225, 0.225]) + ]) + + total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) + frame_indices = np.linspace(0, total_frames - 1, num_frames).astype(int) + + for i in frame_indices: + cap.set(cv2.CAP_PROP_POS_FRAMES, i) + ret, frame = cap.read() + if not ret: + break + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + frame = Image.fromarray(frame) + frame = transform(frame) + frames.append(frame) + + cap.release() + video_tensor = torch.stack(frames).permute(1, 0, 2, 3).unsqueeze(0) + return video_tensor + +def extract_features(video_tensor): + with torch.no_grad(): + features = feature_extractor(video_tensor) + features = F.adaptive_avg_pool3d(features, 1) + features = features.flatten() + return features.numpy() + +def video_features(video_path): + video_tensor = preprocess_video(video_path) + features = extract_features(video_tensor) + return features + +video_path = r'D:\DESKTOP\2025\44\a1\dataset\org\0.mp4' +video_f = video_features(video_path) +print(f"视频features: {video_f.shape}") diff --git a/LBPTOP.db b/LBPTOP.db new file mode 100644 index 0000000..98b479d Binary files /dev/null and b/LBPTOP.db differ diff --git a/LBPTOP.ipynb b/LBPTOP.ipynb new file mode 100644 index 0000000..ef83897 --- /dev/null +++ b/LBPTOP.ipynb @@ -0,0 +1,246 @@ +{ + "cells": [ + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T04:06:31.135934Z", + "start_time": "2025-04-14T04:06:30.845929Z" + } + }, + "cell_type": "code", + "source": [ + "import cv2\n", + "import numpy as np\n", + "from skimage.feature import local_binary_pattern\n" + ], + "id": "9157e102c51206bb", + "outputs": [], + "execution_count": 1 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T04:06:31.144988Z", + "start_time": "2025-04-14T04:06:31.138940Z" + } + }, + "cell_type": "code", + "source": [ + "def extract_lbp_top(video_path, radius=2, n_points=8, method='uniform', block_size=10):\n", + " cap = cv2.VideoCapture(video_path)\n", + " frames = []\n", + "\n", + " # 读取所有帧\n", + " while True:\n", + " ret, frame = cap.read()\n", + " if not ret:\n", + " break\n", + " gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n", + " frames.append(gray)\n", + " cap.release()\n", + "\n", + " frames = np.array(frames)\n", + " T, H, W = frames.shape # 时间、空间维度\n", + "\n", + " # 使用滑动窗口计算 XT, YT 平面\n", + " hist_xy = np.zeros((n_points + 2,))\n", + " hist_xt = np.zeros((n_points + 2,))\n", + " hist_yt = np.zeros((n_points + 2,))\n", + "\n", + " # LBP on XY plane\n", + " for t in range(0, T, block_size):\n", + " if t >= T:\n", + " break\n", + " lbp = local_binary_pattern(frames[t], n_points, radius, method)\n", + " hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), density=True)\n", + " hist_xy += hist\n", + "\n", + " # LBP on XT plane\n", + " for y in range(0, H, block_size):\n", + " if y >= H:\n", + " break\n", + " xt_plane = frames[:, y, :]\n", + " lbp = local_binary_pattern(xt_plane, n_points, radius, method)\n", + " hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), density=True)\n", + " hist_xt += hist\n", + "\n", + " # LBP on YT plane\n", + " for x in range(0, W, block_size):\n", + " if x >= W:\n", + " break\n", + " yt_plane = frames[:, :, x]\n", + " lbp = local_binary_pattern(yt_plane, n_points, radius, method)\n", + " hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), density=True)\n", + " hist_yt += hist\n", + "\n", + " # 拼接三个平面的直方图作为最终特征向量\n", + " feature_vector = np.concatenate([hist_xy, hist_xt, hist_yt])\n", + " feature_vector /= np.linalg.norm(feature_vector) # 归一化\n", + "\n", + " return feature_vector" + ], + "id": "d9d5bd6f6a9e114a", + "outputs": [], + "execution_count": 2 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T04:06:31.297545Z", + "start_time": "2025-04-14T04:06:31.294247Z" + } + }, + "cell_type": "code", + "source": [ + "def getFeature(video_path = r\"D:\\DESKTOP\\2025\\44\\a1\\dataset\\org\\1.mp4\"):\n", + "\n", + " feature = extract_lbp_top(video_path)\n", + " # print(\"Video feature shape (for copyright):\", feature.shape)\n", + " return feature" + ], + "id": "404b8b3562026f1f", + "outputs": [], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T04:06:32.509232Z", + "start_time": "2025-04-14T04:06:31.302931Z" + } + }, + "cell_type": "code", + "source": [ + "import sqlite3\n", + "import io\n", + "import os\n", + "import tqdm\n", + "\n", + "# 注册适配器与转换器:numpy数组 <-> BLOB\n", + "def adapt_array(arr):\n", + " out = io.BytesIO()\n", + " np.save(out, arr)\n", + " out.seek(0)\n", + " return sqlite3.Binary(out.read())\n", + "\n", + "def convert_array(text):\n", + " out = io.BytesIO(text)\n", + " out.seek(0)\n", + " return np.load(out)\n", + "\n", + "# 注册自定义类型处理\n", + "sqlite3.register_adapter(np.ndarray, adapt_array)\n", + "sqlite3.register_converter(\"array\", convert_array)\n", + "\n", + "# 创建数据库连接(带类型检测)\n", + "conn = sqlite3.connect(\"LBPTOP.db\", detect_types=sqlite3.PARSE_DECLTYPES)\n", + "cursor = conn.cursor()\n", + "\n", + "# 创建表\n", + "cursor.execute(\"\"\"\n", + "CREATE TABLE IF NOT EXISTS data (\n", + " id INTEGER PRIMARY KEY,\n", + " array BLOB,\n", + " group_path TEXT,\n", + " full_path TEXT\n", + ")\n", + "\"\"\")\n", + "\n", + "\n", + "def add_to_db(array_to_store,group_path,full_path):\n", + " cursor.execute(\"INSERT INTO data (array,group_path,full_path) VALUES (?,?,?)\", (array_to_store,group_path,full_path,))\n", + " conn.commit()\n", + "\n", + "# # 读取数组\n", + "# cursor.execute(\"SELECT array FROM data WHERE id=1\")\n", + "# fetched_array = cursor.fetchone()[0]\n", + "#\n", + "# print(\"原始数组:\\n\", array_to_store)\n", + "# print(\"读取的数组:\\n\", fetched_array)\n", + "\n", + "folder_path = r\"D:\\DESKTOP\\2025\\44\\a1\\dataset\"\n", + "\n", + "all_files = []\n", + "names = [str(x)+\".mp4\" for x in range(10)]\n", + "print(names)\n", + "\n", + "\n", + "# 遍历文件夹\n", + "for group_path in os.listdir(folder_path):\n", + " full_path = os.path.join(folder_path, group_path)\n", + " if os.path.isdir(full_path):\n", + " # 遍历子文件夹\n", + " for video_path in os.listdir(full_path):\n", + " if os.path.basename(video_path) in names:\n", + " video_full_path = os.path.join(full_path, video_path)\n", + " if os.path.isfile(video_full_path):\n", + " # 处理视频文件\n", + " all_files.append((group_path,video_full_path))\n", + "print(len(all_files))\n" + ], + "id": "4dc69bad309cb6b1", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['0.mp4', '1.mp4', '2.mp4', '3.mp4', '4.mp4', '5.mp4', '6.mp4', '7.mp4', '8.mp4', '9.mp4']\n", + "70\n" + ] + } + ], + "execution_count": 4 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T04:20:52.302187Z", + "start_time": "2025-04-14T04:06:32.521053Z" + } + }, + "cell_type": "code", + "source": [ + "for group_path, video_full_path in tqdm.tqdm(all_files):\n", + " # 读取视频特征\n", + " feature = getFeature(video_full_path)\n", + " # 将特征存储到数据库\n", + " add_to_db(feature,group_path,video_full_path)\n", + " # print(f\"已处理并存储: {video_full_path}\")\n", + "\n", + "conn.close()\n" + ], + "id": "3cd83672f6901125", + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 70/70 [14:19<00:00, 12.28s/it]\n" + ] + } + ], + "execution_count": 5 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/LBPTOP.py b/LBPTOP.py new file mode 100644 index 0000000..465c0aa --- /dev/null +++ b/LBPTOP.py @@ -0,0 +1,61 @@ +import cv2 +import numpy as np +from skimage.feature import local_binary_pattern + + +def extract_lbp_top(video_path, radius=2, n_points=8, method='uniform', block_size=10): + cap = cv2.VideoCapture(video_path) + frames = [] + + # 读取所有帧 + while True: + ret, frame = cap.read() + if not ret: + break + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + frames.append(gray) + cap.release() + + frames = np.array(frames) + T, H, W = frames.shape # 时间、空间维度 + + # 使用滑动窗口计算 XT, YT 平面 + hist_xy = np.zeros((n_points + 2,)) + hist_xt = np.zeros((n_points + 2,)) + hist_yt = np.zeros((n_points + 2,)) + + # LBP on XY plane + for t in range(0, T, block_size): + if t >= T: + break + lbp = local_binary_pattern(frames[t], n_points, radius, method) + hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), density=True) + hist_xy += hist + + # LBP on XT plane + for y in range(0, H, block_size): + if y >= H: + break + xt_plane = frames[:, y, :] + lbp = local_binary_pattern(xt_plane, n_points, radius, method) + hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), density=True) + hist_xt += hist + + # LBP on YT plane + for x in range(0, W, block_size): + if x >= W: + break + yt_plane = frames[:, :, x] + lbp = local_binary_pattern(yt_plane, n_points, radius, method) + hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), density=True) + hist_yt += hist + + # 拼接三个平面的直方图作为最终特征向量 + feature_vector = np.concatenate([hist_xy, hist_xt, hist_yt]) + feature_vector /= np.linalg.norm(feature_vector) # 归一化 + + return feature_vector + +video_path = r'D:\DESKTOP\2025\44\a1\dataset\org\1.mp4' +features = extract_lbp_top(video_path) +print(f"特征向量维度: {features.shape}") \ No newline at end of file diff --git a/analy.ipynb b/analy.ipynb new file mode 100644 index 0000000..55695df --- /dev/null +++ b/analy.ipynb @@ -0,0 +1,292 @@ +{ + "cells": [ + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T06:58:32.199713Z", + "start_time": "2025-04-14T06:58:32.134049Z" + } + }, + "cell_type": "code", + "source": [ + "import sqlite3\n", + "import numpy as np\n", + "import io\n", + "from numpy.linalg import norm\n", + "from collections import defaultdict" + ], + "id": "6917288db44004ea", + "outputs": [], + "execution_count": 1 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T06:58:34.129528Z", + "start_time": "2025-04-14T06:58:34.126022Z" + } + }, + "cell_type": "code", + "source": [ + "currdb = \"i3d.db\"\n", + "#currdb = \"LBPTOP.db\"\n", + "currdb = \"slowfast.db\"" + ], + "id": "dd9b84fa98c77e5a", + "outputs": [], + "execution_count": 2 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T06:58:36.801611Z", + "start_time": "2025-04-14T06:58:36.798114Z" + } + }, + "cell_type": "code", + "source": [ + "# 注册适配器与转换器:numpy数组 <-> BLOB\n", + "def adapt_array(arr):\n", + " out = io.BytesIO()\n", + " np.save(out, arr)\n", + " out.seek(0)\n", + " return sqlite3.Binary(out.read())\n", + "\n", + "def convert_array(text):\n", + " out = io.BytesIO(text)\n", + " out.seek(0)\n", + " return np.load(out)" + ], + "id": "fa2ab158cbe0aa98", + "outputs": [], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T07:01:06.063185Z", + "start_time": "2025-04-14T07:01:06.060008Z" + } + }, + "cell_type": "code", + "source": [ + "\n", + "sqlite3.register_adapter(np.ndarray, adapt_array)\n", + "sqlite3.register_converter(\"BLOB\", convert_array)\n", + "\n", + "# 连接SQLite数据库\n", + "conn = sqlite3.connect(currdb, detect_types=sqlite3.PARSE_DECLTYPES)\n", + "cursor = conn.cursor()" + ], + "id": "629eb156f332c0bc", + "outputs": [], + "execution_count": 12 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T07:01:06.372809Z", + "start_time": "2025-04-14T07:01:06.362911Z" + } + }, + "cell_type": "code", + "source": [ + "# 读取数据库所有数据\n", + "cursor.execute(\"SELECT id, array, group_path, full_path FROM data\")\n", + "all_data = cursor.fetchall()" + ], + "id": "ba7902156f1b6117", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2025-04-14T07:01:06.786016Z", + "start_time": "2025-04-14T07:01:06.779812Z" + } + }, + "cell_type": "code", + "source": [ + "# 整理特征\n", + "data_by_group = defaultdict(list)\n", + "for vid, arr, group, path in all_data:\n", + " data_by_group[group].append({'id': vid, 'feature': arr, 'path': path})\n", + "\n", + "# 相似度函数 (余弦相似度)\n", + "def cosine_similarity(a, b):\n", + " return np.dot(a, b) / (norm(a) * norm(b))\n", + "\n", + "# 计算指标函数\n", + "def compute_metrics(org_feats, query_feats, sim_feats, K=5):\n", + " precision_top1 = []\n", + " recall_at_k = []\n", + " AP_list = []\n", + "\n", + " # 构建搜索库 (原始视频 + 相似视频)\n", + " search_db = org_feats + sim_feats\n", + "\n", + " for query in query_feats:\n", + " similarities = []\n", + " query_feature = query['feature']\n", + "\n", + " # 计算query与所有库视频的相似度\n", + " for target in search_db:\n", + " sim = cosine_similarity(query_feature, target['feature'])\n", + " label = 1 if target in org_feats else 0 # 1代表匹配,0代表不匹配\n", + " similarities.append((sim, label))\n", + "\n", + " # 相似度降序排序\n", + " similarities.sort(key=lambda x: x[0], reverse=True)\n", + " labels_sorted = [label for _, label in similarities]\n", + "\n", + " # Top-1 precision\n", + " precision_top1.append(labels_sorted[0])\n", + "\n", + " # Recall@K\n", + " recall = sum(labels_sorted[:K]) / len(org_feats)\n", + " recall_at_k.append(recall)\n", + "\n", + " # Average Precision (AP)\n", + " hits, sum_precisions = 0, 0\n", + " for idx, label in enumerate(labels_sorted, start=1):\n", + " if label == 1:\n", + " hits += 1\n", + " sum_precisions += hits / idx\n", + " AP = sum_precisions / len(org_feats) if len(org_feats) else 0\n", + " AP_list.append(AP)\n", + "\n", + " # 返回指标均值\n", + " return {\n", + " 'Top-1 Precision': np.mean(precision_top1),\n", + " f'Recall@{K}': np.mean(recall_at_k),\n", + " 'MAP': np.mean(AP_list)\n", + " }" + ], + "id": "initial_id", + "outputs": [], + "execution_count": 14 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T07:01:07.745386Z", + "start_time": "2025-04-14T07:01:07.740942Z" + } + }, + "cell_type": "code", + "source": "data_by_group['org'][0]['feature'].shape", + "id": "55e57dc7ec56b732", + "outputs": [ + { + "data": { + "text/plain": [ + "(2304,)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 15 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T06:00:12.392784Z", + "start_time": "2025-04-14T06:00:12.382725Z" + } + }, + "cell_type": "code", + "source": [ + "# 主函数,计算所有变形组的指标\n", + "def evaluate_all_variants(K=5):\n", + " org_feats = data_by_group['org']\n", + " sim_feats = data_by_group['sim']\n", + "\n", + " results = {}\n", + "\n", + " # 排除 'org' 和 'sim',其余都是变形组\n", + " variant_groups = [group for group in data_by_group if group not in ['org', 'sim']]\n", + "\n", + " for variant in variant_groups:\n", + " variant_feats = data_by_group[variant]\n", + " metrics = compute_metrics(org_feats, variant_feats, sim_feats, K)\n", + " results[variant] = metrics\n", + "\n", + " return results\n", + "\n", + "# 执行评估\n", + "results = evaluate_all_variants(K=3)\n", + "\n", + "# 输出结果\n", + "for variant, metrics in results.items():\n", + " print(f\"变形组: {variant}\")\n", + " for metric_name, value in metrics.items():\n", + " print(f\" {metric_name}: {value:.4f}\")\n", + " print(\"-\" * 40)\n", + "\n", + "# 关闭数据库连接\n", + "conn.close()" + ], + "id": "d9a0103dbc3f1bef", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "变形组: 动态水印2\n", + " Top-1 Precision: 1.0000\n", + " Recall@3: 0.1500\n", + " MAP: 0.5815\n", + "----------------------------------------\n", + "变形组: 水印1+2\n", + " Top-1 Precision: 0.8000\n", + " Recall@3: 0.1600\n", + " MAP: 0.5751\n", + "----------------------------------------\n", + "变形组: 水印1+2+滤镜\n", + " Top-1 Precision: 0.8000\n", + " Recall@3: 0.1500\n", + " MAP: 0.5685\n", + "----------------------------------------\n", + "变形组: 滤镜\n", + " Top-1 Precision: 0.9000\n", + " Recall@3: 0.1800\n", + " MAP: 0.6100\n", + "----------------------------------------\n", + "变形组: 静态水印1\n", + " Top-1 Precision: 0.9000\n", + " Recall@3: 0.1700\n", + " MAP: 0.6058\n", + "----------------------------------------\n" + ] + } + ], + "execution_count": 25 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/i3d.db b/i3d.db new file mode 100644 index 0000000..540a0b5 Binary files /dev/null and b/i3d.db differ diff --git a/i3d.ipynb b/i3d.ipynb new file mode 100644 index 0000000..084d458 --- /dev/null +++ b/i3d.ipynb @@ -0,0 +1,279 @@ +{ + "cells": [ + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:58:08.619189Z", + "start_time": "2025-04-14T03:58:08.616451Z" + } + }, + "cell_type": "code", + "source": [ + "import torch\n", + "import torch.nn.functional as F\n", + "import torchvision.transforms as transforms\n", + "from pytorchvideo.models.hub import i3d_r50\n", + "import cv2\n", + "import numpy as np\n", + "from PIL import Image" + ], + "id": "79af3e0bb61c3290", + "outputs": [], + "execution_count": 5 + }, + { + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2025-04-14T03:58:09.075199Z", + "start_time": "2025-04-14T03:58:08.635303Z" + } + }, + "cell_type": "code", + "source": [ + "# 初始化预训练I3D模型\n", + "model = i3d_r50(pretrained=True).eval()\n", + "feature_extractor = torch.nn.Sequential(*model.blocks[:-1])" + ], + "id": "initial_id", + "outputs": [], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:58:09.118627Z", + "start_time": "2025-04-14T03:58:09.113363Z" + } + }, + "cell_type": "code", + "source": [ + "def preprocess_video(video_path, num_frames=32, size=224):\n", + " cap = cv2.VideoCapture(video_path)\n", + " frames = []\n", + " transform = transforms.Compose([\n", + " transforms.Resize((size, size)),\n", + " transforms.ToTensor(),\n", + " transforms.Normalize(mean=[0.45, 0.45, 0.45], std=[0.225, 0.225, 0.225])\n", + " ])\n", + "\n", + " total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n", + " frame_indices = np.linspace(0, total_frames - 1, num_frames).astype(int)\n", + "\n", + " for i in frame_indices:\n", + " cap.set(cv2.CAP_PROP_POS_FRAMES, i)\n", + " ret, frame = cap.read()\n", + " if not ret:\n", + " break\n", + " frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n", + " frame = Image.fromarray(frame)\n", + " frame = transform(frame)\n", + " frames.append(frame)\n", + "\n", + " cap.release()\n", + " video_tensor = torch.stack(frames).permute(1, 0, 2, 3).unsqueeze(0)\n", + " return video_tensor\n" + ], + "id": "5fd2f80d5947967e", + "outputs": [], + "execution_count": 7 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:58:09.128752Z", + "start_time": "2025-04-14T03:58:09.125636Z" + } + }, + "cell_type": "code", + "source": [ + "def extract_features(video_tensor):\n", + " with torch.no_grad():\n", + " features = feature_extractor(video_tensor)\n", + " features = F.adaptive_avg_pool3d(features, 1)\n", + " features = features.flatten()\n", + " return features.numpy()" + ], + "id": "728a0b9ece5bdc06", + "outputs": [], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:58:09.142606Z", + "start_time": "2025-04-14T03:58:09.138924Z" + } + }, + "cell_type": "code", + "source": [ + "def video_features(video_path):\n", + " video_tensor = preprocess_video(video_path)\n", + " features = extract_features(video_tensor)\n", + " return features" + ], + "id": "60ca6ade121d00af", + "outputs": [], + "execution_count": 9 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:58:09.156458Z", + "start_time": "2025-04-14T03:58:09.152546Z" + } + }, + "cell_type": "code", + "source": [ + "def getFeature(video_path = r\"D:\\DESKTOP\\2025\\44\\a1\\dataset\\org\\1.mp4\"):\n", + "\n", + " feature = video_features(video_path)\n", + " # print(\"Video feature shape (for copyright):\", feature.shape)\n", + " return feature" + ], + "id": "5c3f6ede68d0f22f", + "outputs": [], + "execution_count": 10 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:58:09.206798Z", + "start_time": "2025-04-14T03:58:09.166673Z" + } + }, + "cell_type": "code", + "source": [ + "import sqlite3\n", + "import io\n", + "import os\n", + "import tqdm\n", + "\n", + "# 注册适配器与转换器:numpy数组 <-> BLOB\n", + "def adapt_array(arr):\n", + " out = io.BytesIO()\n", + " np.save(out, arr)\n", + " out.seek(0)\n", + " return sqlite3.Binary(out.read())\n", + "\n", + "def convert_array(text):\n", + " out = io.BytesIO(text)\n", + " out.seek(0)\n", + " return np.load(out)\n", + "\n", + "# 注册自定义类型处理\n", + "sqlite3.register_adapter(np.ndarray, adapt_array)\n", + "sqlite3.register_converter(\"array\", convert_array)\n", + "\n", + "# 创建数据库连接(带类型检测)\n", + "conn = sqlite3.connect(\"i3d.db\", detect_types=sqlite3.PARSE_DECLTYPES)\n", + "cursor = conn.cursor()\n", + "\n", + "# 创建表\n", + "cursor.execute(\"\"\"\n", + "CREATE TABLE IF NOT EXISTS data (\n", + " id INTEGER PRIMARY KEY,\n", + " array BLOB,\n", + " group_path TEXT,\n", + " full_path TEXT\n", + ")\n", + "\"\"\")\n", + "\n", + "\n", + "def add_to_db(array_to_store,group_path,full_path):\n", + " cursor.execute(\"INSERT INTO data (array,group_path,full_path) VALUES (?,?,?)\", (array_to_store,group_path,full_path,))\n", + " conn.commit()\n", + "\n", + "# # 读取数组\n", + "# cursor.execute(\"SELECT array FROM data WHERE id=1\")\n", + "# fetched_array = cursor.fetchone()[0]\n", + "#\n", + "# print(\"原始数组:\\n\", array_to_store)\n", + "# print(\"读取的数组:\\n\", fetched_array)\n", + "\n", + "folder_path = r\"D:\\DESKTOP\\2025\\44\\a1\\dataset\"\n", + "\n", + "all_files = []\n", + "names = [str(x)+\".mp4\" for x in range(10)]\n", + "print(names)\n", + "\n", + "\n", + "# 遍历文件夹\n", + "for group_path in os.listdir(folder_path):\n", + " full_path = os.path.join(folder_path, group_path)\n", + " if os.path.isdir(full_path):\n", + " # 遍历子文件夹\n", + " for video_path in os.listdir(full_path):\n", + " if os.path.basename(video_path) in names:\n", + " video_full_path = os.path.join(full_path, video_path)\n", + " if os.path.isfile(video_full_path):\n", + " # 处理视频文件\n", + " all_files.append((group_path,video_full_path))\n", + "print(len(all_files))\n" + ], + "id": "517f4d3e7e8d4402", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['0.mp4', '1.mp4', '2.mp4', '3.mp4', '4.mp4', '5.mp4', '6.mp4', '7.mp4', '8.mp4', '9.mp4']\n", + "70\n" + ] + } + ], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:59:48.339352Z", + "start_time": "2025-04-14T03:58:09.217915Z" + } + }, + "cell_type": "code", + "source": [ + "for group_path, video_full_path in tqdm.tqdm(all_files):\n", + " # 读取视频特征\n", + " feature = getFeature(video_full_path)\n", + " # 将特征存储到数据库\n", + " add_to_db(feature,group_path,video_full_path)\n", + " # print(f\"已处理并存储: {video_full_path}\")\n", + "\n", + "conn.close()\n" + ], + "id": "aa7bdb735dbc1e1e", + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 70/70 [01:39<00:00, 1.42s/it]\n" + ] + } + ], + "execution_count": 12 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6edb569 Binary files /dev/null and b/requirements.txt differ diff --git a/slowFast.ipynb b/slowFast.ipynb new file mode 100644 index 0000000..a2a9165 --- /dev/null +++ b/slowFast.ipynb @@ -0,0 +1,357 @@ +{ + "cells": [ + { + "cell_type": "code", + "id": "initial_id", + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2025-04-14T03:41:10.176744Z", + "start_time": "2025-04-14T03:41:08.344955Z" + } + }, + "source": [ + "import torch\n", + "import numpy as np\n", + "import cv2\n", + "from decord import VideoReader, cpu" + ], + "outputs": [], + "execution_count": 1 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:10.726870Z", + "start_time": "2025-04-14T03:41:10.181751Z" + } + }, + "cell_type": "code", + "source": [ + "print(torch.__version__)\n", + "print(torch.cuda.is_available())" + ], + "id": "31d50e0f9e4ea204", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.6.0+cu124\n", + "True\n" + ] + } + ], + "execution_count": 2 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:10.875039Z", + "start_time": "2025-04-14T03:41:10.871492Z" + } + }, + "cell_type": "code", + "source": [ + "def load_first_480_frames(video_path, resize=(224, 224)):\n", + " vr = VideoReader(video_path, ctx=cpu(0))\n", + " total_frames = len(vr)\n", + "\n", + " if total_frames < 480:\n", + " raise ValueError(f\"{video_path},视频帧数不足 480 帧\")\n", + "\n", + " indices = list(range(480))\n", + " frames = vr.get_batch(indices).asnumpy()\n", + "\n", + " if resize:\n", + " frames = np.array([cv2.resize(f, resize) for f in frames])\n", + " return frames" + ], + "id": "e351cfd29d48331a", + "outputs": [], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:10.884466Z", + "start_time": "2025-04-14T03:41:10.880516Z" + } + }, + "cell_type": "code", + "source": [ + "def preprocess_for_slowfast(frames, num_frames=32, alpha=4):\n", + " total = len(frames)\n", + " indices = np.linspace(0, total - 1, num=num_frames, dtype=int)\n", + " frames = frames[indices]\n", + "\n", + " frames = frames / 255.0\n", + " frames = (frames - [0.45, 0.45, 0.45]) / [0.225, 0.225, 0.225]\n", + " frames = frames.astype(np.float32)\n", + "\n", + " frames = torch.from_numpy(frames).permute(3, 0, 1, 2).unsqueeze(0)\n", + "\n", + " fast_pathway = frames\n", + " slow_pathway = frames[:, :, ::alpha, :, :]\n", + "\n", + " return [slow_pathway, fast_pathway]" + ], + "id": "f8784f81a946176", + "outputs": [], + "execution_count": 4 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:10.893723Z", + "start_time": "2025-04-14T03:41:10.890080Z" + } + }, + "cell_type": "code", + "source": [ + "# 定义特征提取模型 (SlowFast Backbone)\n", + "class SlowFastFeatureExtractor(torch.nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " model = torch.hub.load(\"facebookresearch/pytorchvideo\", \"slowfast_r50\", pretrained=True)\n", + " # 移除分类头,仅保留backbone部分\n", + " self.blocks = model.blocks[:-1] # 去掉最后的分类器 head\n", + " self.pool = torch.nn.AdaptiveAvgPool3d(1) # 全局池化\n", + "\n", + " def forward(self, x):\n", + " for block in self.blocks:\n", + " x = block(x)\n", + " x = self.pool(x)\n", + " x = torch.flatten(x, 1) # [B, C]\n", + " x = torch.nn.functional.normalize(x, dim=1) # 特征归一化\n", + " return x" + ], + "id": "6c52b60b3399c5b7", + "outputs": [], + "execution_count": 5 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:13.527271Z", + "start_time": "2025-04-14T03:41:10.899167Z" + } + }, + "cell_type": "code", + "source": [ + "\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "print(\"Loading SlowFast backbone for feature extraction...\")\n", + "model = SlowFastFeatureExtractor().to(device).eval()\n", + "\n", + "\n", + "def extract_video_feature(video_path):\n", + "\n", + "\n", + " frames = load_first_480_frames(video_path)\n", + " inputs = preprocess_for_slowfast(frames, num_frames=32, alpha=4)\n", + "\n", + " with torch.no_grad():\n", + " inputs = [x.to(device) for x in inputs]\n", + " features = model(inputs)\n", + "\n", + " features = features.cpu().numpy().squeeze()\n", + " return features" + ], + "id": "d841190cdd5ee920", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading SlowFast backbone for feature extraction...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using cache found in C:\\Users\\zikai/.cache\\torch\\hub\\facebookresearch_pytorchvideo_main\n" + ] + } + ], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:13.545015Z", + "start_time": "2025-04-14T03:41:13.541939Z" + } + }, + "cell_type": "code", + "source": [ + "def getFeature(video_path = r\"D:\\DESKTOP\\2025\\44\\a1\\dataset\\org\\1.mp4\"):\n", + "\n", + " feature = extract_video_feature(video_path)\n", + " # print(\"Video feature shape (for copyright):\", feature.shape)\n", + " return feature" + ], + "id": "dce706080dfba5b6", + "outputs": [], + "execution_count": 7 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:41:13.607891Z", + "start_time": "2025-04-14T03:41:13.554129Z" + } + }, + "cell_type": "code", + "source": [ + "import sqlite3\n", + "import io\n", + "import os\n", + "import tqdm\n", + "\n", + "# 注册适配器与转换器:numpy数组 <-> BLOB\n", + "def adapt_array(arr):\n", + " out = io.BytesIO()\n", + " np.save(out, arr)\n", + " out.seek(0)\n", + " return sqlite3.Binary(out.read())\n", + "\n", + "def convert_array(text):\n", + " out = io.BytesIO(text)\n", + " out.seek(0)\n", + " return np.load(out)\n", + "\n", + "# 注册自定义类型处理\n", + "sqlite3.register_adapter(np.ndarray, adapt_array)\n", + "sqlite3.register_converter(\"array\", convert_array)\n", + "\n", + "# 创建数据库连接(带类型检测)\n", + "conn = sqlite3.connect(\"slowfast.db\", detect_types=sqlite3.PARSE_DECLTYPES)\n", + "cursor = conn.cursor()\n", + "\n", + "# 创建表\n", + "cursor.execute(\"\"\"\n", + "CREATE TABLE IF NOT EXISTS data (\n", + " id INTEGER PRIMARY KEY,\n", + " array BLOB,\n", + " group_path TEXT,\n", + " full_path TEXT\n", + ")\n", + "\"\"\")\n", + "\n", + "\n", + "def add_to_db(array_to_store,group_path,full_path):\n", + " cursor.execute(\"INSERT INTO data (array,group_path,full_path) VALUES (?,?,?)\", (array_to_store,group_path,full_path,))\n", + " conn.commit()\n", + "\n", + "# # 读取数组\n", + "# cursor.execute(\"SELECT array FROM data WHERE id=1\")\n", + "# fetched_array = cursor.fetchone()[0]\n", + "#\n", + "# print(\"原始数组:\\n\", array_to_store)\n", + "# print(\"读取的数组:\\n\", fetched_array)\n", + "\n", + "folder_path = r\"D:\\DESKTOP\\2025\\44\\a1\\dataset\"\n", + "\n", + "all_files = []\n", + "names = [str(x)+\".mp4\" for x in range(10)]\n", + "print(names)\n", + "\n", + "\n", + "# 遍历文件夹\n", + "for group_path in os.listdir(folder_path):\n", + " full_path = os.path.join(folder_path, group_path)\n", + " if os.path.isdir(full_path):\n", + " # 遍历子文件夹\n", + " for video_path in os.listdir(full_path):\n", + " if os.path.basename(video_path) in names:\n", + " video_full_path = os.path.join(full_path, video_path)\n", + " if os.path.isfile(video_full_path):\n", + " # 处理视频文件\n", + " all_files.append((group_path,video_full_path))\n", + "print(len(all_files))\n" + ], + "id": "dcf5af026d672b41", + "outputs": [], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:42:00.157934Z", + "start_time": "2025-04-14T03:41:13.633220Z" + } + }, + "cell_type": "code", + "source": [ + "for group_path, video_full_path in tqdm.tqdm(all_files):\n", + " # 读取视频特征\n", + " feature = getFeature(video_full_path)\n", + " # 将特征存储到数据库\n", + " add_to_db(feature,group_path,video_full_path)\n", + " # print(f\"已处理并存储: {video_full_path}\")\n", + "\n", + "conn.close()\n" + ], + "id": "63eed21338e8f26c", + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 70/70 [00:46<00:00, 1.50it/s]\n" + ] + } + ], + "execution_count": 10 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:42:00.170765Z", + "start_time": "2025-04-14T03:42:00.167606Z" + } + }, + "cell_type": "code", + "source": "", + "id": "d8a84ff72bc12b33", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-04-14T03:42:00.184252Z", + "start_time": "2025-04-14T03:42:00.181880Z" + } + }, + "cell_type": "code", + "source": "", + "id": "7343d8b3fcea327c", + "outputs": [], + "execution_count": null + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/slowFast.py b/slowFast.py new file mode 100644 index 0000000..5f6da92 --- /dev/null +++ b/slowFast.py @@ -0,0 +1,159 @@ +#%% +import torch +import numpy as np +import cv2 +from decord import VideoReader, cpu +#%% +print(torch.__version__) +print(torch.cuda.is_available()) +#%% +def load_first_480_frames(video_path, resize=(224, 224)): + vr = VideoReader(video_path, ctx=cpu(0)) + total_frames = len(vr) + + if total_frames < 480: + raise ValueError(f"{video_path},视频帧数不足 480 帧") + + indices = list(range(480)) + frames = vr.get_batch(indices).asnumpy() + + if resize: + frames = np.array([cv2.resize(f, resize) for f in frames]) + return frames +#%% +def preprocess_for_slowfast(frames, num_frames=32, alpha=4): + total = len(frames) + indices = np.linspace(0, total - 1, num=num_frames, dtype=int) + frames = frames[indices] + + frames = frames / 255.0 + frames = (frames - [0.45, 0.45, 0.45]) / [0.225, 0.225, 0.225] + frames = frames.astype(np.float32) + + frames = torch.from_numpy(frames).permute(3, 0, 1, 2).unsqueeze(0) + + fast_pathway = frames + slow_pathway = frames[:, :, ::alpha, :, :] + + return [slow_pathway, fast_pathway] +#%% +# 定义特征提取模型 (SlowFast Backbone) +class SlowFastFeatureExtractor(torch.nn.Module): + def __init__(self): + super().__init__() + model = torch.hub.load("facebookresearch/pytorchvideo", "slowfast_r50", pretrained=True) + # 移除分类头,仅保留backbone部分 + self.blocks = model.blocks[:-1] # 去掉最后的分类器 head + self.pool = torch.nn.AdaptiveAvgPool3d(1) # 全局池化 + + def forward(self, x): + for block in self.blocks: + x = block(x) + x = self.pool(x) + x = torch.flatten(x, 1) # [B, C] + x = torch.nn.functional.normalize(x, dim=1) # 特征归一化 + return x +#%% + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +print("Loading SlowFast backbone for feature extraction...") +model = SlowFastFeatureExtractor().to(device).eval() + + +def extract_video_feature(video_path): + + + frames = load_first_480_frames(video_path) + inputs = preprocess_for_slowfast(frames, num_frames=32, alpha=4) + + with torch.no_grad(): + inputs = [x.to(device) for x in inputs] + features = model(inputs) + + features = features.cpu().numpy().squeeze() + return features +#%% +def getFeature(video_path = r"D:\DESKTOP\2025\44\a1\dataset\org\1.mp4"): + + feature = extract_video_feature(video_path) + # print("Video feature shape (for copyright):", feature.shape) + return feature +#%% +import sqlite3 +import io +import os +import tqdm + +# 注册适配器与转换器:numpy数组 <-> BLOB +def adapt_array(arr): + out = io.BytesIO() + np.save(out, arr) + out.seek(0) + return sqlite3.Binary(out.read()) + +def convert_array(text): + out = io.BytesIO(text) + out.seek(0) + return np.load(out) + +# 注册自定义类型处理 +sqlite3.register_adapter(np.ndarray, adapt_array) +sqlite3.register_converter("array", convert_array) + +# 创建数据库连接(带类型检测) +conn = sqlite3.connect("slowfast.db", detect_types=sqlite3.PARSE_DECLTYPES) +cursor = conn.cursor() + +# 创建表 +cursor.execute(""" +CREATE TABLE IF NOT EXISTS data ( + id INTEGER PRIMARY KEY, + array BLOB, + group_path TEXT, + full_path TEXT +) +""") + + +def add_to_db(array_to_store,group_path,full_path): + cursor.execute("INSERT INTO data (array,group_path,full_path) VALUES (?,?,?)", (array_to_store,group_path,full_path,)) + conn.commit() + +# # 读取数组 +# cursor.execute("SELECT array FROM data WHERE id=1") +# fetched_array = cursor.fetchone()[0] +# +# print("原始数组:\n", array_to_store) +# print("读取的数组:\n", fetched_array) + + +#%% +folder_path = r"D:\DESKTOP\2025\44\a1\dataset" + +all_files = [] +names = [str(x)+".mp4" for x in range(10)] +print(names) + + +# 遍历文件夹 +for group_path in os.listdir(folder_path): + full_path = os.path.join(folder_path, group_path) + if os.path.isdir(full_path): + # 遍历子文件夹 + for video_path in os.listdir(full_path): + if os.path.basename(video_path) in names: + video_full_path = os.path.join(full_path, video_path) + if os.path.isfile(video_full_path): + # 处理视频文件 + all_files.append((group_path,video_full_path)) +print(len(all_files)) +#%% +for group_path, video_full_path in tqdm.tqdm(all_files): + # 读取视频特征 + feature = getFeature(video_full_path) + # 将特征存储到数据库 + add_to_db(feature,group_path,video_full_path) + # print(f"已处理并存储: {video_full_path}") +#%% +conn.close() +#%% diff --git a/slowfast.db b/slowfast.db new file mode 100644 index 0000000..0ddc13a Binary files /dev/null and b/slowfast.db differ