{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "52685911", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m12.3/12.3 MB\u001b[0m \u001b[31m100.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m0:01\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m394.3/394.3 kB\u001b[0m \u001b[31m45.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m43.1/43.1 MB\u001b[0m \u001b[31m20.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m:00:01\u001b[0m00:01\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.4/3.4 MB\u001b[0m \u001b[31m106.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m35.8/35.8 MB\u001b[0m \u001b[31m30.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m:00:01\u001b[0m00:01\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.6/13.6 MB\u001b[0m \u001b[31m110.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", "\u001b[?25h✅ 环境安装完成\n" ] } ], "source": [ "# ============================================================\n", "# 代码块 1:环境安装\n", "# ============================================================\n", "!pip install -U transformers accelerate qwen-vl-utils[decord] bitsandbytes -q\n", "!pip install -U torch torchvision --index-url https://download.pytorch.org/whl/cu124 -q # 根据你的CUDA版本调整\n", "\n", "import os\n", "os.environ[\"PYTORCH_CUDA_ALLOC_CONF\"] = \"expandable_segments:True,max_split_size_mb:128\"\n", "print(\"✅ 环境安装完成\")" ] }, { "cell_type": "code", "execution_count": null, "id": "70fffa36", "metadata": {}, "outputs": [], "source": [ "from huggingface_hub import login\n", "\n", "login(token=\"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\") " ] }, { "cell_type": "code", "execution_count": 2, "id": "f6914f9a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--2026-09-11 02:40:28-- http://172.245.243.238:8000/test02.mp4\n", "Connecting to 172.245.243.238:8000... connected.\n", "HTTP request sent, awaiting response... 200 OK\n", "Length: 30270635 (29M) [video/mp4]\n", "Saving to: ‘test02.mp4’\n", "\n", "test02.mp4 0%[ ] 0 --.-KB/s " ] }, { "name": "stdout", "output_type": "stream", "text": [ "test02.mp4 100%[===================>] 28.87M 55.1MB/s in 0.5s \n", "\n", "2026-09-11 02:40:29 (55.1 MB/s) - ‘test02.mp4’ saved [30270635/30270635]\n", "\n", "--2026-09-11 02:40:29-- http://172.245.243.238:8000/test03.mp4\n", "Connecting to 172.245.243.238:8000... connected.\n", "HTTP request sent, awaiting response... 200 OK\n", "Length: 13549203 (13M) [video/mp4]\n", "Saving to: ‘test03.mp4’\n", "\n", "test03.mp4 100%[===================>] 12.92M 35.6MB/s in 0.4s \n", "\n", "2026-09-11 02:40:30 (35.6 MB/s) - ‘test03.mp4’ saved [13549203/13549203]\n", "\n", "--2026-09-11 02:40:30-- http://172.245.243.238:8000/test04.mp4\n", "Connecting to 172.245.243.238:8000... connected.\n", "HTTP request sent, awaiting response... 200 OK\n", "Length: 27143071 (26M) [video/mp4]\n", "Saving to: ‘test04.mp4’\n", "\n", "test04.mp4 100%[===================>] 25.88M 53.0MB/s in 0.5s \n", "\n", "2026-09-11 02:40:30 (53.0 MB/s) - ‘test04.mp4’ saved [27143071/27143071]\n", "\n", "--2026-09-11 02:40:30-- http://172.245.243.238:8000/test05.mp4\n", "Connecting to 172.245.243.238:8000... connected.\n", "HTTP request sent, awaiting response... 200 OK\n", "Length: 36972551 (35M) [video/mp4]\n", "Saving to: ‘test05.mp4’\n", "\n", "test05.mp4 100%[===================>] 35.26M 41.0MB/s in 0.9s \n", "\n", "2026-09-11 02:40:31 (41.0 MB/s) - ‘test05.mp4’ saved [36972551/36972551]\n", "\n" ] } ], "source": [ "!wget http://172.245.243.238:8000/test02.mp4\n", "!wget http://172.245.243.238:8000/test03.mp4\n", "!wget http://172.245.243.238:8000/test04.mp4\n", "!wget http://172.245.243.238:8000/test05.mp4" ] }, { "cell_type": "code", "execution_count": 3, "id": "9622b9f4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "============================================================\n", "正在加载 Qwen3-VL-8B-Instruct(4-bit 量化)...\n", "============================================================\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/huggingface_hub/utils/_auth.py:138: UserWarning: \n", "Error while fetching `HF_TOKEN` secret value from your vault: 'Requesting secret HF_TOKEN timed out. Secrets can only be fetched when running from the Colab UI.'.\n", " warnings.warn(f\"\\nError while fetching `HF_TOKEN` secret value from your vault: '{str(e)}'.\")\n", "Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n", "WARNING:huggingface_hub.utils._http:Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "63e98862b6b141e7a4dd379c25c51af9", "version_major": 2, "version_minor": 0 }, "text/plain": [ "config.json: 0%| | 0.00/1.47k [00:00 max_change:\n", " delta = max(-max_change, min(max_change, delta))\n", " current_count = previous_count + delta\n", " \n", " colors = data.get(\"colors\", [])\n", " if not isinstance(colors, list):\n", " colors = []\n", " \n", " try:\n", " occupancy = int(round(float(data.get(\"occupancy\", 0))))\n", " except:\n", " occupancy = 0\n", " occupancy = max(0, min(100, occupancy))\n", " \n", " try:\n", " confidence = float(data.get(\"confidence\", 0.5))\n", " except:\n", " confidence = 0.5\n", " \n", " return {\n", " \"delta\": delta,\n", " \"current_count\": current_count,\n", " \"colors\": colors,\n", " \"occupancy\": occupancy,\n", " \"confidence\": confidence\n", " }\n", "\n", "@torch.inference_mode()\n", "def analyze_one_clip(clip_path, prompt_text, max_pixels=360*420, fps=1.0, max_new_tokens=180):\n", " messages = [\n", " {\n", " \"role\": \"user\",\n", " \"content\": [\n", " {\n", " \"type\": \"video\",\n", " \"video\": str(clip_path),\n", " \"max_pixels\": max_pixels,\n", " \"fps\": fps,\n", " },\n", " {\"type\": \"text\", \"text\": prompt_text},\n", " ],\n", " }\n", " ]\n", " \n", " text = processor.apply_chat_template(\n", " messages, tokenize=False, add_generation_prompt=True\n", " )\n", " \n", " image_inputs, video_inputs, video_kwargs = process_vision_info(\n", " messages, return_video_kwargs=True\n", " )\n", " \n", " # inputs = processor(\n", " # text=[text],\n", " # images=image_inputs,\n", " # videos=video_inputs,\n", " # padding=True,\n", " # return_tensors=\"pt\",\n", " # **video_kwargs,\n", " # )\n", "\n", " # qwen-vl-utils 某些版本会把 fps 返回成 [xxx],\n", " # 而 Qwen3-VL processor 要求 fps 为 float/int。\n", " video_kwargs.pop(\"fps\", None)\n", "\n", " inputs = processor(\n", " text=[text],\n", " images=image_inputs,\n", " videos=video_inputs,\n", " padding=True,\n", " return_tensors=\"pt\",\n", " **video_kwargs,\n", " )\n", "\n", " inputs = inputs.to(DEVICE)\n", " \n", " generated_ids = model.generate(\n", " **inputs,\n", " max_new_tokens=max_new_tokens,\n", " do_sample=False,\n", " )\n", " \n", " generated_ids_trimmed = [\n", " out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)\n", " ]\n", " output_text = processor.batch_decode(\n", " generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False\n", " )[0]\n", " \n", " cleanup(inputs, generated_ids)\n", " return output_text.strip()\n", "\n", "def run_analysis(\n", " video_path=\"/content/test02.mp4\",\n", " segment_sec=1.5,\n", " max_pixels=360*420,\n", " fps=1.0,\n", " max_new_tokens=180,\n", " show_raw=True\n", "):\n", " path = Path(video_path)\n", " if not path.exists():\n", " raise FileNotFoundError(f\"视频不存在: {video_path}\")\n", " \n", " total = duration(path)\n", " if total <= 0:\n", " raise RuntimeError(\"无法获取视频时长\")\n", " \n", " clip_dir = Path(\"/tmp/qwen3_clips\")\n", " clip_dir.mkdir(parents=True, exist_ok=True)\n", " \n", " previous_count = 0\n", " previous_colors = []\n", " history = []\n", " results = []\n", " start = 0.0\n", " index = 0\n", " \n", " PROMPT_TEMPLATE = \"\"\"你是一个高精度的洗衣机滚筒衣物检测专家。\n", "\n", "【任务】\n", "仔细观察当前视频片段,完成以下判断:\n", "1. 当前滚筒内总共能看到几件独立的衣物?(即使折叠、有花纹、部分遮挡也要分别计数)\n", "2. 这些衣物的主要颜色是什么?\n", "3. 衣物大约占滚筒可见空间的百分比?\n", "4. 与上一时刻相比,是增加了还是减少了?\n", "\n", "【特别注意】\n", "- 手伸进滚筒拿衣服、把衣服往外拉,都算“取出”。\n", "- 把衣服推进滚筒、松手放下,都算“放入”。\n", "- 一件有花纹或格纹的衣服只算1件。\n", "- 白色印花T恤、灰色长袖、棕色衣物、黑白格纹衬衫、浅灰花纹布都是不同的独立衣物。\n", "- 优先报告你看到的绝对数量(current_count)。\n", "\n", "【上一时刻状态】\n", "数量:{previous_count}\n", "颜色:{previous_colors}\n", "\n", "【输出要求(只输出纯JSON)】\n", "{{\n", " \"current_count\": 当前滚筒内可见的衣物总件数(整数),\n", " \"delta\": 当前数量减去上一时刻数量,\n", " \"colors\": [\"颜色1\", \"颜色2\", ...],\n", " \"occupancy\": 0-100的整数,\n", " \"confidence\": 0到1的小数\n", "}}\"\"\"\n", "\n", " print(f\"\\n开始分析 | 视频={path.name} | 时长={total:.1f}s | 窗口={segment_sec}s | 模型=Qwen3-VL-8B\")\n", " print(\"-\" * 60)\n", " \n", " while start < total - 0.05:\n", " end = min(total, start + segment_sec)\n", " length = end - start\n", " \n", " if length < 0.4:\n", " print(f\"**{start:.1f}–{end:.1f}s** → ⚠️ 片段过短,跳过\")\n", " start = end\n", " continue\n", " \n", " index += 1\n", " t0 = time.time()\n", " clip = clip_dir / f\"{path.stem}_{index:04d}_{start:.1f}_{end:.1f}.mp4\"\n", " \n", " try:\n", " extract_clip(path, start, length, clip)\n", " \n", " prompt = PROMPT_TEMPLATE.format(\n", " previous_count=previous_count,\n", " previous_colors=\", \".join(previous_colors) if previous_colors else \"暂无\"\n", " )\n", " \n", " print(f\"**{start:.1f}–{end:.1f}s** → 🧠 识别中...\")\n", " raw = analyze_one_clip(\n", " clip, prompt, \n", " max_pixels=max_pixels, \n", " fps=fps, \n", " max_new_tokens=max_new_tokens\n", " )\n", " \n", " if show_raw:\n", " print(f\"[raw] {raw}\")\n", " \n", " data = parse_json(raw)\n", " state = normalize_state(data, previous_count)\n", " \n", " previous_count = state[\"current_count\"]\n", " previous_colors = state[\"colors\"]\n", " \n", " change = state[\"delta\"]\n", " if change > 0:\n", " change_text = f\"🟢 放入 {change} 件\"\n", " elif change < 0:\n", " change_text = f\"🔴 取出 {abs(change)} 件\"\n", " else:\n", " change_text = \"⚪ 数量无变化\"\n", " \n", " colors_text = \"、\".join(state[\"colors\"]) if state[\"colors\"] else \"未知\"\n", " elapsed = time.time() - t0\n", " \n", " line = (\n", " f\"**{start:.1f}–{end:.1f}s**\\n\"\n", " f\" {change_text} | 当前数量={state['current_count']}件\\n\"\n", " f\" 颜色={colors_text} | 占用={state['occupancy']}% | 置信度={state['confidence']:.2f}\\n\"\n", " f\" 耗时={elapsed:.2f}s\"\n", " )\n", " results.append(line)\n", " history.append(f\"{start:.1f}-{end:.1f}s:{change_text} → {state['current_count']}件\")\n", " print(line)\n", " \n", " except Exception as e:\n", " print(f\"**{start:.1f}–{end:.1f}s** → ❌ {type(e).__name__}: {e}\")\n", " \n", " finally:\n", " if clip.exists():\n", " try: clip.unlink()\n", " except: pass\n", " start = end\n", " print(f\"[segment {index}] 进度 {start:.1f}/{total:.1f}s | GPU={torch.cuda.memory_allocated()/1024**3:.2f}GB\")\n", " cleanup()\n", " \n", " print(\"\\n\" + \"=\" * 60)\n", " print(\"🧺 最终衣物状态\")\n", " print(\"=\" * 60)\n", " print(f\"【最终数量】 {previous_count} 件\")\n", " print(f\"【最终颜色】 {', '.join(previous_colors) if previous_colors else '未知'}\")\n", " print(\"=\" * 60)\n", " print(f\"✅ 完成,共分析 {index} 个片段\")\n", " \n", " return {\n", " \"final_count\": previous_count, \n", " \"final_colors\": previous_colors, \n", " \"history\": history,\n", " \"results\": results\n", " }" ] }, { "cell_type": "code", "execution_count": 7, "id": "25e29805", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "开始分析 | 视频=test02.mp4 | 时长=14.1s | 窗口=1.5s | 模型=Qwen3-VL-8B\n", "------------------------------------------------------------\n", "**0.0–1.5s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[transformers] Qwen3VL video processing does not apply the per-frame pixel cap the reference implementation (qwen-vl-utils) applies, so some videos cost far more tokens than they would there. In v5.22 the capped behavior will become the default and `cap_pixels_per_frame` will be removed. Pass `cap_pixels_per_frame=True` to adopt the reference behavior now, or `False` to keep the current behavior and silence this warning.\n", "[transformers] Qwen3VL requires frame timestamps to construct prompts, but the `fps` of the input video could not be inferred. Probably `video_metadata` was missing from inputs and you passed pre-sampled frames. Defaulting to `fps=24`. Please provide `video_metadata` for more accurate results.\n", "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 1,\n", " \"delta\": 1,\n", " \"colors\": [\"灰色\"],\n", " \"occupancy\": 30,\n", " \"confidence\": 0.98\n", "}\n", "**0.0–1.5s**\n", " 🟢 放入 1 件 | 当前数量=1件\n", " 颜色=灰色 | 占用=30% | 置信度=0.98\n", " 耗时=25.77s\n", "[segment 1] 进度 1.5/14.1s | GPU=5.95GB\n", "**1.5–3.0s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 1,\n", " \"delta\": 0,\n", " \"colors\": [\"灰色\"],\n", " \"occupancy\": 60,\n", " \"confidence\": 0.98\n", "}\n", "**1.5–3.0s**\n", " ⚪ 数量无变化 | 当前数量=1件\n", " 颜色=灰色 | 占用=60% | 置信度=0.98\n", " 耗时=22.85s\n", "[segment 2] 进度 3.0/14.1s | GPU=5.95GB\n", "**3.0–4.5s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 1,\n", " \"delta\": 0,\n", " \"colors\": [\"灰色\"],\n", " \"occupancy\": 70,\n", " \"confidence\": 0.98\n", "}\n", "**3.0–4.5s**\n", " ⚪ 数量无变化 | 当前数量=1件\n", " 颜色=灰色 | 占用=70% | 置信度=0.98\n", " 耗时=22.92s\n", "[segment 3] 进度 4.5/14.1s | GPU=5.95GB\n", "**4.5–6.0s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 1,\n", " \"delta\": 0,\n", " \"colors\": [\"黑白格纹\"],\n", " \"occupancy\": 80,\n", " \"confidence\": 0.98\n", "}\n", "**4.5–6.0s**\n", " ⚪ 数量无变化 | 当前数量=1件\n", " 颜色=黑白格纹 | 占用=80% | 置信度=0.98\n", " 耗时=23.29s\n", "[segment 4] 进度 6.0/14.1s | GPU=5.95GB\n", "**6.0–7.5s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 2,\n", " \"delta\": 1,\n", " \"colors\": [\"黑白格纹\", \"棕色\"],\n", " \"occupancy\": 70,\n", " \"confidence\": 0.95\n", "}\n", "**6.0–7.5s**\n", " 🟢 放入 1 件 | 当前数量=2件\n", " 颜色=黑白格纹、棕色 | 占用=70% | 置信度=0.95\n", " 耗时=23.42s\n", "[segment 5] 进度 7.5/14.1s | GPU=5.95GB\n", "**7.5–9.0s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 2,\n", " \"delta\": 0,\n", " \"colors\": [\"黑白格纹\", \"白色\"],\n", " \"occupancy\": 75,\n", " \"confidence\": 0.95\n", "}\n", "**7.5–9.0s**\n", " ⚪ 数量无变化 | 当前数量=2件\n", " 颜色=黑白格纹、白色 | 占用=75% | 置信度=0.95\n", " 耗时=23.92s\n", "[segment 6] 进度 9.0/14.1s | GPU=5.95GB\n", "**9.0–10.5s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 2,\n", " \"delta\": 0,\n", " \"colors\": [\"黑白格纹\", \"棕色\"],\n", " \"occupancy\": 80,\n", " \"confidence\": 0.98\n", "}\n", "**9.0–10.5s**\n", " ⚪ 数量无变化 | 当前数量=2件\n", " 颜色=黑白格纹、棕色 | 占用=80% | 置信度=0.98\n", " 耗时=23.91s\n", "[segment 7] 进度 10.5/14.1s | GPU=5.95GB\n", "**10.5–12.0s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 2,\n", " \"delta\": 0,\n", " \"colors\": [\"黑白格纹\", \"棕色\"],\n", " \"occupancy\": 80,\n", " \"confidence\": 0.98\n", "}\n", "**10.5–12.0s**\n", " ⚪ 数量无变化 | 当前数量=2件\n", " 颜色=黑白格纹、棕色 | 占用=80% | 置信度=0.98\n", " 耗时=24.36s\n", "[segment 8] 进度 12.0/14.1s | GPU=5.95GB\n", "**12.0–13.5s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 3,\n", " \"delta\": 1,\n", " \"colors\": [\"灰色\", \"黑色\", \"棕色\"],\n", " \"occupancy\": 80,\n", " \"confidence\": 0.95\n", "}\n", "**12.0–13.5s**\n", " 🟢 放入 1 件 | 当前数量=3件\n", " 颜色=灰色、黑色、棕色 | 占用=80% | 置信度=0.95\n", " 耗时=24.84s\n", "[segment 9] 进度 13.5/14.1s | GPU=5.95GB\n", "**13.5–14.1s** → 🧠 识别中...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.12/dist-packages/bitsandbytes/backends/cuda/ops.py:957: UserWarning: inner dimension (4304) is not aligned for fast kernel with blocksize=64, falling back to slower implementation.\n", " warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[raw] {\n", " \"current_count\": 2,\n", " \"delta\": -1,\n", " \"colors\": [\"黑色\", \"灰色\"],\n", " \"occupancy\": 60,\n", " \"confidence\": 0.95\n", "}\n", "**13.5–14.1s**\n", " 🔴 取出 1 件 | 当前数量=2件\n", " 颜色=黑色、灰色 | 占用=60% | 置信度=0.95\n", " 耗时=22.97s\n", "[segment 10] 进度 14.1/14.1s | GPU=5.95GB\n", "\n", "============================================================\n", "🧺 最终衣物状态\n", "============================================================\n", "【最终数量】 2 件\n", "【最终颜色】 黑色, 灰色\n", "============================================================\n", "✅ 完成,共分析 10 个片段\n", "\n", "最终结果摘要:\n", "{'final_count': 2, 'final_colors': ['黑色', '灰色'], 'history': ['0.0-1.5s:🟢 放入 1 件 → 1件', '1.5-3.0s:⚪ 数量无变化 → 1件', '3.0-4.5s:⚪ 数量无变化 → 1件', '4.5-6.0s:⚪ 数量无变化 → 1件', '6.0-7.5s:🟢 放入 1 件 → 2件', '7.5-9.0s:⚪ 数量无变化 → 2件', '9.0-10.5s:⚪ 数量无变化 → 2件', '10.5-12.0s:⚪ 数量无变化 → 2件', '12.0-13.5s:🟢 放入 1 件 → 3件', '13.5-14.1s:🔴 取出 1 件 → 2件'], 'results': ['**0.0–1.5s**\\n 🟢 放入 1 件 | 当前数量=1件\\n 颜色=灰色 | 占用=30% | 置信度=0.98\\n 耗时=25.77s', '**1.5–3.0s**\\n ⚪ 数量无变化 | 当前数量=1件\\n 颜色=灰色 | 占用=60% | 置信度=0.98\\n 耗时=22.85s', '**3.0–4.5s**\\n ⚪ 数量无变化 | 当前数量=1件\\n 颜色=灰色 | 占用=70% | 置信度=0.98\\n 耗时=22.92s', '**4.5–6.0s**\\n ⚪ 数量无变化 | 当前数量=1件\\n 颜色=黑白格纹 | 占用=80% | 置信度=0.98\\n 耗时=23.29s', '**6.0–7.5s**\\n 🟢 放入 1 件 | 当前数量=2件\\n 颜色=黑白格纹、棕色 | 占用=70% | 置信度=0.95\\n 耗时=23.42s', '**7.5–9.0s**\\n ⚪ 数量无变化 | 当前数量=2件\\n 颜色=黑白格纹、白色 | 占用=75% | 置信度=0.95\\n 耗时=23.92s', '**9.0–10.5s**\\n ⚪ 数量无变化 | 当前数量=2件\\n 颜色=黑白格纹、棕色 | 占用=80% | 置信度=0.98\\n 耗时=23.91s', '**10.5–12.0s**\\n ⚪ 数量无变化 | 当前数量=2件\\n 颜色=黑白格纹、棕色 | 占用=80% | 置信度=0.98\\n 耗时=24.36s', '**12.0–13.5s**\\n 🟢 放入 1 件 | 当前数量=3件\\n 颜色=灰色、黑色、棕色 | 占用=80% | 置信度=0.95\\n 耗时=24.84s', '**13.5–14.1s**\\n 🔴 取出 1 件 | 当前数量=2件\\n 颜色=黑色、灰色 | 占用=60% | 置信度=0.95\\n 耗时=22.97s']}\n" ] } ], "source": [ "# ============================================================\n", "# 代码块 4:执行分析\n", "# ============================================================\n", "result = run_analysis(\n", " video_path=\"/content/test02.mp4\", # ← 改成你的视频路径\n", " segment_sec=1.5,\n", " max_pixels=360*420, # 显存紧张保持这个,宽松可调到 480*640\n", " fps=1.0,\n", " max_new_tokens=180,\n", " show_raw=True\n", ")\n", "\n", "print(\"\\n最终结果摘要:\")\n", "print(result)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.13" } }, "nbformat": 4, "nbformat_minor": 5 }