国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

yolov5分割+檢測(cè)c++ qt 中部署,以opencv方式(詳細(xì)代碼(全)+復(fù)制可用)

這篇具有很好參考價(jià)值的文章主要介紹了yolov5分割+檢測(cè)c++ qt 中部署,以opencv方式(詳細(xì)代碼(全)+復(fù)制可用)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1:版本說(shuō)明:

qt 5.12.10

opencv 4.5.3 (yolov5模型部署要求opencv>4.5.0)

2:檢測(cè)的代碼

yolo.h
#pragma once
#include<iostream>
#include<cmath>
#include<vector>
#include <opencv2/opencv.hpp>
#include<opencv2/dnn.hpp>

class yolo
{
public:
    yolo() {}
    ~yolo(){}
    bool readModel(cv::dnn::Net &net,std::string &netpath, bool isCuda);
    struct Output
    {
        int id;//結(jié)果類(lèi)別id
        float confidence;//結(jié)果置信度
        cv::Rect box;//矩形框

        int ship_id;//船的id
        int truck_id;//人的id
        int person_id;//人的id
         int  staring_id;//車(chē)的id
        int  forklift_id;//車(chē)的id

        int unload_car_id;//船的id
        int load_car_id;//人的id
        int  private_car_id;//車(chē)的id

    };
    struct Output_max_confidence
    {
        int id;//結(jié)果類(lèi)別id
        float confidence;//結(jié)果置信度
        cv::Rect box;//矩形框

    };
    int ship_num;//總?cè)藬?shù)
    int  car_trucks_num;//總車(chē)數(shù)
    int person_num;//總船數(shù)
    int stacking_area_num;//總?cè)藬?shù)
    int  car_forklift_num;//總車(chē)數(shù)
    int unload_car_num;//總船數(shù)
    int load_car_num;//總?cè)藬?shù)
    int  car_private_num;//總車(chē)數(shù)

    bool Detect(cv::Mat &SrcImg, cv::dnn::Net &net, std::vector<Output> &output);
    void drawPred(cv::Mat &img, std::vector<Output> result, std::vector<cv::Scalar> color);

    //參數(shù)為私有參數(shù),當(dāng)然也可以是設(shè)置成公開(kāi)或者保護(hù)。
    Output_max_confidence get_only_one_max_confidence(std::vector<Output> result);
    float findMax(std::vector<float> vec);

    int getPositionOfMax(std::vector<float> vec, int max);
\
    void drawRect(cv::Mat &img, yolo::Output_max_confidence result);
private:
    //計(jì)算歸一化函數(shù)
    float Sigmoid(float x) {
        return static_cast<float>(1.f / (1.f + exp(-x)));
    }
    //anchors
    const float netAnchors[3][6] = { { 10.0, 13.0, 16.0, 30.0, 33.0, 23.0 },{ 30.0, 61.0, 62.0, 45.0, 59.0, 119.0 },{ 116.0, 90.0, 156.0, 198.0, 373.0, 326.0 } };
    //stride
    const float netStride[3] = { 8.0, 16.0, 32.0 };
    const int netWidth = 640; //網(wǎng)絡(luò)模型輸入大小
    const int netHeight = 640;
    float nmsThreshold = 0.02;
    float boxThreshold = 0.05;
    float classThreshold = 0.45;
    //類(lèi)名
//    std::vector<std::string> className = { "car", "person"};
//    std::vector<std::string> className = { "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
//                                           "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
//                                           "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
//                                           "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
//                                           "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
//                                           "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
//                                           "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
//                                           "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
//                                           "hair drier", "toothbrush"};
    std::vector<std::string> className = { "ship","car_trucks","person","stacking_area","car_forklift","unload_car","load_car","car_private"};//"car","person"


};
yolo.cpp
#include "yolo.h"
#include<iostream>
#include<cmath>
#include<vector>
#include <opencv2/opencv.hpp>
#include<opencv2/dnn.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
#pragma execution_character_set("utf-8");
bool yolo::readModel(Net &net, string &netPath, bool isCuda = false) {
    try {
        net = readNetFromONNX(netPath);
        cout<<"load net successfull!"<<endl;
    }
    catch (const std::exception&) {
        return false;
    }
    //cuda
    if (isCuda) {
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
    }
    //cpu
    else {
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
    }
    return true;
}


