{
  "schemaVersion": 1,
  "id": "3.2.5",
  "title": "人脸AI智能检测系统交互流程设计",
  "durationMinutes": 20,
  "category": "代码实现与交互设计",
  "scenario": "在安防监控、智能交通等领域，实时准确的人脸检测需求日益增长。传统的人脸检测方法在面对复杂光照、多角度、遮挡等情况时，检测效果往往不尽人意。随着深度学习技术的发展，基于深度神经网络的人脸检测模型展现出强大的性能优势。ONNX（Open Neural Network Exchange）作为一种开放式的神经网络交换格式，能够实现不同深度学习框架间的模型转换与共享，使得基于 ONNX 的人脸检测模型可以在多种环境下高效运行。本系统所使用的 “version-RFB-320.onnx” 模型，通过大量数据训练，能够快速准确地检测出图像中的人脸，在实际应用场景中具有重要价值。\n\nAI 模型说明：“version-RFB-320.onnx” 模型是用于人脸检测的 ONNX 格式模型，对应的类别标签文件为 “voc-model-labels.txt” 。该模型的使用交互流程为：\n\n（1）加载 “version-RFB-320.onnx” 模型和 “voc-model-labels.txt” 类别标签；\n\n（2）加载本地测试图片文件夹 “imgs” 中的所有图片，并对每张图片进行预处理以符合模型输入要求；\n\n（3）使用 “version-RFB-320.onnx” 模型对加载的图片进行人脸检测；\n\n（4）在图片上绘制检测到的人脸框，并将处理后的图片保存到 “./detect_imgs_results_onnx” 文件夹中；\n\n（5）统计所有图片中检测到的人脸总数并输出。\n\n你作为一名人工智能训练师，请完成以下工作任务：\n\n（1）补全该模型的使用交互流程对应的 Python 代码（3.2.5.ipynb），实现本地测试图片文件夹 “imgs” 中所有图片的人脸检测，将运行结果截图保存到3.2.5-1.jpg中，并将检测结果的图片上传。\n\n（2）在上面的使用交互流程基础上，结合实际应用场景，设计在人脸检测系统中使用 “version-RFB-320.onnx” 模型的一种人机交互优化方案，包括交互界面布局、操作流程等内容，将其保存为docx文件，命名为 3.2.5.docx。",
  "skillRequirements": "（1）能确保模型在单一场景下稳定运行；\n\n（2）能通过分析，找到单一场景下人工和智能交互的最优方式；\n\n（3）能对单一场景下人工和智能交互界面设计提出优化需求。",
  "qualityIndicators": "（1）模型运行稳定，使用正常；\n\n（2）单一场景下人工和智能交互的最优方式切实可行。",
  "tasks": [
    {
      "id": "code-fill",
      "type": "code-fill",
      "title": "补全代码任务",
      "instructions": "依据公开题面和附件补全代码空位；仅检查完成度与提交格式，不公开标准内容。",
      "codeBlocks": [
        "import os\nimport time\nimport cv2\nimport numpy as np\nimport vision.utils.box_utils_numpy as box_utils\nimport onnxruntime as ort\n\n# 定义预测函数，对模型输出的边界框和置信度进行后处理\ndef predict(width, height, confidences, boxes, prob_threshold, iou_threshold=0.3, top_k=-1):\n    boxes = boxes[0]\n    confidences = confidences[0]\n    picked_box_probs = []\n    picked_labels = []\n    for class_index in range(1, confidences.shape[1]):\n        probs = confidences[:, class_index]\n        mask = probs > prob_threshold\n        probs = probs[mask]\n        if probs.shape[0] == 0:\n            continue\n        subset_boxes = boxes[mask, :]\n        box_probs = np.concatenate([subset_boxes, probs.reshape(-1, 1)], axis=1)\n        box_probs = box_utils.hard_nms(box_probs,\n                                       iou_threshold=iou_threshold,\n                                       top_k=top_k,\n                                       )\n        picked_box_probs.append(box_probs)\n        picked_labels.extend([class_index] * box_probs.shape[0])\n    if not picked_box_probs:\n        return np.array([]), np.array([]), np.array([])\n    picked_box_probs = np.concatenate(picked_box_probs)\n    picked_box_probs[:, 0] *= width\n    picked_box_probs[:, 1] *= height\n    picked_box_probs[:, 2] *= width\n    picked_box_probs[:, 3] *= height\n    return picked_box_probs[:, :4].astype(np.int32), np.array(picked_labels), picked_box_probs[:, 4]\n\n# 从标签文件中读取每一行，并去除行首尾的空白字符，得到类别名称列表 2分\nclass_names = [_______________ for name in open('voc-model-labels.txt').readlines()]\n\n# 创建 ONNX Runtime 的推理会话，用于运行模型进行推理 2分\nort_session = _______________('version-RFB-320.onnx')\n\n# 获取模型输入的名称 2分\ninput_name = _______________()[0].name\n\n# 定义保存检测结果图像的目录路径\nresult_path = \"./detect_imgs_results_onnx\"\n\n# 定义置信度阈值，用于筛选出置信度较高的检测结果\nthreshold = 0.7\n# 定义存储待检测图像的目录路径\npath = \"imgs\"\n# 用于统计所有图像中检测到的目标框总数，初始化为 0\nsum = 0\n\n# 如果保存结果的目录不存在，则创建该目录 2分\nif not os.path.exists(result_path):\n    os._______________\n    \n# 获取指定目录下的所有文件和文件夹名称列表\nlistdir = os.listdir(path)\n\n# 遍历目录下的每个文件\nfor file_path in listdir:\n    # 拼接图像文件的完整路径\n    img_path = os.path.join(path, file_path)\n    # 使用 OpenCV 读取图像文件 2分\n    orig_image = _______________\n    # 将图像从 BGR 颜色空间转换为 RGB 颜色空间（许多模型要求输入为 RGB 格式）\n    image = cv2.cvtColor(orig_image, cv2.COLOR_BGR2RGB)\n    # 将图像调整为 320x240 的尺寸（符合模型输入的尺寸要求） 2分\n    image = _______________(_______________, (320, 240))\n    # 定义图像归一化的均值数组 2分\n    image_mean = _______________([127, 127, 127])\n    # 对图像进行归一化处理，减去均值并除以 128\n    image = (image - image_mean) / 128\n    # 将图像的维度从 (高度, 宽度, 通道数) 转换为 (通道数, 高度, 宽度)\n    image = np.transpose(image, [2, 0, 1])\n    # 在第一个维度上扩展一个维度，将图像变为 (1, 通道数, 高度, 宽度)，以符合模型输入的维度要求  1分\n    image = _______________(image, axis=0)\n    # 将图像数据类型转换为 float32 类型\n    image = image.astype(np.float32)\n    # 记录开始时间，用于计算模型推理的耗时\n    time_time = time.time()\n    # 使用 ONNX Runtime 运行模型，输入图像数据，得到模型输出的置信度和边界框  2分\n    confidences, boxes = _______________(None, {input_name: image})\n    # 计算并打印模型推理的耗时\n    print(\"cost time:{}\".format(time.time() - time_time))\n    # 调用 predict 函数对模型输出的边界框和置信度进行后处理，得到最终的边界框、类别标签和置信度\n    boxes, labels, probs = predict(orig_image.shape[1], orig_image.shape[0], confidences, boxes, threshold)\n    # 遍历每个检测到的目标框\n    for i in range(boxes.shape[0]):\n        # 获取当前目标框的坐标\n        box = boxes[i, :]\n        # 生成当前目标框的标签字符串，包含类别名称和置信度\n        label = f\"{class_names[labels[i]]}: {probs[i]:.2f}\"\n\n        # 在原始图像上绘制目标框，颜色为 (255, 255, 0)，线条粗细为 4\n        cv2.rectangle(orig_image, (box[0], box[1]), (box[2], box[3]), (255, 255, 0), 4)\n        # 将绘制了目标框的图像保存到结果目录中\n        cv2.imwrite(os.path.join(result_path, file_path), orig_image)\n    # 累加当前图像中检测到的目标框数量到总数中\n    sum += boxes.shape[0]\n# 打印所有图像中检测到的目标框总数\nprint(\"sum:{}\".format(sum))"
      ],
      "blanks": [
        {
          "id": "blank-1",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-2",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-3",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-4",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-5",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-6",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-7",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-8",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-9",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        },
        {
          "id": "blank-10",
          "block": 1,
          "placeholder": "_______________",
          "gradingMode": "completion-and-format-only"
        }
      ]
    },
    {
      "id": "3-2-response",
      "type": "rubric-response",
      "title": "交互方案设计",
      "instructions": "说明代码功能对应的人机交互流程。",
      "sections": [
        {
          "id": "response",
          "label": "作答内容"
        }
      ],
      "rubric": [
        {
          "id": "criterion-1",
          "label": "输入与格式校验清晰",
          "weight": 25
        },
        {
          "id": "criterion-2",
          "label": "执行进度和状态反馈完整",
          "weight": 25
        },
        {
          "id": "criterion-3",
          "label": "结果展示可理解",
          "weight": 25
        },
        {
          "id": "criterion-4",
          "label": "包含异常处理与人工确认",
          "weight": 25
        }
      ]
    },
    {
      "id": "artifact-submission",
      "type": "artifact-submission",
      "title": "选择结果文件",
      "instructions": "文件仅在本机选择并校验，不上传，也不持久化文件内容。",
      "items": [
        {
          "id": "artifact-1",
          "label": "提交文件：3.2.5.docx",
          "filename": "3.2.5.docx",
          "extensions": [
            ".docx"
          ],
          "minCount": 1,
          "maxCount": 1,
          "maxSize": 104857600
        }
      ]
    }
  ],
  "attachments": [
    {
      "name": "3.2.5.docx",
      "url": "assets/3.2.5/3.2.5.docx",
      "size": 15387,
      "sha256": "fce1c4efd657a8b4efefc462662b49de7e631ee58960b4485f6cbaf1b43798a7",
      "mime": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    },
    {
      "name": "3.2.5.ipynb",
      "url": "assets/3.2.5/3.2.5.ipynb",
      "size": 6481,
      "sha256": "73e3d7afaf0b64bc61f9808da0b6ac4f7f46abe07cdfc9d8b0e20a9435ce54d3",
      "mime": "application/x-ipynb+json"
    },
    {
      "name": "3.2.5.md",
      "url": "assets/3.2.5/3.2.5.md",
      "size": 2797,
      "sha256": "1768709a2efdf8f47faa75811fe8324337cc48be3915243f32c173c867041eae",
      "mime": "text/markdown"
    },
    {
      "name": "imgs/1.jpg",
      "url": "assets/3.2.5/imgs/1.jpg",
      "size": 49124,
      "sha256": "929d79fd5ac4dea69fd5bc4bd5dab0199f19d06fa84e5649b69c3d5c481c52c9",
      "mime": "image/jpeg"
    },
    {
      "name": "version-RFB-320.onnx",
      "url": "assets/3.2.5/version-RFB-320.onnx",
      "size": 1270727,
      "sha256": "34cd7e60aeff28744c657de7a3dc64e872d506741de66987f3426f2b79f88017",
      "mime": "application/octet-stream"
    },
    {
      "name": "vision/utils/box_utils_numpy.py",
      "url": "assets/3.2.5/vision/utils/box_utils_numpy.py",
      "size": 4509,
      "sha256": "2b23965cd99e9e462e5ce3d52a86e816c17006514edba7ade11fb29688247aab",
      "mime": "text/x-python"
    },
    {
      "name": "voc-model-labels.txt",
      "url": "assets/3.2.5/voc-model-labels.txt",
      "size": 15,
      "sha256": "42f22f006e845cedefcbbbc76399d00a83a27831cb17a7b3fafcb9c60c814cd6",
      "mime": "text/plain"
    }
  ],
  "grading": {
    "mode": "completion-and-format-only"
  },
  "review": {
    "status": "approved",
    "notice": "由公开题面通用生成，未使用答案树。",
    "conflicts": []
  },
  "contentVersion": "6a69b733379b44f9"
}
