yolov8分类推理分析

YOLOv8是一种目标检测算法,其推理处理流程如下:

图像输入:首先将待检测的图像输入到模型中。

第一步:加载模型,可根据使用不同的硬件及框架使用不同的模型加载方式,在此就不做详细解释。
第二步:加载图片,对图片进行仿射变换,将图片调整到指定大小,并进行必要的图像变换和归一化操作,以便用于深度学习模型的输入。

    def preprocess_warpAffine(self, image):
       # 计算缩放比例scale,使得输入图像能够适应指定的输入大小(self.input_size_w, self.input_size_h)。
       # 缩放比例取width和height的最小值与相应的缩放因子之商。
        scale = min((self.input_size_w / image.shape[1], self.input_size_h / image.shape[0]))
        # 计算水平和垂直方向上的偏移量ox和oy,以便将缩放后的图像置于输入大小的中心位置。
        ox = (self.input_size_w  - scale * image.shape[1]) / 2
        oy = (self.input_size_h - scale * image.shape[0]) / 2
        # 构造仿射变换矩阵M,其中包含了缩放、平移操作。M是一个2x3的矩阵,包含了缩放因子和偏移量。
        M = np.array([
            [scale, 0, ox],
            [0, scale, oy]
        ], dtype=np.float32)
        # 使用cv2.warpAffine函数对输入图像进行仿射变换,得到缩放后的图像img_pre。
        # 这里使用了双线性插值方法(cv2.INTER_LINEAR)来处理变换过程中的像素值。
        img_pre = cv2.warpAffine(image, M, (self.input_size_w, self.input_size_h), flags=cv2.INTER_LINEAR,
                                borderMode=cv2.BORDER_CONSTANT, borderValue=(114, 114, 114))
        IM = cv2.invertAffineTransform(M)
		# 对缩放后的图像进行颜色通道顺序的反转(RGB转BGR),并将像素值范围从[0, 255]归一化到[0, 1]之间。
        img_pre = (img_pre[...,::-1] / 255.0).astype(np.float32)
        # 将图像的维度顺序从(HWC)转换为(CHW),并添加额外的批次维度,以满足模型输入的要求。
        img_pre = img_pre.transpose(2, 0, 1)[None]
        img_pre = np.array(img_pre)
        # 返回预处理后的图像img_pre和逆变换矩阵IM(用于后续处理结果的可视化)。
        return img_pre, IM

第三步:调用模型进行推理

  result = self.model.execute([img_pre, ])

第四步:对模型输出result进行转置操作,使其维度从[1, 8400, 84]变为[1, 84, 8400],结果保存在tmp中。

tmp = result[0].transpose(0, 2, 1)

第五步:调用self.postprocess方法对转置后的输出tmp进行后处理,得到检测框信息,保存在boxes中。

 boxes  = self.postprocess(tmp, IM)

这段代码完成了对模型输出结果的解析、筛选、坐标变换和NMS处理,最终得到经过后处理的预测框结果。

def postprocess(self, pred, IM=[], conf_thres=0.95, iou_thres=0.45):

        # 输入是模型推理的结果,即8400个预测框
        # 1,8400,84 [cx,cy,w,h,class*80]
        self.boxes = []
        # 遍历模型输出的预测结果pred,每个预测框包含了(cx, cy, w, h, class_scores)等信息。
        # 对每个预测框进行解析,计算预测框的左上角和右下角坐标,以及置信度和类别。
        for item in pred[0]:
            cx, cy, w, h = item[:4]
            label = item[4:].argmax()
            confidence = item[4 + label]
            # 根据设定的置信度阈值(conf_thres),筛选出置信度高于阈值的预测框
            if confidence < conf_thres:
                continue
            # 将筛选后的预测框信息保存到self.boxes中,格式为[left, top, right, bottom, confidence, label]
            left    = cx - w * 0.5
            top     = cy - h * 0.5
            right   = cx + w * 0.5
            bottom  = cy + h * 0.5
            self.boxes.append([left, top, right, bottom, confidence, label])
            
		# 对保存的预测框信息进行仿射逆变换操作,将预测框的坐标映射回原始图像空间
        self.boxes = np.array(self.boxes)
        # print(boxes)
        # 根据置信序对预测框进行排序。
        if len(self.boxes) == 0:
            self.boxes = []
        else:
            lr = self.boxes[:,[0, 2]]
            tb = self.boxes[:,[1, 3]]
            self.boxes[:,[0,2]] = IM[0][0] * lr + IM[0][2]
            self.boxes[:,[1,3]] = IM[1][1] * tb + IM[1][2]
            self.boxes = sorted(self.boxes.tolist(), key=lambda x:x[4], reverse=True)
        # 调用NMS(非极大值抑制)函数对预测框进行进一步处理,去除重叠度高的冗余框,最终返回处理后的预测框结果。
        return self.NMS(self.boxes, iou_thres)
    def NMS(self, boxes, iou_thres):

        remove_flags = [False] * len(boxes)

        keep_boxes = []
        for i, ibox in enumerate(boxes):
            if remove_flags[i]:
                continue

            keep_boxes.append(ibox)
            for j in range(i + 1, len(boxes)):
                if remove_flags[j]:
                    continue

                jbox = boxes[j]
                if(ibox[5] != jbox[5]):
                    continue
                if self.iou(ibox, jbox) > iou_thres:
                    remove_flags[j] = True
        return keep_boxes
    def iou(self, box1, box2):

        def area_box(box):
            return (box[2] - box[0]) * (box[3] - box[1])
        
        left,  top    = max(box1[:2],  box2[:2])
        right, bottom = min(box1[2:4], box2[2:4])
        union = max((right - left), 0) * max((bottom - top), 0)
        cross = area_box(box1) + area_box(box2) - union
        if cross == 0 or union == 0:
            return 0
        return union / cross
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值