基于VS2019,利用paddle-ocr源码生成DLL文件

目录

修改代码,解决返回值问题

生成DLL文件

新建另一个工程进行测试


接上这一篇

基于VS2019的paddle-ocr编译、测试和代码精简_Jieeeee`的博客-CSDN博客

接下来,生成一个DLL文件给其他工程调用

修改代码,解决返回值问题

首先修改上文中的代码,因为paddle-ocr源码会将每幅图里的字符串分开,标上坐标

但是对我的应用来说,我只需要读取当前的全部字符即可,不需要用到两维的向量,而且二维的向量也不利于函数返回

// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <vector>

#include <include/args.h>
#include <include/paddleocr.h>
#include <include/paddlestructure.h>
#include <chrono>  
using namespace std::chrono;
using namespace PaddleOCR;
using namespace std;


string return_result(const vector<OCRPredictResult>& ocr_result) {

    std::string rec_result;
    for (int i = 0; i < ocr_result.size(); i++) {
        //这里的ocr_result.size()是单张图片内识别的多个字符串
        if (ocr_result[i].score != -1.0) {
            rec_result += ocr_result[i].text;
        }
    }
    //cout << "rec text: " << rec_result;
    //cout << std::endl;
    return rec_result;
}


vector<string> ocr(vector<cv::Mat> img_list) {
    PPOCR ocr = PPOCR();
    vector<string> result;
    std::vector<std::vector<OCRPredictResult>> ocr_results =
        ocr.ocr(img_list, FLAGS_det, FLAGS_rec, FLAGS_cls);

    for (int i = 0; i < img_list.size(); ++i) {
        //Utility::print_result(ocr_results[i]);
        result.push_back(return_result(ocr_results[i]));
    }
    return result;
}


int main(int argc, char** argv) {
    vector<string> result;
    high_resolution_clock::time_point  startTime, endTime;
    cv::Mat image1 = cv::imread("./img/test1.png");
    cv::Mat image2 = cv::imread("./img/test2.png");
    cv::Mat image3 = cv::imread("./img/test3.png");
    cv::Mat image4 = cv::imread("./img/test4.png");
    cv::Mat image5 = cv::imread("./img/test5.png");

    vector<cv::Mat> img_list;

    img_list.push_back(image1);
    img_list.push_back(image2);
    img_list.push_back(image3);
    img_list.push_back(image4);
    img_list.push_back(image5);


    startTime = high_resolution_clock::now();
    result = ocr(img_list);
    endTime = high_resolution_clock::now();
    long   interval_time = (duration_cast<milliseconds>(endTime - startTime).count());
    printf("\r\ntime = %d ", interval_time);

    for (int i = 0; i < result.size(); i++)
    {
        cout << result[i] << "\r\n";
    }

    cout << std::endl;
}

测试没错,开始生成DLL的过程,参考博客

Win10 + C++ + Paddle编译成DLL C++调用OCR文字识别_paddleocr c++如何使用_weixin_45052870的博客-CSDN博客

生成DLL文件

 

修改一下args.cpp  将能放在一起的外部文件都放在release文件夹下

// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gflags/gflags.h>

// common args
DEFINE_bool(use_gpu, true, "Infering with GPU or CPU.");
DEFINE_bool(use_tensorrt, false, "Whether use tensorrt.");
DEFINE_int32(gpu_id, 0, "Device id of GPU to execute.");
DEFINE_int32(gpu_mem, 4000, "GPU id when infering with GPU.");
DEFINE_int32(cpu_threads, 10, "Num of threads with CPU.");
DEFINE_bool(enable_mkldnn, false, "Whether use mkldnn with CPU.");
DEFINE_string(precision, "fp32", "Precision be one of fp32/fp16/int8");
DEFINE_bool(benchmark, false, "Whether use benchmark.");
DEFINE_string(output, "./output/", "Save benchmark log path.");
DEFINE_string(image_dir, "./img", "Dir of input image.");
DEFINE_string(
    type, "ocr",
    "Perform ocr or structure, the value is selected in ['ocr','structure'].");
// detection related
DEFINE_string(det_model_dir, "det", "Path of det inference model.");
DEFINE_string(limit_type, "max", "limit_type of input image.");
DEFINE_int32(limit_side_len, 960, "limit_side_len of input image.");
DEFINE_double(det_db_thresh, 0.3, "Threshold of det_db_thresh.");
DEFINE_double(det_db_box_thresh, 0.6, "Threshold of det_db_box_thresh.");
DEFINE_double(det_db_unclip_ratio, 1.5, "Threshold of det_db_unclip_ratio.");
DEFINE_bool(use_dilation, false, "Whether use the dilation on output map.");
DEFINE_string(det_db_score_mode, "slow", "Whether use polygon score.");
DEFINE_bool(visualize, true, "Whether show the detection results.");
// classification related
DEFINE_bool(use_angle_cls, false, "Whether use use_angle_cls.");
DEFINE_string(cls_model_dir, "", "Path of cls inference model.");
DEFINE_double(cls_thresh, 0.9, "Threshold of cls_thresh.");
DEFINE_int32(cls_batch_num, 1, "cls_batch_num.");
// recognition related
DEFINE_string(rec_model_dir, "rec", "Path of rec inference model.");
DEFINE_int32(rec_batch_num, 6, "rec_batch_num.");
DEFINE_string(rec_char_dict_path, "ppocr_keys_v1.txt",
              "Path of dictionary.");
DEFINE_int32(rec_img_h, 48, "rec image height");
DEFINE_int32(rec_img_w, 320, "rec image width");

// layout model related
DEFINE_string(layout_model_dir, "", "Path of table layout inference model.");
DEFINE_string(layout_dict_path,
              "../../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt",
              "Path of dictionary.");
DEFINE_double(layout_score_threshold, 0.5, "Threshold of score.");
DEFINE_double(layout_nms_threshold, 0.5, "Threshold of nms.");
// structure model related
DEFINE_string(table_model_dir, "", "Path of table struture inference model.");
DEFINE_int32(table_max_len, 488, "max len size of input image.");
DEFINE_int32(table_batch_num, 1, "table_batch_num.");
DEFINE_bool(merge_no_span_structure, true,
            "Whether merge <td> and </td> to <td></td>");
DEFINE_string(table_char_dict_path,
              "../../ppocr/utils/dict/table_structure_dict_ch.txt",
              "Path of dictionary.");

// ocr forward related
DEFINE_bool(det, true, "Whether use det in forward.");
DEFINE_bool(rec, true, "Whether use rec in forward.");
DEFINE_bool(cls, false, "Whether use cls in forward.");
DEFINE_bool(table, false, "Whether use table structure in forward.");
DEFINE_bool(layout, false, "Whether use layout analysis in forward.");

 然后修改代码main.cpp

// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <vector>

#include <include/args.h>
#include <include/paddleocr.h>
#include <include/paddlestructure.h>
#include <chrono>  
#include "include/ppocr.h"
using namespace std::chrono;
using namespace PaddleOCR;
using namespace std;


string return_result(const vector<OCRPredictResult>& ocr_result) {

    std::string rec_result;
    for (int i = 0; i < ocr_result.size(); i++) {
        //这里的ocr_result.size()是单张图片内识别的多个字符串
        if (ocr_result[i].score != -1.0) {
            rec_result += ocr_result[i].text;
        }
    }
    //cout << "rec text: " << rec_result;
    //cout << std::endl;
    return rec_result;
}


__declspec(dllexport) vector<string> ocr(vector<cv::Mat> img_list) {
    PPOCR ocr = PPOCR();
    vector<string> result;
    std::vector<std::vector<OCRPredictResult>> ocr_results =
        ocr.ocr(img_list, FLAGS_det, FLAGS_rec, FLAGS_cls);

    for (int i = 0; i < img_list.size(); ++i) {
        //Utility::print_result(ocr_results[i]);
        result.push_back(return_result(ocr_results[i]));
    }
    return result;
}

新建ppocr.h文件

#pragma once
///c+ +
#pragma once
#ifndef IMAGE_API
#define IMAGE_API
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <vector>
#include <include/args.h>
#include <include/paddleocr.h>
#include <include/paddlestructure.h>

using namespace std::chrono;
using namespace PaddleOCR;
using namespace std;
extern "C"
{
	// 图像推理
	__declspec(dllexport) vector<string> ocr(vector<cv::Mat> img_list);
}
#endif
///

然后编译出ppocr.dll

新建另一个工程进行测试

随便新建一个带命令行的工程,将上述工程中的全部文件拷贝到工程目录下(这一步是为了能使用调试器)

 然后修改该工程代码 读取DLL并且调用函数

	HMODULE dllHandle = LoadLibrary(L"ppocr.dll");
    if (!dllHandle) {
        std::cerr << "Error loading ppocr.dll" << std::endl;
        return 1;
    }
    // 获取 ocr 函数的地址
    OcrFunction ocrFunc = reinterpret_cast<OcrFunction>(GetProcAddress(dllHandle, "ocr"));
    if (!ocrFunc) {
        std::cerr << "Error getting ocr function address" << std::endl;
        return 1;
    }
    // 调用 ocr 函数
    std::vector<std::string> result = ocrFunc(imgList);

然后调试器运行得到结果

 如果需要在release里直接运行exe 需要把所有模型和dll依赖都放到releas里

再测试一下,运行正常

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值