{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":129750,"databundleVersionId":15563344,"sourceType":"competition"}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Install Ultralytics (YOLO)\n!pip install -q ultralytics\nimport os\nimport pandas as pd\nimport numpy as np\nfrom ultralytics import YOLO\nimport yaml\nfrom tqdm.notebook import tqdm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-11T07:16:15.483041Z","iopub.execute_input":"2026-02-11T07:16:15.483790Z","iopub.status.idle":"2026-02-11T07:16:32.966920Z","shell.execute_reply.started":"2026-02-11T07:16:15.483757Z","shell.execute_reply":"2026-02-11T07:16:32.966318Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define the dataset configuration\ndataset_config = {\n    'path': '/kaggle/input/dal-shemagh-detection-challenge', # Root dir\n    'train': 'images/train',  # Train images (relative to path)\n    'val': 'images/train',    # Using train as val for demo (Split this properly for real training!)\n    'names': {\n        0: 'person',\n        1: 'shemagh'\n    }\n}\n\n# Write to data.yaml\nwith open('data.yaml', 'w') as f:\n    yaml.dump(dataset_config, f)\n\nprint(\"data.yaml created successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-11T07:16:32.968299Z","iopub.execute_input":"2026-02-11T07:16:32.968789Z","iopub.status.idle":"2026-02-11T07:16:32.974123Z","shell.execute_reply.started":"2026-02-11T07:16:32.968741Z","shell.execute_reply":"2026-02-11T07:16:32.973508Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import albumentations as A\n\nmy_transform = A.Compose([\n    # A.Resize((640, 640)),\n    A.HorizontalFlip(p=0.5),\n    A.ColorJitter(brightness=0.15, contrast=0.15, saturation=0.15, p=0.4),\n    A.GaussianBlur(p=0.1),\n    A.Rotate(limit=15, p=0.3),\n    A.Affine(\n        scale=(0.8, 1.2),\n        translate_percent=(-0.1, 0.1),\n        p=0.3\n    ),\n    A.RandomBrightnessContrast(\n        brightness_limit=0.15, \n        contrast_limit=0.15, \n        p=0.3\n    ),\n    A.GaussNoise(var_limit=(10.0, 30.0), p=0.15),\n    A.CLAHE(clip_limit=2.0, tile_grid_size=(8, 8), p=0.1),\n    A.RandomGamma(gamma_limit=(80, 120), p=0.2),\n    A.HueSaturationValue(\n        hue_shift_limit=10,\n        sat_shift_limit=20,\n        val_shift_limit=15,\n        p=0.2\n    ),\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-11T07:16:32.974879Z","iopub.execute_input":"2026-02-11T07:16:32.975090Z","iopub.status.idle":"2026-02-11T07:16:34.397010Z","shell.execute_reply.started":"2026-02-11T07:16:32.975067Z","shell.execute_reply":"2026-02-11T07:16:34.396426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load a pre-trained YOLO model (Recommended: yolo11s.pt or yolo11m.pt)\nmodel = YOLO('yolo11n.pt')\n\n# Train the model\nresults = model.train(\n    data='data.yaml',\n    epochs=200,            # Increase this for better results!\n    imgsz=640,\n    batch=16,\n    project='dal_challenge',\n    name='shemagh_detector',\n    patience=20,\n    exist_ok=True,\n    augmentations=my_transform,\n    dropout=0.1,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-11T07:16:34.397887Z","iopub.execute_input":"2026-02-11T07:16:34.398180Z","iopub.status.idle":"2026-02-11T07:37:31.828973Z","shell.execute_reply.started":"2026-02-11T07:16:34.398155Z","shell.execute_reply":"2026-02-11T07:37:31.828276Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"yolo_model = YOLO(\"/kaggle/working/runs/detect/dal_challenge/shemagh_detector/weights/best.pt\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-11T07:39:05.657204Z","iopub.execute_input":"2026-02-11T07:39:05.658057Z","iopub.status.idle":"2026-02-11T07:39:05.706137Z","shell.execute_reply.started":"2026-02-11T07:39:05.658021Z","shell.execute_reply":"2026-02-11T07:39:05.705572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import glob\n\n# 2. Пути к тестовым изображениям\ntest_images = glob.glob('/kaggle/input/dal-shemagh-detection-challenge/images/test/*.jpg')\nsubmission_data = []\n\n# 3. Функция расчёта IoU (без изменений)\ndef calculate_iou(box1, box2):\n    \"\"\"\n    box1, box2: [x, y, w, h] в относительных координатах (0..1)\n    \"\"\"\n    b1_x1, b1_x2 = box1[0] - box1[2]/2, box1[0] + box1[2]/2\n    b1_y1, b1_y2 = box1[1] - box1[3]/2, box1[1] + box1[3]/2\n    b2_x1, b2_x2 = box2[0] - box2[2]/2, box2[0] + box2[2]/2\n    b2_y1, b2_y2 = box2[1] - box2[3]/2, box2[1] + box2[3]/2\n\n    inter_x1 = max(b1_x1, b2_x1)\n    inter_y1 = max(b1_y1, b2_y1)\n    inter_x2 = min(b1_x2, b2_x2)\n    inter_y2 = min(b1_y2, b2_y2)\n\n    inter_area = max(0, inter_x2 - inter_x1) * max(0, inter_y2 - inter_y1)\n    b1_area = (b1_x2 - b1_x1) * (b1_y2 - b1_y1)\n    b2_area = (b2_x2 - b2_x1) * (b2_y2 - b2_y1)\n    union_area = b1_area + b2_area - inter_area\n    return inter_area / union_area if union_area > 0 else 0\n\n# 4. Основной цикл инференса\nprint(f\"Обрабатывается {len(test_images)} изображений...\")\n\nfor img_path in tqdm(test_images):\n    filename = os.path.basename(img_path)\n\n    # Инференс\n    results = yolo_model.predict(img_path, conf=0.25, verbose=False)[0]\n\n    prediction_strings = []\n    person_boxes = []\n    shemagh_boxes = []\n\n    if len(results.boxes) == 0:\n        prediction_str = \"-\"\n        right_place = 0\n    else:\n        for box in results.boxes:\n            cls = int(box.cls[0])\n            conf = float(box.conf[0])\n            x, y, w, h = box.xywhn[0].tolist()\n\n            prediction_strings.append(f\"{cls} {conf:.4f} {x:.4f} {y:.4f} {w:.4f} {h:.4f}\")\n\n            if cls == 0:\n                person_boxes.append([x, y, w, h])\n            elif cls == 1:\n                shemagh_boxes.append([x, y, w, h])\n\n        prediction_str = \" \".join(prediction_strings)\n\n        # ---------- УЛУЧШЕННАЯ ЛОГИКА right_place (минимальные изменения) ----------\n        right_place = 0\n        if person_boxes and shemagh_boxes:\n            best_iou = 0.0\n            best_pair = None\n\n            # 1. Ищем наилучшую пару (человек, платок) по IoU\n            for p_idx, p_box in enumerate(person_boxes):\n                for s_idx, s_box in enumerate(shemagh_boxes):\n                    iou = calculate_iou(p_box, s_box)  # порядок не важен\n                    if iou > best_iou:\n                        best_iou = iou\n                        best_pair = (p_idx, s_idx)\n\n            if best_pair is not None:\n                p_box = person_boxes[best_pair[0]]\n                s_box = shemagh_boxes[best_pair[1]]\n\n                # 2. Критерии правильного размещения\n                iou_threshold = 0.02        # можно подобрать (0.07..0.15)\n                vertical_threshold = 0.0    # центр платка выше центра человека (y↑ вниз, значит s_y < p_y)\n                min_area_ratio = 0.4\n\n                iou_ok = best_iou > iou_threshold\n                vertical_ok = s_box[1] < p_box[1] - vertical_threshold\n                area_ratio = (s_box[2] * s_box[3]) / (p_box[2] * p_box[3])\n                size_ok = area_ratio > min_area_ratio\n\n                # Итоговое решение: IoU + вертикальное положение (можно добавить size_ok при необходимости)\n                if iou_ok and size_ok:   # и, опционально, size_ok\n                    right_place = 1\n        # --------------------------------------------------------------------------\n\n    submission_data.append([filename, right_place, prediction_str])\n\n# 5. Сохранение результата\ndf_sub = pd.DataFrame(submission_data, columns=['filename', 'right_place', 'prediction_string'])\ndf_sub.to_csv('submission.csv', index=False)\n\nprint(\"submission.csv успешно создан!\")\nprint(df_sub.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-11T07:39:06.275909Z","iopub.execute_input":"2026-02-11T07:39:06.276414Z","iopub.status.idle":"2026-02-11T07:39:18.633755Z","shell.execute_reply.started":"2026-02-11T07:39:06.276382Z","shell.execute_reply":"2026-02-11T07:39:18.633014Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}