bool yolo::Detect(Mat &SrcImg, Net &net, vector<Output> &output) {
    Mat blob;
    int col = SrcImg.cols;
    int row = SrcImg.rows;
    int maxLen = MAX(col, row);
    Mat netInputImg = SrcImg.clone();
    if (maxLen > 1.2*col || maxLen > 1.2*row) {
        Mat resizeImg = Mat::zeros(maxLen, maxLen, CV_8UC3);
        SrcImg.copyTo(resizeImg(Rect(0, 0, col, row)));
        netInputImg = resizeImg;
    }
    blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(104, 117, 123), true, false);
    blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(0, 0,0), true, false);//如果訓(xùn)練集未對(duì)圖片進(jìn)行減去均值操作,則需要設(shè)置為這句
    //blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(114, 114,114), true, false);
    net.setInput(blob);
    std::vector<cv::Mat> netOutputImg;
    //vector<string> outputLayerName{"345","403", "461","output" };
    //net.forward(netOutputImg, outputLayerName[3]); //獲取output的輸出
    net.forward(netOutputImg, net.getUnconnectedOutLayersNames());

    //接上面
    std::vector<int> classIds;//結(jié)果id數(shù)組
    std::vector<float> confidences;//結(jié)果每個(gè)id對(duì)應(yīng)置信度數(shù)組
    std::vector<cv::Rect> boxes;//每個(gè)id矩形框
    std::vector<int> ship_id;//記錄下人數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> trucks_id;//記錄下車(chē)數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> person_id;//記錄下人數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> stacking_id;//記錄下車(chē)數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> forklift_id;//記錄下人數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> unload_car_id;//記錄下車(chē)數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> load_car_id;//記錄下人數(shù)的id號(hào)碼----補(bǔ)充
    std::vector<int> car_private_id;//記錄下車(chē)數(shù)的id號(hào)碼----補(bǔ)充

    float ratio_h = (float)netInputImg.rows / netHeight;
    float ratio_w = (float)netInputImg.cols / netWidth;
    int net_width = className.size() + 5;  //輸出的網(wǎng)絡(luò)寬度是類(lèi)別數(shù)+5
    float* pdata = (float*)netOutputImg[0].data;
    for (int stride = 0; stride < 3; stride++) {    //stride
        int grid_x = (int)(netWidth / netStride[stride]);
        int grid_y = (int)(netHeight / netStride[stride]);
        for (int anchor = 0; anchor < 3; anchor++) { //anchors
            const float anchor_w = netAnchors[stride][anchor * 2];
            const float anchor_h = netAnchors[stride][anchor * 2 + 1];
            for (int i = 0; i < grid_y; i++) {
                for (int j = 0; j < grid_y; j++) {
                    //float box_score = Sigmoid(pdata[4]);//獲取每一行的box框中含有某個(gè)物體的概率 yolo5.0
                    float box_score = pdata[4];//獲取每一行的box框中含有某個(gè)物體的概率 yolo6.0
                    if (box_score > boxThreshold) {
                        //為了使用minMaxLoc(),將85長(zhǎng)度數(shù)組變成Mat對(duì)象
                        cv::Mat scores(1, className.size(), CV_32FC1, pdata + 5);
                        Point classIdPoint;
                        double max_class_socre;
                        minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
                        //max_class_socre = Sigmoid((float)max_class_socre);  //yolo 5.0
                        max_class_socre = (float)max_class_socre;    //yolo 6.0
                        if (max_class_socre > classThreshold) {
                            //rect [x,y,w,h]
                            //yolov5 5.0格式
                            //float x = (Sigmoid(pdata[0]) * 2.f - 0.5f + j) * netStride[stride];  //x
                            //float y = (Sigmoid(pdata[1]) * 2.f - 0.5f + i) * netStride[stride];   //y
                            //float w = powf(Sigmoid(pdata[2]) * 2.f, 2.f) * anchor_w;   //w
                            //float h = powf(Sigmoid(pdata[3]) * 2.f, 2.f) * anchor_h;  //h
                            //yolov5 6.0格式:
                            float x = pdata[0];// (Sigmoid(pdata[0]) * 2.f - 0.5f + j) * netStride[stride];  //x
                            float y = pdata[1];// (Sigmoid(pdata[1]) * 2.f - 0.5f + i) * netStride[stride];   //y
                            float w = pdata[2];// powf(Sigmoid(pdata[2]) * 2.f, 2.f) * anchor_w;   //w
                            float h = pdata[3];// powf(Sigmoid(pdata[3]) * 2.f, 2.f) * anchor_h;  //h
                            int left = (x - 0.5*w)*ratio_w;
                            int top = (y - 0.5*h)*ratio_h;

                            classIds.push_back(classIdPoint.x);
                            confidences.push_back(max_class_socre*box_score);
                            boxes.push_back(Rect(left, top, int(w*ratio_w), int(h*ratio_h)));

                        }
                    }
                    pdata += net_width;//指針移到下一行
                }
            }
        }
    }

    //接上面執(zhí)行非最大抑制以消除具有較低置信度的冗余重疊框(NMS)
    vector<int> nms_result;
    int ship_id_ini=0;//初始化人數(shù),
    int trucks_id_ini=0;//初始化人數(shù),
    int person_id_ini=0;//初始化車(chē)輛數(shù)
    int stacking_id_ini=0;//初始化車(chē)輛數(shù)

    int forklift_id_ini=0;//初始化車(chē)輛數(shù)
    int unload_car_id_ini=0;//初始化車(chē)輛數(shù)
    int load_car_id_ini=0;//初始化車(chē)輛數(shù)
    int car_private_id_ini=0;//初始化車(chē)輛數(shù)


    NMSBoxes(boxes, confidences, classThreshold, nmsThreshold, nms_result);
    for (int i = 0; i < nms_result.size(); i++) {
        int idx = nms_result[i];
        Output result;
        result.id = classIds[idx];
        result.confidence = confidences[idx];
        result.box = boxes[idx];

        output.push_back(result);
        if(result.id==0)//當(dāng)類(lèi)別數(shù)等于船的時(shí)候
        {
            result.ship_id=ship_id_ini;//當(dāng)船等于
            ship_id_ini=ship_id_ini+1;

        }
        if(result.id==1)//當(dāng)類(lèi)別數(shù)等于車(chē)的時(shí)候
        {
            result.truck_id=trucks_id_ini;//當(dāng)車(chē)數(shù)等于
            trucks_id_ini=trucks_id_ini+1;
        }
        if(result.id==2)//當(dāng)類(lèi)別數(shù)等于人的時(shí)候
        {
            result.person_id=person_id_ini;//當(dāng)人數(shù)等于
            person_id_ini=person_id_ini+1;

        }if(result.id==3)//當(dāng)類(lèi)別數(shù)等于人的時(shí)候
        {
            result.staring_id=stacking_id_ini;//當(dāng)人數(shù)等于
            stacking_id_ini=stacking_id_ini+1;

        }
        if(result.id==4)//當(dāng)類(lèi)別數(shù)等于人的時(shí)候
        {
            result.forklift_id=forklift_id_ini;//當(dāng)人數(shù)等于
            forklift_id_ini=forklift_id_ini+1;

        }
        if(result.id==5)//當(dāng)類(lèi)別數(shù)等于人的時(shí)候
        {
            result.unload_car_id=unload_car_id_ini;//當(dāng)人數(shù)等于
            unload_car_id_ini=unload_car_id_ini+1;

        }
        if(result.id==6)//當(dāng)類(lèi)別數(shù)等于人的時(shí)候
        {
            result.load_car_id=load_car_id_ini;//當(dāng)人數(shù)等于
            load_car_id_ini=load_car_id_ini+1;

        }
        if(result.id==7)//當(dāng)類(lèi)別數(shù)等于人的時(shí)候
        {
            result.private_car_id=car_private_id_ini;//當(dāng)人數(shù)等于
            car_private_id_ini=car_private_id_ini+1;

        }

    }

    ship_num=ship_id_ini;
    car_trucks_num=trucks_id_ini;
    person_num=person_id_ini;

    stacking_area_num=stacking_id_ini;
    car_forklift_num=forklift_id_ini ;//總車(chē)數(shù)
    unload_car_num=unload_car_id_ini;//總船數(shù)
    load_car_num=load_car_id_ini;//總?cè)藬?shù)
    car_private_num=car_private_id_ini;//總車(chē)數(shù)

    if (output.size())
        return true;
    else
        return false;

}//這個(gè)括號(hào)是最后

