{"metadata":{"kernelspec":{"display_name":"Python 3","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.12"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":127283,"databundleVersionId":15634477,"isSourceIdPinned":false}],"dockerImageVersionId":31328,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q git+https://github.com/openai/CLIP.git","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Imports\n","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load data\n","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/competitions/accident/test_metadata.csv\")\nprint(\"Shape:\", df.shape)\n\ndf.head()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Temporal Detection\n","metadata":{}},{"cell_type":"code","source":"def compute_motion(video_path, max_frames=300):\n    cap = cv2.VideoCapture(video_path)\n    ret, prev = cap.read()\n\n    if not ret:\n        return None, None\n\n    prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)\n    motions = []\n    fps = cap.get(cv2.CAP_PROP_FPS)\n\n    while True:\n        ret, frame = cap.read()\n        if not ret or len(motions) >= max_frames:\n            break\n\n        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n        diff = cv2.absdiff(prev_gray, gray)\n        motions.append(diff.mean())\n        prev_gray = gray\n\n    cap.release()\n    return np.array(motions), fps\n\n\ndef smooth(x, k=7):\n    return np.convolve(x, np.ones(k) / k, mode=\"same\")\n\n\ndef detect_time(motions):\n    if motions is None or len(motions) < 10:\n        return None\n\n    n = len(motions)\n    start = max(int(0.15 * n), 10)\n    end = int(0.9 * n)\n\n    motions = motions[start:end]\n    sm = smooth(motions)\n    sm = (sm - sm.mean()) / (sm.std() + 1e-6)\n\n    peaks = np.where(sm > 1.5)[0]\n    if len(peaks) == 0:\n        return None\n\n    clusters = []\n    current = [peaks[0]]\n\n    for p in peaks[1:]:\n        if p - current[-1] <= 3:\n            current.append(p)\n        else:\n            clusters.append(current)\n            current = [p]\n    clusters.append(current)\n\n    best = max(clusters, key=len)\n    center = int(np.mean(best)) + start\n\n    return center","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Spatial Localization\n","metadata":{}},{"cell_type":"code","source":"def get_motion_center(video_path, frame_idx):\n    cap = cv2.VideoCapture(video_path)\n\n    centers = []\n\n    for dt in [-2, -1, 0, 1, 2]:\n        f = max(frame_idx + dt, 0)\n        cap.set(cv2.CAP_PROP_POS_FRAMES, max(f - 1, 0))\n\n        ret1, prev = cap.read()\n        ret2, curr = cap.read()\n\n        if not ret1 or not ret2:\n            continue\n\n        prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)\n        curr_gray = cv2.cvtColor(curr, cv2.COLOR_BGR2GRAY)\n\n        diff = cv2.absdiff(prev_gray, curr_gray)\n\n        thresh = np.percentile(diff, 95)\n        mask = diff > thresh\n\n        ys, xs = np.where(mask)\n        if len(xs) < 10:\n            continue\n\n        weights = diff[ys, xs]\n        cx = np.average(xs, weights=weights)\n        cy = np.average(ys, weights=weights)\n\n        h, w = diff.shape\n        centers.append((cx / w, cy / h))\n\n    cap.release()\n\n    if len(centers) == 0:\n        return None\n\n    centers = np.array(centers)\n    return centers.mean(axis=0)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Motion Direction\n","metadata":{}},{"cell_type":"code","source":"def get_motion_direction(video_path, frame_idx):\n    cap = cv2.VideoCapture(video_path)\n\n    coords = []\n\n    for dt in [-5, -3, -1, 1]:\n        f = max(frame_idx + dt, 0)\n        cap.set(cv2.CAP_PROP_POS_FRAMES, f)\n\n        ret, frame = cap.read()\n        if not ret:\n            continue\n\n        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n        coords.append(gray.mean())\n\n    cap.release()\n\n    if len(coords) < 2:\n        return 0, 0\n\n    dx = coords[-1] - coords[0]\n    dy = coords[len(coords) // 2] - coords[0]\n\n    return dx, dy","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Classification\n","metadata":{}},{"cell_type":"code","source":"def classify(scene, dx, dy):\n    if scene == \"highway\":\n        pred = \"rear-end\"\n    elif \"intersection\" in scene:\n        pred = \"t-bone\"\n    else:\n        pred = \"sideswipe\"\n\n    mag = abs(dx) + abs(dy)\n\n    if mag < 0.5:\n        pred = \"rear-end\"\n    elif abs(dx) > abs(dy):\n        pred = \"sideswipe\"\n\n    return pred","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Inference\n","metadata":{}},{"cell_type":"code","source":"results = []\n\nfor _, row in tqdm(df.iterrows(), total=len(df)):\n\n    video_path = os.path.join(\"/kaggle/input/competitions/accident\", row[\"path\"])\n\n    motions, fps = compute_motion(video_path)\n\n    if motions is None or fps <= 0:\n        results.append([row[\"path\"], 10.0, 0.5, 0.5, \"rear-end\"])\n        continue\n\n    t_frame = detect_time(motions)\n\n    if t_frame is None:\n        t_frame = len(motions) // 2\n\n    t_sec = t_frame / fps\n\n    coords = get_motion_center(video_path, t_frame)\n\n    if coords is None:\n        x, y = 0.5, 0.5\n    else:\n        x, y = coords\n\n    dx, dy = get_motion_direction(video_path, t_frame)\n\n    accident_type = classify(row[\"scene_layout\"], dx, dy)\n\n    x = float(np.clip(x, 0, 1))\n    y = float(np.clip(y, 0, 1))\n\n    results.append([row[\"path\"], t_sec, x, y, accident_type])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Submission\n","metadata":{}},{"cell_type":"code","source":"submission = pd.DataFrame(results, columns=[\"path\", \"accident_time\", \"center_x\", \"center_y\", \"type\"])\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"submission.csv saved!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pd.read_csv(\"/kaggle/working/submission.csv\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}