[CV学习笔记]tensorrt加速篇之yolov5seg 实例分割

1. 前言

yolov5-7.0版本继续更新了实例分割的代码,其分割的精度与速度令人惊讶,本文将yolov5-seg进行tensorrt加速,并利用矩阵的方法对进行部分后处理.
在这里插入图片描述

实例分割原理:yolact

yolov5seg-cpp实现代码:Yolov5-instance-seg-tensorrt

cpp矩阵实现:algorithm-cpp

本文测试代码:https://github.com/Rex-LK/tensorrt_learning/tree/main/trt_cpp/src/trt/demo-infer/yolov5seg
欢迎正在学习或者想学的CV的同学进群一起讨论与学习,v:Rex1586662742,q群:468713665

2. 实例分割结果

yolov5-seg的结果分为两部分,一个是检测的结果,维度为25200*117,前85列为每个检测框结果,后32列为每个检测框的mask系数,另外一个是分割结果:原型mask,维度为32 * 160 * 160,实例分割的后处理就是将目标框里面的mask系数与原型mask进行加权求和,从而获得实例分割的效果。

2.1 检测结果后处理

通过置信度以及NMS可以挑选出最终的目标框,这个过程就不在过多的赘述了。

2.2 实例分割分割结果后处理

实例分割的后处理过程其实是一个矩阵相乘的过程,因此基于。。。实现cpp矩阵,在这里实现了后处理,原作者的代码是用过利用opencv里面的Mat来表示一个矩阵,然后进行一些矩阵的操作,而本文实现在在自定义Matrix上进行矩阵操作。
在这里插入图片描述

// 原型mask 32 * 160 * 160
float *seg_det = seg_out->cpu<float>();
vector<float> mask(seg_det, seg_det + segChannels * segWidth * segHeight);
// 矩阵表示
Matrix seg_proto(segChannels, segWidth * segHeight, mask);
for (int i = 0; i < box_result.size(); ++i) {
    // 可以将所有的mask系数放在一起,然后利用cuda进行加速计算

    // 每个目标框的mask系数 乘以原型mask 并取sigmod
    Matrix resSeg = (mygemm(box_result[i].mask_cofs,seg_proto).exp(-1) + 1.0).power(-1);
    
    Mat resMat(resSeg.data_);
    resMat = resMat.reshape(0,{segHeight,segWidth});
    // 如果图片预处理为直接resize,那么计算出来的resMat可以直接缩放回原图,
    // 如果是填充黑边的resize,可以参考原代码将原型mask恢复到原图大小
    resize(resMat, resMat, Size(INPUT_H,INPUT_W), INTER_NEAREST);
    // 获取原型mask里面目标框的区域
    Rect temp_rect = box_result[i].box;
    // 将目标框区域 大于0.5的值变为255
    cv::Mat binaryMat;
    inRange(resMat(temp_rect), 0.5, 1, binaryMat);
    box_result[i].boxMask = binaryMat;
    // cv::imwrite(to_string(i) + "_.jpg", b);
    }

下面为利用cpp实现的矩阵,可以实现一些简单的矩阵运算。

class Matrix{
public:
    Matrix();
    Matrix(int rows, int cols, const std::initializer_list<float>& pdata={});
    Matrix(int rows, int cols, const std::vector<float>&v);
    
    const float& operator()(int irow, int icol)const {return data_[irow * cols_ + icol];}
    float& operator()(int irow, int icol){return data_[irow * cols_ + icol];}
    Matrix element_wise(const std::function<float(float)> &func) const;
    Matrix operator*(const Matrix &value) const;
    Matrix operator*(float value) const;
    Matrix operator+(float value) const;
    Matrix operator-(float value) const;
    Matrix operator/(float value) const;
    int rows() const{return rows_;}
    int cols() const{return cols_;}
    Matrix view(int rows, int cols) const;
    Matrix power(float y) const;
    float reduce_sum() const;
    float* ptr() const{return (float*)data_.data();}
    Matrix exp(float value);
public:
    int rows_ = 0;
    int cols_ = 0;
    std::vector<float> data_;
};

3. 测试

下载本代码
修改CMakeLists.txt 里面的cuda、tensorrt、protobuf路径
修改main.cpp里面的路径,修改yolov5seg.cu里面的模型路径以及图片路径。
cd trt_cpp
mkdir build && cd biild
cmake … && make -j
./…/workspace/demo_infer
测试结果如下:
在这里插入图片描述

4. 总结

本次学习了yolov5实例分割的原理以及代码,通过对比原理以及代码的步骤,弄清楚了yolov5是如何实现实例的分割任务的,如果本文对各位有用,麻烦到github点个小star。

Yolov8-seg是一种基于目标检测和语义分割的实例分割方法。在Yolov8-seg中,首先使用YoloV5目标检测器检测图像中的物体,然后将检测到的物体传递给语义分割模型,以生成每个物体的分割掩膜。 如果您想提取分割掩膜,您可以按照以下步骤进行操作: 1. 使用Yolov8-seg模型检测图像中的物体。 2. 将检测到的物体传递给语义分割模型,以生成每个物体的分割掩膜。 3. 对于每个检测到的物体,提取其对应的分割掩膜。 4. 将分割掩膜应用于原始图像,以提取物体的图像部分。 您可以使用Python和深度学习框架(如PyTorch或TensorFlow)来实现这些步骤。以下是一个示例代码片段,用于提取Yolov8-seg模型生成的分割掩膜并将其应用于原始图像: ```python import cv2 import torch # Load Yolov8-seg and semantic segmentation models yolo_model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True) seg_model = torch.hub.load('pytorch/vision', 'deeplabv3_resnet101', pretrained=True) # Load image img = cv2.imread('image.jpg') # Detect objects using Yolov8-seg model results = yolo_model(img) # Extract segmentation masks for each detected object masks = [] for result in results.xyxy: box = result[:4].tolist() mask = seg_model(img, box=box)['out'] mask = torch.argmax(mask.squeeze(), dim=0).cpu().numpy() masks.append(mask) # Apply segmentation masks to original image to extract object parts object_parts = [] for mask in masks: object_part = cv2.bitwise_and(img, img, mask=mask) object_parts.append(object_part) # Display extracted object parts for object_part in object_parts: cv2.imshow('Object part', object_part) cv2.waitKey(0) ``` 请注意,此代码片段仅用于示例目的,您需要根据自己的需求进行修改和优化。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rex晚枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值