void yolo::drawPred(Mat &img, vector<Output> result, vector<Scalar> color)
{

    for (int i = 0; i < result.size(); i++)
    {
        int left, top;
        left = result[i].box.x;
        top = result[i].box.y;
        int color_num = i;
        rectangle(img, result[i].box, color[result[i].id], 2, 8);
        //      string label = className[result[i].id] + ":" + to_string(result[i].confidence)+" id:"+to_string(result[i].person_id);
        string label;
        if(result[i].id==0)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==1)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==2)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==3)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==4)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==5)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==6)
        {
            label = className[result[i].id] ;
        }
        if(result[i].id==7)
        {
            label = className[result[i].id];
        }
        int baseLine;
        Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
        top = max(top, labelSize.height);
        //rectangle(frame, Point(left, top - int(1.5 * labelSize.height)), Point(left + int(1.5 * labelSize.width), top + baseLine), Scalar(0, 255, 0), FILLED);
        putText(img, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 1, color[result[i].id], 2);
    }
    //imshow("res", img);
    //imwrite("./result.jpg", img);
    //waitKey();
    //destroyAllWindows();
}

//這個(gè)是針對(duì)悍馬的畫(huà)框
void yolo::drawRect(cv::Mat &img, yolo::Output_max_confidence result)
{

    int left, top;
    left = result.box.x;
    top = result.box.y;

    rectangle(img, result.box,Scalar(0,0,255) , 2, 8);
    //      string label = className[result[i].id] + ":" + to_string(result[i].confidence)+" id:"+to_string(result[i].person_id);
    string label;
    if(result.id==0)
    {
        label = className[result.id];
    }
    int baseLine;
    Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
    top = max(top, labelSize.height);
    //rectangle(frame, Point(left, top - int(1.5 * labelSize.height)), Point(left + int(1.5 * labelSize.width), top + baseLine), Scalar(0, 255, 0), FILLED);
    putText(img, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 2,Scalar(0,0,255), 2);

}

float yolo::findMax(std::vector<float> vec) {
    float max = -999;
    for (auto v : vec) {
        if (max < v) max = v;
    }
    return max;
}

int yolo::getPositionOfMax(std::vector<float> vec, int max) {
    auto distance = find(vec.begin(), vec.end(), max);
    return distance - vec.begin();
}

//返回一個(gè)最大置信度的框
yolo::Output_max_confidence yolo::get_only_one_max_confidence(std::vector<Output> result)
{

    std::vector<float>confidence;
    for (int i = 0; i < result.size(); i++)
    {
        confidence.push_back(result.at(i).confidence);
        //        cout<<"result.at(i).confidence"<<result.at(i).confidence<<endl;
    }
    float maxConfidence=findMax(confidence);
    int position = result.size()-getPositionOfMax(confidence, maxConfidence);
    //    cout<<"max_confidengce"<<maxConfidence<<"position:"<<position<<endl;
    Output_max_confidence o_m_c;
    o_m_c.confidence=maxConfidence;
    o_m_c.id=position;
    o_m_c.box=result.at(position).box;
    return o_m_c ;

}
檢測(cè)的調(diào)用代碼測(cè)試案例

這段調(diào)用的例子,只要把frame 改成你們自己的圖片即可

yolo test;    //創(chuàng)建yolo類(lèi)
cv::dnn::Net net; //創(chuàng)建yolo網(wǎng)絡(luò)
vector< cv::Scalar> color;//Bounding Box顏色 
QString Filename_onnx="quanjingbest.onnx";
cv::String filename_onnx=Filename_onnx.toStdString();
vector<yolo::Output>result_video;
test.readModel(net,filename_onnx,false);
for (int i = 0; i < 80; i++) {
        int b = rand() % 256;
        int g = rand() % 256;
        int r = rand() % 256;
        color.push_back( cv::Scalar(b, g, r));
    }

cv::Mat frame=cv::imread("D://1.jpg");
if(test.Detect(frame, net, result_video))          //調(diào)用YOLO模型檢測(cè)
      test.drawPred(frame, result_video, color);
cv::imshow("a",frame);
cv::waitKey(1);

4:分割的主要代碼

YoloSeg.h
#ifndef YOLO_SEG_H
#define YOLO_SEG_H


