{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":19989,"databundleVersionId":1160143,"sourceType":"competition"},{"sourceId":10131622,"sourceType":"datasetVersion","datasetId":6252893}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport csv","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:04:11.514447Z","iopub.execute_input":"2024-12-07T19:04:11.514942Z","iopub.status.idle":"2024-12-07T19:04:11.52039Z","shell.execute_reply.started":"2024-12-07T19:04:11.514883Z","shell.execute_reply":"2024-12-07T19:04:11.519211Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 计算IoU的函数\ndef calculate_iou(box1, box2):\n    x1, y1, w1, h1 = box1\n    x2, y2, w2, h2 = box2\n    \n    # 计算两个框的交集\n    x1_int = max(x1, x2)\n    y1_int = max(y1, y2)\n    x2_int = min(x1 + w1, x2 + w2)\n    y2_int = min(y1 + h1, y2 + h2)\n    \n    # 计算交集区域的面积\n    intersection_w = max(0, x2_int - x1_int)\n    intersection_h = max(0, y2_int - y1_int)\n    intersection_area = intersection_w * intersection_h\n    \n    # 计算两个框的并集\n    box1_area = w1 * h1\n    box2_area = w2 * h2\n    union_area = box1_area + box2_area - intersection_area\n    \n    # 计算IoU\n    iou = intersection_area / union_area if union_area > 0 else 0\n    return iou\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:04:11.522529Z","iopub.execute_input":"2024-12-07T19:04:11.523389Z","iopub.status.idle":"2024-12-07T19:04:11.536907Z","shell.execute_reply.started":"2024-12-07T19:04:11.523335Z","shell.execute_reply":"2024-12-07T19:04:11.535256Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 计算AP的函数，并统计FN\ndef calculate_ap(preds_df, marking_test, iou_threshold=0.5):\n    aps = []\n    \n    for image_id in preds_df['image_id'].unique():\n        pred_boxes = preds_df[preds_df['image_id'] == image_id]\n        true_boxes = marking_test[marking_test['image_id'] == image_id]\n        \n        # 按照分数降序排列预测框\n        pred_boxes = pred_boxes.sort_values(by='score', ascending=False)\n        \n        true_boxes_matched = set()\n        pred_matches = []\n        \n        # 计算每个预测框的IoU\n        for _, pred_row in pred_boxes.iterrows():\n            pred_box = (pred_row['x'], pred_row['y'], pred_row['w'], pred_row['h'])\n            pred_score = pred_row['score']\n            \n            best_iou = 0\n            best_match = None\n            \n            for idx, true_row in true_boxes.iterrows():\n                if idx in true_boxes_matched:\n                    continue\n                \n                true_box = (true_row['x'], true_row['y'], true_row['w'], true_row['h'])\n                iou = calculate_iou(pred_box, true_box)\n                \n                if iou > best_iou:\n                    best_iou = iou\n                    best_match = idx\n            \n            if best_iou >= iou_threshold:\n                pred_matches.append(1)\n                true_boxes_matched.add(best_match)\n            else:\n                pred_matches.append(0)\n        \n        # 统计 FN (未匹配的真实框)\n        fn = len(true_boxes) - len(true_boxes_matched)\n        \n        # 计算TP和FP\n        tp = np.sum(pred_matches)\n        fp = len(pred_matches) - tp\n        \n        ap=tp/(tp+fp+fn)\n        aps.append(ap)\n    \n    mean_ap = np.mean(aps)\n    return mean_ap\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:04:11.538511Z","iopub.execute_input":"2024-12-07T19:04:11.539001Z","iopub.status.idle":"2024-12-07T19:04:11.555767Z","shell.execute_reply.started":"2024-12-07T19:04:11.538947Z","shell.execute_reply":"2024-12-07T19:04:11.554423Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Real boxes","metadata":{}},{"cell_type":"code","source":"marking = pd.read_csv('../input/global-wheat-detection/train.csv')\n\nbboxs = np.stack(marking['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\nfor i, column in enumerate(['x', 'y', 'w', 'h']):\n    marking[column] = bboxs[:,i]\nmarking.drop(columns=['bbox'], inplace=True)\n\nmarking_test = marking[marking['source'] == 'rres_1']\nprint(marking_test.shape)\nmarking_test","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:04:11.558208Z","iopub.execute_input":"2024-12-07T19:04:11.558549Z","iopub.status.idle":"2024-12-07T19:04:12.315551Z","shell.execute_reply.started":"2024-12-07T19:04:11.558515Z","shell.execute_reply":"2024-12-07T19:04:12.31424Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"# 定义一个函数，解析 PredictionString\ndef parse_prediction_string(image_id, prediction_string):\n    data = prediction_string.split()\n    groups = [data[i:i+5] for i in range(0, len(data), 5)]  # 每5个数据划分为一组\n    return [{\"image_id\": image_id,\n             \"score\": float(group[0]), \n             \"x\": int(group[1]), \n             \"y\": int(group[2]), \n             \"w\": int(group[3]), \n             \"h\": int(group[4])} for group in groups]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:04:46.130758Z","iopub.execute_input":"2024-12-07T19:04:46.131188Z","iopub.status.idle":"2024-12-07T19:04:46.13856Z","shell.execute_reply.started":"2024-12-07T19:04:46.13115Z","shell.execute_reply":"2024-12-07T19:04:46.137209Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 读取 CSV 文件\ndata_list = []\nwith open('/kaggle/input/result-pl-tta-fold1/submission.csv', 'r') as file:\n    reader = csv.reader(file)\n    next(reader)  # 跳过第一行注释\n    for row in reader:\n        image_id = row[0]\n        prediction_string = row[1]\n        parsed_data = parse_prediction_string(image_id, prediction_string)\n        data_list.extend(parsed_data)\n\n# 将 data_list 转换为 DataFrame\ndata_list_df = pd.DataFrame(data_list)\n\n# 输出结果\nprint(data_list_df.shape)\ndata_list_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:08:54.880056Z","iopub.execute_input":"2024-12-07T19:08:54.880437Z","iopub.status.idle":"2024-12-07T19:08:55.08222Z","shell.execute_reply.started":"2024-12-07T19:08:54.880402Z","shell.execute_reply":"2024-12-07T19:08:55.081012Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Compute mAP","metadata":{}},{"cell_type":"code","source":"def calculate_mean_mAP(preds_df, marking_test, iou_thresholds=np.arange(0.6,0.8,0.01)):\n    aps = []\n    \n    for threshold in iou_thresholds:\n        ap= calculate_ap(preds_df, marking_test, iou_threshold=threshold)\n        aps.append(ap)\n        print(f\"mAP at IoU threshold {threshold} : {ap}\")\n    \n    print(aps)\n    mean_map = np.mean(aps)\n    return mean_map\n\n\n# 计算多个阈值的mAP\nmap_score= calculate_mean_mAP(data_list_df, marking_test)\nprint(f\"Mean mAP across all thresholds: {map_score}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T19:14:21.696888Z","iopub.execute_input":"2024-12-07T19:14:21.697282Z","iopub.status.idle":"2024-12-07T19:14:25.040689Z","shell.execute_reply.started":"2024-12-07T19:14:21.69725Z","shell.execute_reply":"2024-12-07T19:14:25.039159Z"}},"outputs":[],"execution_count":null}]}