OcrSVTR.cpp 6.3 KB
Newer Older
Your Name's avatar
Your Name committed
1
2
3
4
5
6
7
8
#include <OcrSVTR.h>
#include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp>
#include <Filesystem.h>
#include <SimpleLog.h>

namespace migraphxSamples
{
liucong's avatar
liucong committed
9
SVTR::SVTR() {}
Your Name's avatar
Your Name committed
10

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

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

    // 获取配置文件参数
liucong's avatar
liucong committed
30
    cv::FileNode netNode  = configurationFile["OcrSVTR"];
liucong's avatar
liucong committed
31
    std::string modelPath = (std::string)netNode["ModelPath"];
liucong's avatar
liucong committed
32
    std::string dictPath  = (std::string)netNode["DictPath"];
Your Name's avatar
Your Name committed
33

liucong's avatar
liucong committed
34
    // 加载模型
liucong's avatar
liucong committed
35
    if(!Exists(modelPath))
Your Name's avatar
Your Name committed
36
    {
liucong's avatar
liucong committed
37
        LOG_ERROR(stdout, "%s not exist!\n", modelPath.c_str());
Your Name's avatar
Your Name committed
38
39
40
        return MODEL_NOT_EXIST;
    }
    migraphx::onnx_options onnx_options;
liucong's avatar
liucong committed
41
42
43
    onnx_options.map_input_dims["x"] = {1, 3, 48, 320}; // 设置最大shape
    net                              = migraphx::parse_onnx(modelPath, onnx_options);
    LOG_INFO(stdout, "succeed to load model: %s\n", GetFileName(modelPath).c_str());
Your Name's avatar
Your Name committed
44

liucong's avatar
liucong committed
45
    // 获取模型输入/输出节点信息
liucong's avatar
liucong committed
46
47
48
49
50
51
52
53
54
    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
55
56
57
58
59
60

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

    // 编译模型
    migraphx::compile_options options;
liucong's avatar
liucong committed
61
62
63
64
    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
65

liucong's avatar
liucong committed
66
67
    // warm up
    std::unordered_map<std::string, migraphx::argument> inputData;
liucong's avatar
liucong committed
68
    inputData[inputName] = migraphx::argument{inputShape};
liucong's avatar
liucong committed
69
    net.eval(inputData);
Your Name's avatar
Your Name committed
70
71
72

    std::ifstream in(dictPath);
    std::string line;
liucong's avatar
liucong committed
73
    if(in)
Your Name's avatar
Your Name committed
74
    {
liucong's avatar
liucong committed
75
        while(getline(in, line))
Your Name's avatar
Your Name committed
76
77
78
79
80
81
82
83
84
85
86
87
88
        {
            charactorDict.push_back(line);
        }
        charactorDict.insert(charactorDict.begin(), "#");
        charactorDict.push_back(" ");
    }
    else
    {
        std::cout << "no such label file: " << dictPath << ", exit the program..." << std::endl;
        exit(1);
    }

    // log
liucong's avatar
liucong committed
89
90
    LOG_INFO(stdout, "InputMaxSize:%dx%d\n", inputSize.width, inputSize.height);
    LOG_INFO(stdout, "InputName:%s\n", inputName.c_str());
Your Name's avatar
Your Name committed
91
92
93
94

    return SUCCESS;
}