#pragma once
#include<iostream>
#include<opencv2/opencv.hpp>
#include "yolov5_seg_utils.h"

class YoloSeg {
public:
    YoloSeg() {
    }
    ~YoloSeg() {}
    /** \brief Read onnx-model
    * \param[out] read onnx file into cv::dnn::Net
    * \param[in] modelPath:onnx-model path
    * \param[in] isCuda:if true and opencv built with CUDA(cmake),use OpenCV-GPU,else run it on cpu.
    */
    bool ReadModel(cv::dnn::Net& net, std::string& netPath, bool isCuda);
    /** \brief  detect.
    * \param[in] srcImg:a 3-channels image.
    * \param[out] output:detection results of input image.
    */
    bool Detect(cv::Mat& srcImg, cv::dnn::Net& net, std::vector<OutputSeg>& output);

#if(defined YOLO_P6 && YOLO_P6==true)

    const int _netWidth = 1280;  //ONNX圖片輸入寬度
    const int _netHeight = 1280; //ONNX圖片輸入高度
    const int _segWidth = 320;  //_segWidth=_netWidth/mask_ratio
    const int _segHeight = 320;
    const int _segChannels = 32;
#else

    const int _netWidth = 640;   //ONNX圖片輸入寬度
    const int _netHeight = 640;  //ONNX圖片輸入高度
    const int _segWidth = 160;    //_segWidth=_netWidth/mask_ratio
    const int _segHeight = 160;
    const int _segChannels = 32;

#endif // YOLO_P6

    float _classThreshold = 0.25;
    float _nmsThreshold = 0.45;
    float _maskThreshold = 0.5;

public:
    std::vector<std::string> _className = { "steel"};//類(lèi)別名,換成自己的模型需要修改此項(xiàng)
};

#endif // YOLO_SEG_H
YoloSeg.cpp
#include "yolo_seg.h"

#include"yolo_seg.h"
using namespace std;
using namespace cv;
using namespace cv::dnn;

bool YoloSeg::ReadModel(Net& net, string& netPath, bool isCuda = false) {
    try {
        net = readNet(netPath);
#if CV_VERSION_MAJOR==4 &&CV_VERSION_MINOR==7&&CV_VERSION_REVISION==0
        net.enableWinograd(false);  //bug of opencv4.7.x in AVX only platform ,https://github.com/opencv/opencv/pull/23112 and https://github.com/opencv/opencv/issues/23080
        //net.enableWinograd(true);		//If your CPU supports AVX2, you can set it true to speed up
#endif
    }
    catch (const std::exception&) {
        return false;
    }
    if (isCuda) {
        //cuda
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); //or DNN_TARGET_CUDA_FP16
    }
    else {
        //cpu
        cout << "Inference device: CPU" << endl;
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
    }
    return true;
}


bool YoloSeg::Detect(Mat& srcImg, Net& net, vector<OutputSeg>& output) {
    Mat blob;
    output.clear();
    int col = srcImg.cols;
    int row = srcImg.rows;
    Mat netInputImg;
    Vec4d params;
    LetterBox(srcImg, netInputImg, params, cv::Size(_netWidth, _netHeight));
    blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(_netWidth, _netHeight), cv::Scalar(0, 0, 0), true, false);
    //**************************************************************************************************************************************************/
    //如果在其他設(shè)置沒(méi)有問(wèn)題的情況下但是結(jié)果偏差很大,可以嘗試下用下面兩句語(yǔ)句
    // If there is no problem with other settings, but results are a lot different from  Python-onnx , you can try to use the following two sentences
    //
    //$ blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(_netWidth, _netHeight), cv::Scalar(104, 117, 123), true, false);
    //$ blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(_netWidth, _netHeight), cv::Scalar(114, 114,114), true, false);
    //****************************************************************************************************************************************************/
    net.setInput(blob);
    std::vector<cv::Mat> net_output_img;
    //*********************************************************************************************************************************
    //net.forward(net_output_img, net.getUnconnectedOutLayersNames());
    //opencv4.5.x和4.6.x這里輸出不一致,推薦使用下面的固定名稱(chēng)輸出
    // 如果使用net.forward(net_output_img, net.getUnconnectedOutLayersNames()),需要確認(rèn)下net.getUnconnectedOutLayersNames()返回值中output0在前,output1在后,否者出錯(cuò)
    //
    // The outputs of opencv4.5.x and 4.6.x are inconsistent.Please make sure "output0" is in front of "output1" if you use net.forward(net_output_img, net.getUnconnectedOutLayersNames())
    //*********************************************************************************************************************************
    vector<string> output_layer_names{ "output0","output1" };
    net.forward(net_output_img, output_layer_names); //獲取output的輸出

    std::vector<int> class_ids;//結(jié)果id數(shù)組
    std::vector<float> confidences;//結(jié)果每個(gè)id對(duì)應(yīng)置信度數(shù)組
    std::vector<cv::Rect> boxes;//每個(gè)id矩形框
    std::vector<vector<float>> picked_proposals;  //output0[:,:, 5 + _className.size():net_width]===> for mask
    int net_width = _className.size() + 5 + _segChannels;// 80 + 5 + 32 = 117
    int out0_width= net_output_img[0].size[2];

