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模型进行目标检测的函数,下面将详细解释每个部分。

函数说明

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

主要逻辑

1. 图像大小调整

int neww = 0, newh = 0, padw = 0, padh = 0;

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

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

// 创建用于神经网络输入的 blob
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. 设置网络输入并前向传播

// 设置网络输入
this->net.setInput(blob);

std::vector<cv::Mat> outs;

// 前向传播获取输出
this->net.forward(outs, this->net.getUnconnectedOutLayersNames());
  • 将blob作为神经网络输入,通过前向传播得到输出,输出保存在向量outs中。

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

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

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

std::vector<int> ids; // 存储类别 ID 的向量
std::vector<float> confs; // 存储置信度的向量
std::vector<cv::Rect> boxes; // 存储边界框的向量

float ratiow = (float)frame.cols / neww; // 原始宽度与新宽度的比例
float ratioh = (float)frame.rows / newh; // 原始高度与新高度的比例

float* pdata = (float*)outs[0].data;

for (int n = 0; n < numproposal; ++n)
{
    float maxss = 0.0;
    int idp = 0;

    for (int k = 0; k < nout - 4; ++k)
    {
        if (pdata[k + 4] > maxss)
        {
            maxss = pdata[k + 4];
            idp = k;
        }
    }

    if (maxss >= this->confThreshold)
    {
        float cx = (pdata[0] - padw) * ratiow;
        float cy = (pdata[1] - padh) * ratioh;

        float w = pdata[2] * ratiow;
        float h = pdata[3] * ratioh;

        int left = int(cx - 0.5 * w);
        int top = int(cy - 0.5 * h);

        boxes.push_back(cv::Rect(left, top, int(w), int(h)));
        confs.push_back(maxss);
        ids.push_back(idp);
    }

    pdata += nout;
}
  • 遍历每个提案,通过比较置信度来确定类别ID。如果最大置信度高于设定阈值,则计算相应边界框的位置并存储类别ID、置信度及边界框信息。

6. 非极大抑制(NMS)

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

7. 绘制检测结果

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

总结

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


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

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?