ZBLOG

详解下面代码 /** * @brief 检测图像中的目标。 * * 此函数接收一帧图像,使用 YOLOv8 模型进行目标检测,并绘制检测结果。 * * @param frame 输入的 cv::Mat 类型图像,表示待检测的图像帧。 */ void YOLOV8::detect(cv::Mat& frame) { int neww = 0, newh = 0, padw = 0, padh = 0; // 调整输入图像的大小 cv::Mat simg = this->...

这段代码是使用YOLOv8模型进行目标检测的函数,下面将详细解释每个部分。

函数说明

  1. /**
  2. * @brief 检测图像中的目标。
  3. *
  4. * 此函数接收一帧图像,使用 YOLOv8 模型进行目标检测,并绘制检测结果。
  5. *
  6. * @param frame 输入的 cv::Mat 类型图像,表示待检测的图像帧。
  7. */
  • @brief:简单描述了该函数的目的,即检测输入图像中的目标。
  • @param:说明了输入参数frame是一个OpenCV的cv::Mat类型,表示待处理的图像。

主要逻辑

1. 图像大小调整

  1. int neww = 0, newh = 0, padw = 0, padh = 0;
  2. // 调整输入图像的大小
  3. cv::Mat simg = this->resize_img(frame, &neww, &newh, &padw, &padh);
  • resize_img是一个自定义函数,用于调整输入图像大小以适应网络要求,同时计算出新的宽度、高度以及填充量(如果有的话)。

2. 创建Blob用于神经网络输入

  1. // 创建用于神经网络输入的 blob
  2. cv::Mat blob = cv::dnn::blobFromImage(simg, 1.0 / 255.0, cv::Size(this->inpHeight, this->inpWidth), cv::Scalar(0, 0, 0), true, false);
  • 使用OpenCV DNN模块创建一个blob,该blob会被用作神经网络的输入。将图像归一化到[0,1]区间,并按指定尺寸调整(由成员变量inpHeightinpWidth决定)。

3. 设置网络输入并前向传播

  1. // 设置网络输入
  2. this->net.setInput(blob);
  3. std::vector<cv::Mat> outs;
  4. // 前向传播获取输出
  5. this->net.forward(outs, this->net.getUnconnectedOutLayersNames());
  • 将blob作为神经网络输入,通过前向传播得到输出,输出保存在向量outs中。

4. 获取提案数量和重塑输出矩阵形状

  1. int numproposal = outs[0].size[2]; // 获取提案数量
  2. int nout = outs[0].size[1]; // 获取输出维度
  3. outs[0] = outs[0].reshape(0, nout); // 重塑输出矩阵形状
  4. cv::transpose(outs[0], outs[0]); // 转置输出矩阵
  • 从输出中获取提案数量和维度,然后重塑并转置以便后续处理。

5. 提取类别ID、置信度和边界框信息

  1. std::vector<int> ids; // 存储类别 ID 的向量
  2. std::vector<float> confs; // 存储置信度的向量
  3. std::vector<cv::Rect> boxes; // 存储边界框的向量
  4. float ratiow = (float)frame.cols / neww; // 原始宽度与新宽度的比例
  5. float ratioh = (float)frame.rows / newh; // 原始高度与新高度的比例
  6. float* pdata = (float*)outs[0].data;
  7. for (int n = 0; n < numproposal; ++n)
  8. {
  9. float maxss = 0.0;
  10. int idp = 0;
  11. for (int k = 0; k < nout - 4; ++k)
  12. {
  13. if (pdata[k + 4] > maxss)
  14. {
  15. maxss = pdata[k + 4];
  16. idp = k;
  17. }
  18. }
  19. if (maxss >= this->confThreshold)
  20. {
  21. float cx = (pdata[0] - padw) * ratiow;
  22. float cy = (pdata[1] - padh) * ratioh;
  23. float w = pdata[2] * ratiow;
  24. float h = pdata[3] * ratioh;
  25. int left = int(cx - 0.5 * w);
  26. int top = int(cy - 0.5 * h);
  27. boxes.push_back(cv::Rect(left, top, int(w), int(h)));
  28. confs.push_back(maxss);
  29. ids.push_back(idp);
  30. }
  31. pdata += nout;
  32. }
  • 遍历每个提案,通过比较置信度来确定类别ID。如果最大置信度高于设定阈值,则计算相应边界框的位置并存储类别ID、置信度及边界框信息。

6. 非极大抑制(NMS)

  1. // 应用非极大抑制(NMS)以消除冗余框
  2. std::vector<int> indices;
  3. cv::dnn::NMSBoxes(boxes, confs, this->confThreshold, this->nmsThreshold, indices);
  • 使用非极大抑制算法消除冗余框,以减少重复检测到同一物体时产生的不必要的信息。

7. 绘制检测结果

  1. // 绘制最终检测到的目标结果
  2. for (int idx : indices)
  3. {
  4. this->drawPred(frame, boxes[idx], ids[idx], confs[idx]);
  5. }
  • 根据NMS后的索引绘制最终检测出的物体,将其显示在原始帧上。

总结

整体来看,这段代码实现了对给定图像的一次完整的目标检测流程,包括预处理、前向推理、后处理及可视化,是利用YOLOv8进行实时物体识别的重要组成部分。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=20123

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?