//    assert(net_width == out0_width, "Error Wrong number of _className or _segChannels");  //模型類(lèi)別數(shù)目不對(duì)或者_(dá)segChannels設(shè)置錯(cuò)誤
    int net_height = net_output_img[0].size[1];// 25200
    float* pdata = (float*)net_output_img[0].data;
    for (int r = 0; r < net_height; r++) {    //lines
        float box_score = pdata[4];
        if (box_score >= _classThreshold) {
            cv::Mat scores(1, _className.size(), CV_32FC1, pdata + 5); //  可是 后面不只是有80個(gè)類(lèi)別的概率;
            Point classIdPoint;
            double max_class_socre;
            minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
            max_class_socre = (float)max_class_socre;
            if (max_class_socre >= _classThreshold) {

                vector<float> temp_proto(pdata + 5 + _className.size(), pdata + net_width); // Mask Coeffcients,mask的掩碼系數(shù)
                picked_proposals.push_back(temp_proto);
                //rect [x,y,w,h]
                float x = (pdata[0] - params[2]) / params[0];  //x
                float y = (pdata[1] - params[3]) / params[1];  //y
                float w = pdata[2] / params[0];  //w
                float h = pdata[3] / params[1];  //h
                int left = MAX(int(x - 0.5 * w + 0.5), 0);
                int top = MAX(int(y - 0.5 * h + 0.5), 0);
                class_ids.push_back(classIdPoint.x);
                confidences.push_back(max_class_socre * box_score);
                boxes.push_back(Rect(left, top, int(w + 0.5), int(h + 0.5)));
            }
        }
        pdata += net_width;//下一行

    }

    //NMS
    vector<int> nms_result;
    cv::dnn::NMSBoxes(boxes, confidences, _classThreshold, _nmsThreshold, nms_result);
    std::vector<vector<float>> temp_mask_proposals;
    Rect holeImgRect(0, 0, srcImg.cols, srcImg.rows);
    for (int i = 0; i < nms_result.size(); ++i) {

        int idx = nms_result[i];
        OutputSeg result;
        result.id = class_ids[idx];
        result.confidence = confidences[idx];
        result.box = boxes[idx] & holeImgRect;
        temp_mask_proposals.push_back(picked_proposals[idx]);
        output.push_back(result);
    }

    MaskParams mask_params;
    mask_params.params = params;
    mask_params.srcImgShape = srcImg.size();
    for (int i = 0; i < temp_mask_proposals.size(); ++i) {
        GetMask2(Mat(temp_mask_proposals[i]).t(), net_output_img[1], output[i], mask_params); // 注意這里是net_output_img[1],為原型mask
    }


    //******************** ****************
    // 老版本的方案,如果上面GetMask2出錯(cuò),建議使用這個(gè)。
    // If the GetMask2() still reports errors , it is recommended to use GetMask().
    // Mat mask_proposals;
    //for (int i = 0; i < temp_mask_proposals.size(); ++i)
    //	mask_proposals.push_back(Mat(temp_mask_proposals[i]).t());
    //GetMask(mask_proposals, net_output_img[1], output, mask_params);
    //*****************************************************/


    if (output.size())
        return true;
    else
        return false;
}
yolov5_seg_utils.h
#ifndef YOLOV5_SEG_UTILS_H
#define YOLOV5_SEG_UTILS_H


#pragma once
#include<iostream>
#include <numeric>
#include<opencv2/opencv.hpp>

#define YOLO_P6 false //是否使用P6模型
#define ORT_OLD_VISON 12  //ort1.12.0 之前的版本為舊版本API

struct OutputSeg {
    int id;             //結(jié)果類(lèi)別id
    float confidence;   //結(jié)果置信度
    cv::Rect box;       //矩形框
    cv::Mat boxMask;       //矩形框內(nèi)mask,節(jié)省內(nèi)存空間和加快速度
};
struct MaskParams {
    int segChannels = 32;
    int segWidth = 160;
    int segHeight = 160;
    int netWidth = 640;
    int netHeight = 640;
    float maskThreshold = 0.5;
    cv::Size srcImgShape;
    cv::Vec4d params;

};
bool CheckParams(int netHeight, int netWidth, const int* netStride, int strideSize);
void DrawPred(cv::Mat& img, std::vector<OutputSeg> result, std::vector<std::string> classNames, std::vector<cv::Scalar> color);
void LetterBox(const cv::Mat& image, cv::Mat& outImage,
    cv::Vec4d& params, //[ratio_x,ratio_y,dw,dh]
    const cv::Size& newShape = cv::Size(640, 640),
    bool autoShape = false,
    bool scaleFill = false,
    bool scaleUp = true,
    int stride = 32,
    const cv::Scalar& color = cv::Scalar(114, 114, 114));
void GetMask(const cv::Mat& maskProposals, const cv::Mat& maskProtos, std::vector<OutputSeg>& output, const MaskParams& maskParams);
void GetMask2(const cv::Mat& maskProposals, const cv::Mat& maskProtos, OutputSeg& output, const MaskParams& maskParams);

#endif // YOLOV5_SEG_UTILS_H
?yolov5_seg_utils.cpp
#include "yolov5_seg_utils.h"

#pragma once
#include "yolov5_seg_utils.h"
using namespace cv;
using namespace std;
bool CheckParams(int netHeight, int netWidth, const int* netStride, int strideSize) {
    if (netHeight % netStride[strideSize - 1] != 0 || netWidth % netStride[strideSize - 1] != 0)
    {
        cout << "Error:_netHeight and _netWidth must be multiple of max stride " << netStride[strideSize - 1] << "!" << endl;
        return false;
    }
    return true;
}