liucong's avatar
liucong committed
95
96
ErrorCode
SVTR::Infer(cv::Mat& img, std::string& resultsChar, float& resultsdScore, float& maxWHRatio)
Your Name's avatar
Your Name committed
97
{
liucong's avatar
liucong committed
98
    if(img.empty() || img.type() != CV_8UC3)
Your Name's avatar
Your Name committed
99
    {
liucong's avatar
liucong committed
100
        LOG_ERROR(stdout, "image error!\n");
Your Name's avatar
Your Name committed
101
102
103
104
105
106
107
108
109
110
111
        return IMAGE_ERROR;
    }

    cv::Mat srcImage;
    cv::Mat resizeImg;
    img.copyTo(srcImage);

    float ratio = 1.f;
    int imgC = 3, imgH = 48;
    int resizeW;
    int imgW = int((48 * maxWHRatio));
liucong's avatar
liucong committed
112
113
    ratio    = float(srcImage.cols) / float(srcImage.rows);
    if(ceil(imgH * ratio) > imgW)
Your Name's avatar
Your Name committed
114
115
116
117
118
119
120
121
    {
        resizeW = imgW;
    }
    else
    {
        resizeW = int(ceil(imgH * ratio));
    }
    cv::resize(srcImage, resizeImg, cv::Size(resizeW, imgH));
liucong's avatar
liucong committed
122
123
124
125
126
127
128
129
130
131
    cv::copyMakeBorder(resizeImg,
                       resizeImg,
                       0,
                       0,
                       0,
                       int(imgW - resizeImg.cols),
                       cv::BORDER_CONSTANT,
                       {127, 127, 127});

    resizeImg.convertTo(resizeImg, CV_32FC3, 1.0 / 255.0);
Your Name's avatar
Your Name committed
132
133
    std::vector<cv::Mat> bgrChannels(3);
    cv::split(resizeImg, bgrChannels);
liucong's avatar
liucong committed
134
    std::vector<float> mean  = {0.485f, 0.456f, 0.406f};
Your Name's avatar
Your Name committed
135
    std::vector<float> scale = {1 / 0.229f, 1 / 0.224f, 1 / 0.225f};
liucong's avatar
liucong committed
136
    for(auto i = 0; i < bgrChannels.size(); i++)
Your Name's avatar
Your Name committed
137
    {
liucong's avatar
liucong committed
138
139
        bgrChannels[i].convertTo(
            bgrChannels[i], CV_32FC1, 1.0 * scale[i], (0.0 - mean[i]) * scale[i]);
Your Name's avatar
Your Name committed
140
141
    }
    cv::merge(bgrChannels, resizeImg);
liucong's avatar
liucong committed
142
143
    cv::Mat inputBlob                          = cv::dnn::blobFromImage(resizeImg);
    std::vector<std::size_t> inputShapeOfInfer = {1, 3, 48, resizeW};
Your Name's avatar
Your Name committed
144

liucong's avatar
liucong committed
145
146
    // 创建输入数据
    std::unordered_map<std::string, migraphx::argument> inputData;
liucong's avatar
liucong committed
147
148
    inputData[inputName] = migraphx::argument{migraphx::shape(inputShape.type(), inputShapeOfInfer),
                                              (float*)inputBlob.data};
Your Name's avatar
Your Name committed
149
150
151

    // 推理
    std::vector<migraphx::argument> inferenceResults = net.eval(inputData);
liucong's avatar
liucong committed
152

Your Name's avatar
Your Name committed
153
    // 获取推理结果
liucong's avatar
liucong committed
154
    migraphx::argument result   = inferenceResults[0];
Your Name's avatar
Your Name committed
155
    migraphx::shape outputShape = result.get_shape();
liucong's avatar
liucong committed
156
157
158
    int n2                      = outputShape.lens()[1];
    int n3                      = outputShape.lens()[2];
    int n                       = n2 * n3;
Your Name's avatar
Your Name committed
159
    std::vector<float> out(n);
liucong's avatar
liucong committed
160
    memcpy(out.data(), result.data(), sizeof(float) * outputShape.elements());
Your Name's avatar
Your Name committed
161
162
163
    out.resize(n);

    int argmaxIdx;
liucong's avatar
liucong committed
164
165
166
    int lastIndex  = 0;
    float score    = 0.f;
    int count      = 0;
Your Name's avatar
Your Name committed
167
    float maxValue = 0.0f;
liucong's avatar
liucong committed
168
    for(int j = 0; j < n2; j++)
Your Name's avatar
Your Name committed
169
    {
liucong's avatar
liucong committed
170
171
172
173
174
175
176
177
178
179
        argmaxIdx =
            int(std::distance(&out[(j)*n3], std::max_element(&out[(j)*n3], &out[(j + 1) * n3])));
        maxValue = float(*std::max_element(&out[(j)*n3], &out[(j + 1) * n3]));

        if(argmaxIdx > 0 && (!(n > 0 && argmaxIdx == lastIndex)))
        {
            score += maxValue;
            count += 1;
            resultsChar += charactorDict[argmaxIdx];
        }
Your Name's avatar
Your Name committed
180
181
182
183
184
185
186
        lastIndex = argmaxIdx;
    }
    resultsdScore = score / count;

    return SUCCESS;
}

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