"vscode:/vscode.git/clone" did not exist on "edb6eb86437d8f1c8df3d509d6e507e466742978"
YOLOV7.cpp 7.63 KB
Newer Older
liucong's avatar
liucong committed
1
#include <YOLOV7.h>
Your Name's avatar
Your Name committed
2
3
4
5
6
7
8
9
10
#include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp>
#include <migraphx/quantization.hpp>
#include <Filesystem.h>
#include <SimpleLog.h>

namespace migraphxSamples
{

liucong's avatar
liucong committed
11
DetectorYOLOV7::DetectorYOLOV7() {}
Your Name's avatar
Your Name committed
12

liucong's avatar
liucong committed
13
DetectorYOLOV7::~DetectorYOLOV7() { configurationFile.release(); }
Your Name's avatar
Your Name committed
14

liucong's avatar
liucong committed
15
16
ErrorCode
DetectorYOLOV7::Initialize(InitializationParameterOfDetector initializationParameterOfDetector)
Your Name's avatar
Your Name committed
17
{
liucong's avatar
liucong committed
18
    // 读取配置文件
liucong's avatar
liucong committed
19
    std::string configFilePath = initializationParameterOfDetector.configFilePath;
liucong's avatar
liucong committed
20
    if(!Exists(configFilePath))
Your Name's avatar
Your Name committed
21
    {
liucong's avatar
liucong committed
22
23
24
25
26
        LOG_ERROR(stdout, "no configuration file!\n");
        return CONFIG_FILE_NOT_EXIST;
    }
    if(!configurationFile.open(configFilePath, cv::FileStorage::READ))
    {
liucong's avatar
liucong committed
27
28
        LOG_ERROR(stdout, "fail to open configuration file\n");
        return FAIL_TO_OPEN_CONFIG_FILE;
Your Name's avatar
Your Name committed
29
    }
liucong's avatar
liucong committed
30
    LOG_INFO(stdout, "succeed to open configuration file\n");
Your Name's avatar
Your Name committed
31
32

    // 获取配置文件参数
liucong's avatar
liucong committed
33
34
35
    cv::FileNode netNode                = configurationFile["DetectorYOLOV7"];
    std::string modelPath               = (std::string)netNode["ModelPath"];
    std::string pathOfClassNameFile     = (std::string)netNode["ClassNameFile"];
Your Name's avatar
Your Name committed
36
    yolov7Parameter.confidenceThreshold = (float)netNode["ConfidenceThreshold"];
liucong's avatar
liucong committed
37
38
39
40
    yolov7Parameter.nmsThreshold        = (float)netNode["NMSThreshold"];
    yolov7Parameter.objectThreshold     = (float)netNode["ObjectThreshold"];
    yolov7Parameter.numberOfClasses     = (int)netNode["NumberOfClasses"];
    useFP16                             = (bool)(int)netNode["UseFP16"];
Your Name's avatar
Your Name committed
41
42

    // 加载模型
liucong's avatar
liucong committed
43
    if(!Exists(modelPath))
Your Name's avatar
Your Name committed
44
    {
liucong's avatar
liucong committed
45
        LOG_ERROR(stdout, "%s not exist!\n", modelPath.c_str());
Your Name's avatar
Your Name committed
46
47
48
        return MODEL_NOT_EXIST;
    }
    net = migraphx::parse_onnx(modelPath);
liucong's avatar
liucong committed
49
    LOG_INFO(stdout, "succeed to load model: %s\n", GetFileName(modelPath).c_str());
Your Name's avatar
Your Name committed
50

liucong's avatar
liucong committed
51
    // 获取模型输入/输出节点信息
liucong's avatar
liucong committed
52
53
54
55
56
57
58
59
60
    std::unordered_map<std::string, migraphx::shape> inputs  = net.get_inputs();
    std::unordered_map<std::string, migraphx::shape> outputs = net.get_outputs();
    inputName                                                = inputs.begin()->first;
    inputShape                                               = inputs.begin()->second;
    int N                                                    = inputShape.lens()[0];
    int C                                                    = inputShape.lens()[1];
    int H                                                    = inputShape.lens()[2];
    int W                                                    = inputShape.lens()[3];
    inputSize                                                = cv::Size(W, H);
Your Name's avatar
Your Name committed
61
62
63
64

    // 设置模型为GPU模式
    migraphx::target gpuTarget = migraphx::gpu::target{};

liucong's avatar
liucong committed
65
    // 量化
Your Name's avatar
Your Name committed
66
67
68
69
70
71
72
    if(useFP16)
    {
        migraphx::quantize_fp16(net);
    }

    // 编译模型
    migraphx::compile_options options;
liucong's avatar
liucong committed
73
74
75
76
    options.device_id    = 0; // 设置GPU设备,默认为0号设备
    options.offload_copy = true;
    net.compile(gpuTarget, options);
    LOG_INFO(stdout, "succeed to compile model: %s\n", GetFileName(modelPath).c_str());
Your Name's avatar
Your Name committed
77

liucong's avatar
liucong committed
78
79
    // warm up
    std::unordered_map<std::string, migraphx::argument> inputData;
liucong's avatar
liucong committed
80
    inputData[inputName] = migraphx::argument{inputShape};
Your Name's avatar
Your Name committed
81
82
83
84
85
    net.eval(inputData);

    // 读取类别名
    if(!pathOfClassNameFile.empty())
    {
liucong's avatar
liucong committed
86
87
        std::ifstream classNameFile(pathOfClassNameFile);
        std::string line;
liucong's avatar
liucong committed
88
        while(getline(classNameFile, line))
Your Name's avatar
Your Name committed
89
90
91
92
93
94
95
96
97
98
        {
            classNames.push_back(line);
        }
    }
    else
    {
        classNames.resize(yolov7Parameter.numberOfClasses);
    }

    // log
liucong's avatar
liucong committed
99
100
101
102
103
104
    LOG_INFO(stdout, "InputSize:%dx%d\n", inputSize.width, inputSize.height);
    LOG_INFO(stdout, "InputName:%s\n", inputName.c_str());
    LOG_INFO(stdout, "ConfidenceThreshold:%f\n", yolov7Parameter.confidenceThreshold);
    LOG_INFO(stdout, "objectThreshold:%f\n", yolov7Parameter.objectThreshold);
    LOG_INFO(stdout, "NMSThreshold:%f\n", yolov7Parameter.nmsThreshold);
    LOG_INFO(stdout, "NumberOfClasses:%d\n", yolov7Parameter.numberOfClasses);
Your Name's avatar
Your Name committed
105
106
107
108

    return SUCCESS;
}

liucong's avatar
liucong committed
109
110
ErrorCode DetectorYOLOV7::Detect(const cv::Mat& srcImage,
                                 std::vector<ResultOfDetection>& resultsOfDetection)
Your Name's avatar
Your Name committed
111
{
liucong's avatar
liucong committed
112
    if(srcImage.empty() || srcImage.type() != CV_8UC3)
Your Name's avatar
Your Name committed
113
    {
liucong's avatar
liucong committed
114
        LOG_ERROR(stdout, "image error!\n");
Your Name's avatar
Your Name committed
115
116
117
        return IMAGE_ERROR;
    }

liucong's avatar
liucong committed
118
    // 数据预处理并转换为NCHW格式
Your Name's avatar
Your Name committed
119
    cv::Mat inputBlob;
liucong's avatar
liucong committed
120
121
    cv::dnn::blobFromImage(
        srcImage, inputBlob, 1 / 255.0, inputSize, cv::Scalar(0, 0, 0), true, false);
Your Name's avatar
Your Name committed
122

liucong's avatar
liucong committed
123
124
    // 创建输入数据
    std::unordered_map<std::string, migraphx::argument> inputData;
liucong's avatar
liucong committed
125
    inputData[inputName] = migraphx::argument{inputShape, (float*)inputBlob.data};
Your Name's avatar
Your Name committed
126
127
128
129
130
131

    // 推理
    std::vector<migraphx::argument> inferenceResults = net.eval(inputData);

    // 获取推理结果
    std::vector<cv::Mat> outs;
liucong's avatar
liucong committed
132
    migraphx::argument result = inferenceResults[0];
Your Name's avatar
Your Name committed
133
134
135

    // 转换为cv::Mat
    migraphx::shape outputShape = result.get_shape();
liucong's avatar
liucong committed
136
137
138
    int shape[] = {outputShape.lens()[0], outputShape.lens()[1], outputShape.lens()[2]};
    cv::Mat out(3, shape, CV_32F);
    memcpy(out.data, result.data(), sizeof(float) * outputShape.elements());
Your Name's avatar
Your Name committed
139
140
    outs.push_back(out);

liucong's avatar
liucong committed
141
    // 获取先验框的个数
Your Name's avatar
Your Name committed
142
    int numProposal = outs[0].size[1];
liucong's avatar
liucong committed
143
144
    int numOut      = outs[0].size[2];
    // 变换输出的维度
Your Name's avatar
Your Name committed
145
    outs[0] = outs[0].reshape(0, numProposal);
liucong's avatar
liucong committed
146
147

    // 生成先验框
Your Name's avatar
Your Name committed
148
149
150
    std::vector<float> confidences;
    std::vector<cv::Rect> boxes;
    std::vector<int> classIds;
liucong's avatar
liucong committed
151
152
    float ratioh = (float)srcImage.rows / inputSize.height,
          ratiow = (float)srcImage.cols / inputSize.width;
Your Name's avatar
Your Name committed
153

liucong's avatar
liucong committed
154
    // 计算cx,cy,w,h,box_sore,class_sore
Your Name's avatar
Your Name committed
155
156
    int n = 0, rowInd = 0;
    float* pdata = (float*)outs[0].data;
liucong's avatar
liucong committed
157
    for(n = 0; n < numProposal; n++)
Your Name's avatar
Your Name committed
158
159
    {
        float boxScores = pdata[4];
liucong's avatar
liucong committed
160
        if(boxScores > yolov7Parameter.objectThreshold)
Your Name's avatar
Your Name committed
161
162
163
164
165
166
        {
            cv::Mat scores = outs[0].row(rowInd).colRange(5, numOut);
            cv::Point classIdPoint;
            double maxClassScore;
            cv::minMaxLoc(scores, 0, &maxClassScore, 0, &classIdPoint);
            maxClassScore *= boxScores;
liucong's avatar
liucong committed
167
            if(maxClassScore > yolov7Parameter.confidenceThreshold)
Your Name's avatar
Your Name committed
168
169
            {
                const int classIdx = classIdPoint.x;
liucong's avatar
liucong committed
170
171
172
173
                float cx           = pdata[0] * ratiow;
                float cy           = pdata[1] * ratioh;
                float w            = pdata[2] * ratiow;
                float h            = pdata[3] * ratioh;
Your Name's avatar
Your Name committed
174
175

                int left = int(cx - 0.5 * w);
liucong's avatar
liucong committed
176
                int top  = int(cy - 0.5 * h);
Your Name's avatar
Your Name committed
177
178
179
180
181
182
183
184
185
186

                confidences.push_back((float)maxClassScore);
                boxes.push_back(cv::Rect(left, top, (int)(w), (int)(h)));
                classIds.push_back(classIdx);
            }
        }
        rowInd++;
        pdata += numOut;
    }

liucong's avatar
liucong committed
187
    // 执行non maximum suppression消除冗余重叠boxes
Your Name's avatar
Your Name committed
188
    std::vector<int> indices;
liucong's avatar
liucong committed
189
190
191
192
193
194
    cv::dnn::NMSBoxes(boxes,
                      confidences,
                      yolov7Parameter.confidenceThreshold,
                      yolov7Parameter.nmsThreshold,
                      indices);
    for(size_t i = 0; i < indices.size(); ++i)
Your Name's avatar
Your Name committed
195
    {
liucong's avatar
liucong committed
196
197
198
199
200
        int idx               = indices[i];
        int classID           = classIds[idx];
        std::string className = classNames[classID];
        float confidence      = confidences[idx];
        cv::Rect box          = boxes[idx];
Your Name's avatar
Your Name committed
201
202

        ResultOfDetection result;
liucong's avatar
liucong committed
203
204
205
206
        result.boundingBox = box;
        result.confidence  = confidence; // confidence
        result.classID     = classID;    // label
        result.className   = className;
Your Name's avatar
Your Name committed
207
208
209
210
211
212
        resultsOfDetection.push_back(result);
    }

    return SUCCESS;
}

liucong's avatar
liucong committed
213
} // namespace migraphxSamples