{"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},{"sourceId":10132065,"sourceType":"datasetVersion","datasetId":6253224}],"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-07T20:15:05.177537Z","iopub.execute_input":"2024-12-07T20:15:05.178088Z","iopub.status.idle":"2024-12-07T20:15:06.399042Z","shell.execute_reply.started":"2024-12-07T20:15:05.17804Z","shell.execute_reply":"2024-12-07T20:15:06.397881Z"}},"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-07T20:15:06.40115Z","iopub.execute_input":"2024-12-07T20:15:06.401804Z","iopub.status.idle":"2024-12-07T20:15:06.409886Z","shell.execute_reply.started":"2024-12-07T20:15:06.40175Z","shell.execute_reply":"2024-12-07T20:15:06.408556Z"}},"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-07T20:15:06.411935Z","iopub.execute_input":"2024-12-07T20:15:06.412447Z","iopub.status.idle":"2024-12-07T20:15:06.434074Z","shell.execute_reply.started":"2024-12-07T20:15:06.412398Z","shell.execute_reply":"2024-12-07T20:15:06.432877Z"}},"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-07T20:15:06.437141Z","iopub.execute_input":"2024-12-07T20:15:06.437691Z","iopub.status.idle":"2024-12-07T20:15:07.603277Z","shell.execute_reply.started":"2024-12-07T20:15:06.43764Z","shell.execute_reply":"2024-12-07T20:15:07.602083Z"}},"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-07T20:15:07.604907Z","iopub.execute_input":"2024-12-07T20:15:07.605345Z","iopub.status.idle":"2024-12-07T20:15:07.613066Z","shell.execute_reply.started":"2024-12-07T20:15:07.605299Z","shell.execute_reply":"2024-12-07T20:15:07.611694Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 读取 CSV 文件\ndata_list = []\nwith open('/kaggle/input/result-fold1/submission (1).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-07T20:15:07.614521Z","iopub.execute_input":"2024-12-07T20:15:07.614912Z","iopub.status.idle":"2024-12-07T20:15:07.755969Z","shell.execute_reply.started":"2024-12-07T20:15:07.614881Z","shell.execute_reply":"2024-12-07T20:15:07.754549Z"}},"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.4, 0.6, 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-07T20:15:07.757535Z","iopub.execute_input":"2024-12-07T20:15:07.757999Z"}},"outputs":[],"execution_count":null}]}