void LetterBox(const cv::Mat& image, cv::Mat& outImage, cv::Vec4d& params, const cv::Size& newShape,
    bool autoShape, bool scaleFill, bool scaleUp, int stride, const cv::Scalar& color)
{
    if (false) {
        int maxLen = MAX(image.rows, image.cols);
        outImage = Mat::zeros(Size(maxLen, maxLen), CV_8UC3);
        image.copyTo(outImage(Rect(0, 0, image.cols, image.rows)));
        params[0] = 1;
        params[1] = 1;
        params[3] = 0;
        params[2] = 0;
    }

    cv::Size shape = image.size();
    float r = std::min((float)newShape.height / (float)shape.height,
        (float)newShape.width / (float)shape.width);
    if (!scaleUp)
        r = std::min(r, 1.0f);

    float ratio[2]{ r, r };
    int new_un_pad[2] = { (int)std::round((float)shape.width * r),(int)std::round((float)shape.height * r) };

    auto dw = (float)(newShape.width - new_un_pad[0]);
    auto dh = (float)(newShape.height - new_un_pad[1]);

    if (autoShape)
    {
        dw = (float)((int)dw % stride);
        dh = (float)((int)dh % stride);
    }
    else if (scaleFill)
    {
        dw = 0.0f;
        dh = 0.0f;
        new_un_pad[0] = newShape.width;
        new_un_pad[1] = newShape.height;
        ratio[0] = (float)newShape.width / (float)shape.width;
        ratio[1] = (float)newShape.height / (float)shape.height;
    }

    dw /= 2.0f;
    dh /= 2.0f;

    if (shape.width != new_un_pad[0] && shape.height != new_un_pad[1])
    {
        cv::resize(image, outImage, cv::Size(new_un_pad[0], new_un_pad[1]));
    }
    else {
        outImage = image.clone();
    }

    int top = int(std::round(dh - 0.1f));
    int bottom = int(std::round(dh + 0.1f));
    int left = int(std::round(dw - 0.1f));
    int right = int(std::round(dw + 0.1f));
    params[0] = ratio[0];
    params[1] = ratio[1];
    params[2] = left;
    params[3] = top;
    cv::copyMakeBorder(outImage, outImage, top, bottom, left, right, cv::BORDER_CONSTANT, color);
}

void GetMask(const cv::Mat& maskProposals, const cv::Mat& maskProtos, std::vector<OutputSeg>& output, const MaskParams& maskParams) {
    //cout << maskProtos.size << endl;

    int seg_channels = maskParams.segChannels;
    int net_width = maskParams.netWidth;
    int seg_width = maskParams.segWidth;
    int net_height = maskParams.netHeight;
    int seg_height = maskParams.segHeight;
    float mask_threshold = maskParams.maskThreshold;
    Vec4f params = maskParams.params;
    Size src_img_shape = maskParams.srcImgShape;

    Mat protos = maskProtos.reshape(0, { seg_channels,seg_width * seg_height });

    Mat matmul_res = (maskProposals * protos).t();
    Mat masks = matmul_res.reshape(output.size(), { seg_width,seg_height });
    vector<Mat> maskChannels;
    split(masks, maskChannels);
    for (int i = 0; i < output.size(); ++i) {
        Mat dest, mask;
        //sigmoid
        cv::exp(-maskChannels[i], dest);
        dest = 1.0 / (1.0 + dest);

        Rect roi(int(params[2] / net_width * seg_width), int(params[3] / net_height * seg_height), int(seg_width - params[2] / 2), int(seg_height - params[3] / 2));
        dest = dest(roi);
        resize(dest, mask, src_img_shape, INTER_NEAREST);

        //crop
        Rect temp_rect = output[i].box;
        mask = mask(temp_rect) > mask_threshold;
        output[i].boxMask = mask;
    }
}
void GetMask2(const Mat& maskProposals, const Mat& mask_protos, OutputSeg& output, const MaskParams& maskParams) {
    int seg_channels = maskParams.segChannels;
    int net_width = maskParams.netWidth;
    int seg_width = maskParams.segWidth;
    int net_height = maskParams.netHeight;
    int seg_height = maskParams.segHeight;
    float mask_threshold = maskParams.maskThreshold;
    Vec4f params = maskParams.params;
    Size src_img_shape = maskParams.srcImgShape;

    Rect temp_rect = output.box;
    // 把已經(jīng)到原圖的檢測(cè)框坐標(biāo)信息  映射到  獲得mask原型分支的輸入尺寸上【160, 160】
    int rang_x = floor((temp_rect.x * params[0] + params[2]) / net_width * seg_width);
    int rang_y = floor((temp_rect.y * params[1] + params[3]) / net_height * seg_height);
    int rang_w = ceil(((temp_rect.x + temp_rect.width) * params[0] + params[2]) / net_width * seg_width) - rang_x;
    int rang_h = ceil(((temp_rect.y  + temp_rect.height) * params[0] + params[3]) / net_width * seg_height) - rang_y;

    //
    rang_w = MAX(rang_w, 1);
    rang_h = MAX(rang_h, 1);
    if (rang_x + rang_w > seg_width){
        if (seg_width - rang_x > 0)
            rang_w =seg_width -rang_x;
        else
            rang_x -= 1;
    }
    if (rang_y + rang_h > seg_height) {
        if (seg_height - rang_y > 0)
            rang_h = seg_height - rang_y;
        else
            rang_y -= 1;
    }

    vector<Range> roi_ranges;
    roi_ranges.push_back(Range(0,1));
    roi_ranges.push_back(Range::all());
    roi_ranges.push_back(Range(rang_y, rang_h+rang_y));
    roi_ranges.push_back(Range(rang_x, rang_w+rang_x));

    // 裁剪mask原型
    Mat temp_mask_protos = mask_protos(roi_ranges).clone(); // 剪裁原型,保存檢測(cè)框內(nèi)部的原型,其余位置清零,  以此來(lái)獲得感興趣區(qū)域(roi)
    Mat protos = temp_mask_protos.reshape(0, { seg_channels, rang_w*rang_h});// 檢測(cè)至檢測(cè)框大小?

    // mask系數(shù)與mask原型做矩陣乘法
    Mat matmul_res = (maskProposals * protos).t(); // mask系數(shù)【1,32】 與 mask原型【32, h*w】進(jìn)行矩陣相稱(chēng)
    Mat masks_feature = matmul_res.reshape(1,{rang_h, rang_w}); //【1,h,w】
    Mat dest, mask;

    // sigmod
    cv::exp(-masks_feature, dest);
    dest = 1.0 / (1.0 + dest);

    // 檢測(cè)框坐標(biāo) 映射到 原圖尺寸
    int left = floor((net_width / seg_width * rang_x - params[2]) / params[0]);
    int top = floor((net_width / seg_height * rang_y - params[3]) / params[1]);
    int width = ceil(net_width / seg_height * rang_w / params[0]);
    int height = ceil(net_height / seg_height * rang_h / params[1]);

    // 檢測(cè)框mask縮放到原圖尺寸
    resize(dest, mask, Size(width, height), INTER_NEAREST);

    // 閾值化
    mask = mask(temp_rect - Point(left, top)) > mask_threshold;
    output.boxMask = mask;
}

