{"version":2,"relationshipURLBase":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html","relationshipResolution":"Resolve relative relationship URLs against relationshipURLBase; complete records and absolute URLs are in blocks.","title":"4 · AP 必须说明积分协议 · 实现代码","url":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html","markdown":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.md","pages":[{"id":"reading-opening","title":"4 · AP 必须说明积分协议 · 实现代码","unit":"4 · AP 必须说明积分协议 · 实现代码","unitId":"notebook-blocks/86f64f86923e48fcaaea1efc4926457c","chapter":"course","number":1}],"aliases":[{"oldId":"b-96abe2ce9f8e0c9b3042aecc","targetId":"b-96abe2ce9f8e0c9b3042aecc","page":"reading-opening","operation":"move","beforeSHA256":"9027342eb8430f11699811edb871aeb2e37b28e9f874a2aa48778e6bac2818b7","afterSHA256":"9027342eb8430f11699811edb871aeb2e37b28e9f874a2aa48778e6bac2818b7","reason":"Same source body in authored semantic page"},{"oldId":"b-4d8375a95b4f428bfaddafb7","targetId":"b-4d8375a95b4f428bfaddafb7","page":"reading-opening","operation":"move","beforeSHA256":"18bc83d56bf3dff94de53e0b204b3af6df0f90bba3b150ba4324379221a732ec","afterSHA256":"18bc83d56bf3dff94de53e0b204b3af6df0f90bba3b150ba4324379221a732ec","reason":"Same source body in authored semantic page"},{"oldId":"b-d319e0256f14a09857abec02","targetId":"b-d319e0256f14a09857abec02","page":"reading-opening","operation":"move","beforeSHA256":"dc06c1e728a4b5740ba634b145bc9a1da6323031626734cb4555db5a744df806","afterSHA256":"dc06c1e728a4b5740ba634b145bc9a1da6323031626734cb4555db5a744df806","reason":"Same source body in authored semantic page"},{"oldId":"b-3abd8b129ec81009f4960d41","targetId":"b-3abd8b129ec81009f4960d41","page":"reading-opening","operation":"move","beforeSHA256":"4e0de6d032a3765c60907de32f28cd988b659299663e842d319bdb0426243d78","afterSHA256":"4e0de6d032a3765c60907de32f28cd988b659299663e842d319bdb0426243d78","reason":"Same source body in authored semantic page"},{"oldId":"b-683b7e402ff64225646e2bec","targetId":"b-683b7e402ff64225646e2bec","page":"reading-opening","operation":"move","beforeSHA256":"f31cf1d9a14598b7df30758514ff673215dd7e7f6b95d40db8325a0cf067437d","afterSHA256":"f31cf1d9a14598b7df30758514ff673215dd7e7f6b95d40db8325a0cf067437d","reason":"Same source body in authored semantic page"}],"blocks":[{"id":"b-96abe2ce9f8e0c9b3042aecc","type":"p","scope":"document","url":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html#b-96abe2ce9f8e0c9b3042aecc","content":"[LAB 09 · 检测几何：框、匹配、NMS 与 AP](/course/notebooks/90d213b4e1e04c7e889ee6fc042b2358.html)","sha256":"9027342eb8430f11699811edb871aeb2e37b28e9f874a2aa48778e6bac2818b7","chapter":{"id":"course","title":"4 · AP 必须说明积分协议 · 实现代码"},"unit":{"id":"notebook-blocks/86f64f86923e48fcaaea1efc4926457c","title":"4 · AP 必须说明积分协议 · 实现代码"},"page":{"id":"reading-opening","title":"4 · AP 必须说明积分协议 · 实现代码","number":1},"sectionTitle":"4 · AP 必须说明积分协议 · 实现代码","currentQuestion":"4 · AP 必须说明积分协议 · 实现代码","sourceSlides":[],"knowledgeBlock":null,"formulas":[],"previousBlock":null,"nextBlock":"b-4d8375a95b4f428bfaddafb7","prerequisites":[],"relatedBlocks":[]},{"id":"b-4d8375a95b4f428bfaddafb7","type":"h1","scope":"document","url":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html#b-4d8375a95b4f428bfaddafb7","content":"# 4 · AP 必须说明积分协议 · 实现代码","sha256":"18bc83d56bf3dff94de53e0b204b3af6df0f90bba3b150ba4324379221a732ec","chapter":{"id":"course","title":"4 · AP 必须说明积分协议 · 实现代码"},"unit":{"id":"notebook-blocks/86f64f86923e48fcaaea1efc4926457c","title":"4 · AP 必须说明积分协议 · 实现代码"},"page":{"id":"reading-opening","title":"4 · AP 必须说明积分协议 · 实现代码","number":1},"sectionTitle":"4 · AP 必须说明积分协议 · 实现代码","currentQuestion":"4 · AP 必须说明积分协议 · 实现代码","sourceSlides":[],"knowledgeBlock":null,"formulas":[],"previousBlock":"b-96abe2ce9f8e0c9b3042aecc","nextBlock":"b-d319e0256f14a09857abec02","prerequisites":[{"id":"b-96abe2ce9f8e0c9b3042aecc","url":"#b-96abe2ce9f8e0c9b3042aecc","role":"problem-context"}],"relatedBlocks":[]},{"id":"b-d319e0256f14a09857abec02","type":"p","scope":"document","url":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html#b-d319e0256f14a09857abec02","content":"并入相关学习路径","sha256":"dc06c1e728a4b5740ba634b145bc9a1da6323031626734cb4555db5a744df806","chapter":{"id":"course","title":"4 · AP 必须说明积分协议 · 实现代码"},"unit":{"id":"notebook-blocks/86f64f86923e48fcaaea1efc4926457c","title":"4 · AP 必须说明积分协议 · 实现代码"},"page":{"id":"reading-opening","title":"4 · AP 必须说明积分协议 · 实现代码","number":1},"sectionTitle":"4 · AP 必须说明积分协议 · 实现代码","currentQuestion":"4 · AP 必须说明积分协议 · 实现代码","sourceSlides":[],"knowledgeBlock":null,"formulas":[],"previousBlock":"b-4d8375a95b4f428bfaddafb7","nextBlock":"b-3abd8b129ec81009f4960d41","prerequisites":[{"id":"b-4d8375a95b4f428bfaddafb7","url":"#b-4d8375a95b4f428bfaddafb7","role":"section-title"},{"id":"b-96abe2ce9f8e0c9b3042aecc","url":"#b-96abe2ce9f8e0c9b3042aecc","role":"problem-context"}],"relatedBlocks":[]},{"id":"b-3abd8b129ec81009f4960d41","type":"p","scope":"document","url":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html#b-3abd8b129ec81009f4960d41","content":"固定框匹配、PR/AP、NMS误删相邻对象反例","sha256":"4e0de6d032a3765c60907de32f28cd988b659299663e842d319bdb0426243d78","chapter":{"id":"course","title":"4 · AP 必须说明积分协议 · 实现代码"},"unit":{"id":"notebook-blocks/86f64f86923e48fcaaea1efc4926457c","title":"4 · AP 必须说明积分协议 · 实现代码"},"page":{"id":"reading-opening","title":"4 · AP 必须说明积分协议 · 实现代码","number":1},"sectionTitle":"4 · AP 必须说明积分协议 · 实现代码","currentQuestion":"4 · AP 必须说明积分协议 · 实现代码","sourceSlides":[],"knowledgeBlock":null,"formulas":[],"previousBlock":"b-d319e0256f14a09857abec02","nextBlock":"b-683b7e402ff64225646e2bec","prerequisites":[{"id":"b-4d8375a95b4f428bfaddafb7","url":"#b-4d8375a95b4f428bfaddafb7","role":"section-title"},{"id":"b-96abe2ce9f8e0c9b3042aecc","url":"#b-96abe2ce9f8e0c9b3042aecc","role":"problem-context"}],"relatedBlocks":[]},{"id":"b-683b7e402ff64225646e2bec","type":"pre","scope":"document","url":"https://codingai-lec03.pages.dev/course/notebook-blocks/86f64f86923e48fcaaea1efc4926457c.html#b-683b7e402ff64225646e2bec","content":"```\ndef all_points_ap(recall, precision):\n    \"\"\"All-points interpolated AP = sum of recall increments * envelope.\n\n    This is not 11-point AP, the mean of raw precisions, or COCO 101-point AP.\n    A sentinel at recall 1 with precision 0 gives unreached recall zero credit.\n    \"\"\"\n    recall, precision = np.asarray(recall, float), np.asarray(precision, float)\n    if recall.shape != precision.shape or np.any(np.diff(recall) < -1e-12):\n        raise ValueError(\"Aligned arrays and nondecreasing recall required\")\n    if np.any((recall < 0) | (recall > 1) | (precision < 0) | (precision > 1)):\n        raise ValueError(\"Recall and precision must be in [0,1]\")\n    mrec = np.r_[0.0, recall, 1.0]\n    mpre = np.r_[0.0, precision, 0.0]\n    envelope = np.maximum.accumulate(mpre[::-1])[::-1]\n    changed = np.where(mrec[1:] > mrec[:-1])[0]\n    ap = np.sum((mrec[changed + 1] - mrec[changed]) * envelope[changed + 1])\n    return float(ap), mrec, envelope\n\n\ndef evaluate_single_class(pred_boxes, scores, gt_boxes, iou_threshold=0.50):\n    \"\"\"One image / one class: choose the best-IoU GT, then check if already used.\n\n    VOC-style greedy matching, aligned with LAB10: a used best GT makes the\n    prediction a duplicate FP; do not fall back to a lower-IoU unused GT.\n    Score ties and IoU ties preserve input order. Threshold comparison is >=.\n    No crowd, ignore regions, maxDets, area bins, or dataset pooling.\n    \"\"\"\n    if not 0 <= iou_threshold <= 1:\n        raise ValueError(\"iou_threshold must be in [0,1]\")\n    pred_boxes, gt_boxes = boxes_xyxy(pred_boxes), boxes_xyxy(gt_boxes)\n    scores = np.asarray(scores, dtype=float)\n    if scores.shape != (len(pred_boxes),) or not np.isfinite(scores).all():\n        raise ValueError(\"Require one finite score per prediction\")\n    if len(gt_boxes) == 0:\n        raise ValueError(\"AP is undefined for this no-GT single-class example\")\n    order = np.argsort(-scores, kind=\"stable\")\n    used = np.zeros(len(gt_boxes), dtype=bool)\n    overlaps = box_iou(pred_boxes, gt_boxes)\n    tp, rows = [], []\n    for rank, pred_i in enumerate(order, 1):\n        gt_i = int(np.argmax(overlaps[pred_i]))\n        best_iou = float(overlaps[pred_i, gt_i])\n        meets_threshold = best_iou >= iou_threshold\n        is_tp = bool(meets_threshold and not used[gt_i])\n        if is_tp:\n            used[gt_i] = True\n            reason = \"new GT matched\"\n        elif meets_threshold:\n            reason = \"duplicate: maximum-IoU GT already used; no fallback\"\n        else:\n            reason = \"IoU below evaluation threshold\"\n        tp.append(int(is_tp))\n        rows.append({\"rank\": rank, \"prediction\": int(pred_i + 1),\n                     \"score\": float(scores[pred_i]), \"status\": \"TP\" if is_tp else \"FP\",\n                     \"gt\": gt_i + 1 if is_tp else None,\n                     \"best_gt\": gt_i + 1, \"best_iou_any_gt\": best_iou, \"reason\": reason})\n    tp = np.asarray(tp, dtype=int)\n    cumulative_tp, cumulative_fp = np.cumsum(tp), np.cumsum(1 - tp)\n    recall = cumulative_tp / len(gt_boxes)\n    precision = np.divide(cumulative_tp, np.arange(1, len(tp) + 1), dtype=float)\n    ap, mrec, envelope = all_points_ap(recall, precision)\n    for i, row in enumerate(rows):\n        row.update(cumulative_tp=int(cumulative_tp[i]), cumulative_fp=int(cumulative_fp[i]),\n                   recall=float(recall[i]), precision=float(precision[i]))\n    return {\"iou_threshold\": iou_threshold, \"rows\": rows, \"ap\": ap,\n            \"recall\": recall.tolist(), \"precision\": precision.tolist(),\n            \"envelope_recall\": mrec.tolist(), \"precision_envelope\": envelope.tolist(),\n            \"final_recall\": float(recall[-1]) if len(recall) else 0.0}\n\nfor threshold in EVAL_THRESHOLDS:\n    evaluation = evaluate_single_class(PRED, SCORES, GT, threshold)\n    print(\"IoU threshold:\", threshold, \"all-points AP:\", evaluation[\"ap\"])\n    for row in evaluation[\"rows\"]:\n        print(row)\n```","sha256":"f31cf1d9a14598b7df30758514ff673215dd7e7f6b95d40db8325a0cf067437d","chapter":{"id":"course","title":"4 · AP 必须说明积分协议 · 实现代码"},"unit":{"id":"notebook-blocks/86f64f86923e48fcaaea1efc4926457c","title":"4 · AP 必须说明积分协议 · 实现代码"},"page":{"id":"reading-opening","title":"4 · AP 必须说明积分协议 · 实现代码","number":1},"sectionTitle":"4 · AP 必须说明积分协议 · 实现代码","currentQuestion":"4 · AP 必须说明积分协议 · 实现代码","sourceSlides":[],"knowledgeBlock":null,"formulas":[],"previousBlock":"b-3abd8b129ec81009f4960d41","nextBlock":null,"prerequisites":[{"id":"b-4d8375a95b4f428bfaddafb7","url":"#b-4d8375a95b4f428bfaddafb7","role":"section-title"},{"id":"b-96abe2ce9f8e0c9b3042aecc","url":"#b-96abe2ce9f8e0c9b3042aecc","role":"problem-context"}],"relatedBlocks":[]}]}