void DrawPred(Mat& img, vector<OutputSeg> result, std::vector<std::string> classNames, vector<Scalar> color) {
    Mat mask = img.clone();
    for (int i=0; i< result.size(); i++){
        int left, top;
        left = result[i].box.x;
        top = result[i].box.y;
        int color_num =i;

        // 目標(biāo)畫(huà)框
        rectangle(img, result[i].box, color[result[i].id], 2, 8);

        // 目標(biāo)mask,這里非目標(biāo)像素值為0
        mask(result[i].box).setTo(color[result[i].id], result[i].boxMask);
        string label = classNames[result[i].id] + ":" + to_string(result[i].confidence);

        // 框左上角打印信息
        int baseLine;
        Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
        top = max(top, labelSize.height);
        putText(img, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.5, color[result[i].id], 2);
    }

    addWeighted(img, 0.5, mask, 0.5, 0, img);
}
分割的調(diào)用代碼測(cè)試案例

void frmMain::test_yoloseg()
{
    string model_path = "20231001segquanjing.onnx";
    YoloSeg test;
    Net net;
    if (test.ReadModel(net, model_path, true)) {
        cout << "read net ok!" << endl;
    }
    else {
        return ;
    }
    vector<OutputSeg> result;
    cv::Mat img_seg_test=cv::imread("E:/data_seg/quanjingCameraPicture2/1/segdata2278.jpg");


    bool find = test.Detect(img_seg_test, net, result);

    if (find) {
        DrawPred(img_seg_test, result, test._className, color);
    }
    else {
        cout << "Detect Failed!"<<endl;
    }


    string label = "steel:" ; //ms
    putText(img_seg_test, label, Point(30,30), FONT_HERSHEY_SIMPLEX,0.5, Scalar(0,0,255), 2, 8);

    QPixmap img_test_xmap= my_publiction.cvMatToQPixmap(img_seg_test);
    // 設(shè)置QLabel的最小尺寸
    ui->lab1->setMinimumSize(600, 600);
    ui->lab1->setScaledContents(true);
    img_test_xmap = img_test_xmap.scaled( ui->lab1->width(),  ui->lab1->height(), Qt::KeepAspectRatio,Qt::SmoothTransformation); // 將圖像縮放到QLabel的大小
    ui->lab1->setPixmap(img_test_xmap);
//    imshow("result", img_seg_test);



}

?分割的效果圖如下:

yolov5截取檢測(cè)圖像 c++,qt,c++,YOLO文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-770093.html

到了這里,關(guān)于yolov5分割+檢測(cè)c++ qt 中部署,以opencv方式(詳細(xì)代碼(全)+復(fù)制可用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 2022.09.29更新 c++下面部署yolov5實(shí)例分割模型(六)

    2022.09.29更新 c++下面部署yolov5實(shí)例分割模型(六)

    2023.01.11 更新: 新增加onnxruntime的1.13.x版本支持。 由于onnxruntime從1.12升級(jí)到1.13之后,GetOutputName()這個(gè)API變成了GetOutputNameAllocated(),坑就出現(xiàn)在這里,新版api的返回值是一個(gè)unique_ptr指針,這就意味著他使用一次時(shí)候就失效了,所以在循環(huán)跑模型的時(shí)候基本的第二次都報(bào)錯(cuò)

    2024年02月12日
    瀏覽(27)
  • yolov5目標(biāo)檢測(cè)多線程C++部署

    yolov5目標(biāo)檢測(cè)多線程C++部署

    下面的代碼搭建了簡(jiǎn)單的一個(gè)生產(chǎn)者-消費(fèi)者模型,在capture()函數(shù)中進(jìn)行入隊(duì)操作,infer()函數(shù)中進(jìn)行出隊(duì)操作,為了模擬采圖-推理流程,在函數(shù)中調(diào)用Sleep()函數(shù)延時(shí)。 輸出結(jié)果: 現(xiàn)在我們把capture函數(shù)中的Sleep(1000)改成Sleep(500)來(lái)模擬生產(chǎn)者加速生產(chǎn),再次執(zhí)行程序,則輸出:

    2024年02月13日
    瀏覽(24)
  • 瑞芯微RK3588 C++部署Yolov8檢測(cè)和分割模型

    瑞芯微RK3588 C++部署Yolov8檢測(cè)和分割模型

    最近這一個(gè)月在研究國(guó)產(chǎn)瑞芯微板子上部署yolov8的檢測(cè)和分割模型,踩了很多坑,記錄一下部署的過(guò)程和遇到的一些問(wèn)題: 需要的環(huán)境和代碼主要包括: (1)rknn-toolkit2-1.5.2:工具鏈,開(kāi)發(fā)環(huán)境 (2)rockchip-yolov8:pt模型轉(zhuǎn)onnx模型 (3)yolov8_onnx2rknn:在(2)的基礎(chǔ)上轉(zhuǎn)檢測(cè)

    2024年04月09日
    瀏覽(28)
  • 基于樹(shù)莓派Qt+opencv+yolov5-Lite+C++部署深度學(xué)習(xí)推理

    基于樹(shù)莓派Qt+opencv+yolov5-Lite+C++部署深度學(xué)習(xí)推理

    ? ? ? ? 本文是基于 qt和opencv的dnn 深度學(xué)習(xí)推理模塊,在樹(shù)莓派上部署YOLO系列推理,適用于yolov5-6.1以及yolov5-Lite,相比直接用python的onnxruntime,用基于opencv的dnn模塊,利用訓(xùn)練生成的onnx模型,即可快速部署,不需要在樹(shù)莓派上額外安裝深度學(xué)習(xí)的一系列環(huán)境,因?yàn)槲覀冎?/p>

    2024年04月16日
    瀏覽(135)
  • 2023.01更新 c++下面部署yolov8檢測(cè)和實(shí)例分割模型(七)

    2023.12.05 更新: 新增yolov8的RT-DETR部署 先開(kāi)貼占個(gè)坑。 yolov8:https://github.com/ultralytics/ultralytics 這次的v8更新的是一個(gè)框架,里面也可以用v5和v3。 但是這次更新來(lái)說(shuō),目前模型的檢測(cè)效果和之前的yolov7剛出來(lái)一樣,會(huì)多出很多誤檢,在某些情況下這些誤檢反而效果不好。另外最

    2024年02月11日
    瀏覽(20)
  • 2021.11.01 c++下 opencv部署yolov5-6.0版本 (四)

    2021.11.01 c++下 opencv部署yolov5-6.0版本 (四)

    ----2022.10.10 更新yolov5-seg實(shí)例分割模型: 2022.09.29更新 c++下面使用opencv部署yolov5和yolov7實(shí)例分割模型(六)_愛(ài)晚乏客游的博客-CSDN博客 ?-----2022.07.25 更新了下yolov7的部署,有需要的自取 2022.07.25 C++下使用opencv部署yolov7模型(五)_愛(ài)晚乏客游的博客-CSDN博客 此篇文章針對(duì)yolov5的

    2024年02月04日
    瀏覽(26)
  • Jetson nano部署Yolov5目標(biāo)檢測(cè) + Tensor RT加速(超級(jí)詳細(xì)版)

    Jetson nano部署Yolov5目標(biāo)檢測(cè) + Tensor RT加速(超級(jí)詳細(xì)版)

    在工作或?qū)W習(xí)中我們需要進(jìn)行部署,下面這篇文章是我親自部署jetson nano之后做出的總結(jié),包括自己遇到一些報(bào)錯(cuò)和踩坑,希望對(duì)你們有所幫助 :?) 讀卡器 SD卡? 小螺絲刀 網(wǎng)線(更改語(yǔ)言需要網(wǎng)絡(luò)) 燒錄鏡像就是要把SD卡里的東西給完全清除,好比我們電腦重裝系統(tǒng)一樣,

    2024年02月13日
    瀏覽(18)
  • Yolov5同時(shí)進(jìn)行目標(biāo)檢測(cè)和分割分割

    Yolov5同時(shí)進(jìn)行目標(biāo)檢測(cè)和分割分割

    基于yolov5(v6.0分支)的多任務(wù)檢測(cè)和分割模型。 之前很早就萌生idea在yolov5基礎(chǔ)上添加一個(gè)分割頭用于語(yǔ)義分割,近期正好也有論文YLOLOP是這么做的. 這里基于yolov5最新分支修改,主要改動(dòng)如下: 1 . 解耦頭:實(shí)驗(yàn)在小數(shù)據(jù)集上有一定效果(map 1%+ ),大數(shù)據(jù)集上提升不明顯; 2.

    2024年02月05日
    瀏覽(18)
  • 【目標(biāo)檢測(cè)】YOLOv5-7.0:加入實(shí)例分割

    【目標(biāo)檢測(cè)】YOLOv5-7.0:加入實(shí)例分割

    前段時(shí)間,YOLOv5推出7.0版本,主要更新點(diǎn)是在目標(biāo)檢測(cè)的同時(shí)引入了實(shí)例分割。 目前,YOLOv5團(tuán)隊(duì)已經(jīng)轉(zhuǎn)向了YOLOv8的更新,因此,7.0版本大概率是YOLOv5的最終穩(wěn)定版。 官方公告中給出了YOLOv5-7.0的更新要點(diǎn): 推出了基于coco-seg的實(shí)例分割預(yù)訓(xùn)練模型 支持Paddle Paddle模型導(dǎo)出 自動(dòng)

    2024年02月11日
    瀏覽(18)
  • [C++]使用純opencv部署yolov8旋轉(zhuǎn)框目標(biāo)檢測(cè)

    [C++]使用純opencv部署yolov8旋轉(zhuǎn)框目標(biāo)檢測(cè)

    【官方框架地址】 https://github.com/ultralytics/ultralytics 【算法介紹】 YOLOv8是一種先進(jìn)的對(duì)象檢測(cè)算法,它通過(guò)單個(gè)神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)了快速的物體檢測(cè)。其中,旋轉(zhuǎn)框檢測(cè)是YOLOv8的一項(xiàng)重要特性,它可以有效地檢測(cè)出不同方向和角度的物體。 旋轉(zhuǎn)框檢測(cè)的原理是通過(guò)預(yù)測(cè)物體的邊界

    2024年04月26日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包