feat.暂时废弃百度 OCR API

This commit is contained in:
MistEO
2021-12-17 21:20:40 +08:00
parent 02551f62ce
commit a2c49d2feb
10 changed files with 123 additions and 66 deletions

View File

@@ -5,12 +5,6 @@
"connectType_Doc": "连接类型0-连接电脑上的模拟器1-连接自定义端口,请手动修改'emulator.Custom'中的相关字段。默认0",
"taskDelay": 2000,
"taskDelay_Doc": "识别的延迟越快识别频率越快但会增加CPU消耗。单位毫秒默认2000",
"printWindow": false,
"printWindow_Doc": "截图功能开启后每次结算界面会截图到screenshot目录下。true-开启false-关闭默认false",
"penguinReport": true,
"penguinReport_Doc": "企鹅数据汇报:每次到结算界面,是否汇报掉落数据至企鹅数据 https://penguin-stats.cn/。true-开启false-关闭默认true",
"penguinReportCmdLine": "curl -H \"Content-Type: application/json\" -d \"[body]\" \"https://penguin-stats.cn/PenguinStats/api/v2/report\" [extra]",
"penguinReportCmdLine_Doc": "企鹅数据汇报的命令,想打印详细信息可以尝试添加 -v -i",
"controlDelayRange": [
0,
0
@@ -19,7 +13,13 @@
"adbExtraSwipeDist": 50,
"adbExtraSwipeDist_Doc": "额外的滑动距离adb有bug同样的参数偶尔会划得非常远。额外做一个短程滑动把之前的停下来",
"adbExtraSwipeDuration": 1000,
"adbExtraSwipeDuration_Doc": "额外的滑动持续时间adb有bug同样的参数偶尔会划得非常远。额外做一个短程滑动把之前的停下来。若小于0则关闭额外滑动功能"
"adbExtraSwipeDuration_Doc": "额外的滑动持续时间adb有bug同样的参数偶尔会划得非常远。额外做一个短程滑动把之前的停下来。若小于0则关闭额外滑动功能",
"penguinReport": {
"Doc": "企鹅数据汇报:每次到结算界面,汇报掉落数据至企鹅数据 https://penguin-stats.cn/。true-开启false-关闭默认true",
"enable": true,
"cmdFormat": "curl -H \"Content-Type: application/json\" -d \"[body]\" \"https://penguin-stats.cn/PenguinStats/api/v2/report\" [extra]",
"cmdFormat_Doc": "命令格式,想打印详细信息可以尝试添加 -v -i"
}
},
"emulator_Doc": "下面的和模拟器窗口捕获逻辑有关,不需要修改",
"emulator": {

View File

@@ -8,6 +8,7 @@
#include "AsstUtils.hpp"
#include "Logger.hpp"
#include "Resource.h"
bool asst::AipOcr::request_access_token(const std::string& client_id, const std::string& client_secret)
{
@@ -16,7 +17,7 @@ bool asst::AipOcr::request_access_token(const std::string& client_id, const std:
m_access_token.clear();
std::string_view cmd_fmt =
R"(curl -k \"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s\")";
R"(curl -s -k "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s")";
constexpr int cmd_len = 256;
char cmd[cmd_len] = { 0 };
@@ -42,22 +43,43 @@ bool asst::AipOcr::request_access_token(const std::string& client_id, const std:
return true;
}
std::vector<asst::TextRect> asst::AipOcr::request_ocr_accurate(const cv::Mat& image, const TextRectProc& pred)
bool asst::AipOcr::request_ocr_general(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred)
{
LogTraceFunction;
std::string_view cmd_fmt =
R"(curl -k \"https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=%s\" --data \"image=%s\" -H \"Content-Type:application/x-www-form-urlencoded\")";
return request_ocr_and_parse(cmd_fmt, image, pred);
}
std::vector<asst::TextRect> asst::AipOcr::request_ocr_and_parse(std::string_view cmd_fmt, const cv::Mat& image, const TextRectProc& pred)
{
if (m_access_token.empty()) {
return std::vector<asst::TextRect>();
auto& cfg = Resrc.cfg().get_options().aip_ocr;
request_access_token(cfg.client_id, cfg.client_secret);
}
std::string_view cmd_fmt =
R"(curl -s -k "https://aip.baidubce.com/rest/2.0/ocr/v1/general?access_token=%s" --data "image=%s" -H "Content-Type:application/x-www-form-urlencoded")";
return request_ocr_and_parse(cmd_fmt, image, out_result, pred);
}
bool asst::AipOcr::request_ocr_accurate(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred)
{
LogTraceFunction;
if (m_access_token.empty()) {
auto& cfg = Resrc.cfg().get_options().aip_ocr;
request_access_token(cfg.client_id, cfg.client_secret);
}
std::string_view cmd_fmt =
R"(curl -s -k "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=%s" --data "image=%s" -H "Content-Type:application/x-www-form-urlencoded")";
return request_ocr_and_parse(cmd_fmt, image, out_result, pred);
}
bool asst::AipOcr::request_ocr_and_parse(std::string_view cmd_fmt, const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred)
{
if (m_access_token.empty()) {
return false;
}
// CreateProcess 最大只能接受 32767 chars一张图片随便就超过了
// 这个功能暂时没法用,得集成下 libcurl 或者别的
std::vector<uchar> buf;
cv::imencode(".png", image, buf);
auto* enc_msg = reinterpret_cast<unsigned char*>(buf.data());
@@ -66,7 +88,7 @@ std::vector<asst::TextRect> asst::AipOcr::request_ocr_and_parse(std::string_view
size_t cmd_len = encoded.size() + cmd_fmt.size() + m_access_token.size();
char* cmd = new char[cmd_len];
memset(cmd, 0, cmd_len);
sprintf_s(cmd, cmd_len, cmd_fmt.data(), encoded.c_str(), m_access_token.c_str());
sprintf_s(cmd, cmd_len, cmd_fmt.data(), m_access_token.c_str(), encoded.c_str());
Log.trace("call cmd:", cmd);
std::string response = utils::callcmd(cmd);
@@ -75,21 +97,21 @@ std::vector<asst::TextRect> asst::AipOcr::request_ocr_and_parse(std::string_view
auto parse_res = json::parse(response);
if (!parse_res) {
return std::vector<asst::TextRect>();
return false;
}
try {
auto json = parse_res.value();
return parse_response(json);
return parse_response(json, out_result, pred);
}
catch (...) {
return std::vector<asst::TextRect>();
return false;
}
}
std::vector<asst::TextRect> asst::AipOcr::parse_response(const json::value& json, const TextRectProc& pred)
bool asst::AipOcr::parse_response(const json::value& json, std::vector<TextRect>& out_result, const TextRectProc& pred)
{
if (!json.exist("words_result")) {
return std::vector<asst::TextRect>();
return false;
}
std::vector<TextRect> result;
@@ -115,7 +137,9 @@ std::vector<asst::TextRect> asst::AipOcr::parse_response(const json::value& json
}
}
Log.trace("OcrPack::recognize | raw : ", log_str_raw);
Log.trace("OcrPack::recognize | proc : ", log_str_proc);
return result;
Log.trace("AipOcr::parse_response | raw : ", log_str_raw);
Log.trace("AipOcr::parse_response | proc : ", log_str_proc);
out_result = result;
return true;
}

View File

@@ -20,22 +20,23 @@ namespace asst
public:
~AipOcr() = default;
AipOcr& get_instance()
static AipOcr& get_instance()
{
static AipOcr unique_instance;
return unique_instance;
}
bool request_access_token(const std::string& client_id, const std::string& client_secret);
std::vector<TextRect> request_ocr_accurate(const cv::Mat& image, const TextRectProc& pred = nullptr);
bool request_ocr_general(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
bool request_ocr_accurate(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
private:
AipOcr() = default;
AipOcr(const AipOcr&) = default;
AipOcr(AipOcr&&) noexcept = default;
std::vector<TextRect> request_ocr_and_parse(std::string_view cmd_fmt, const cv::Mat& image, const TextRectProc& pred = nullptr);
std::vector<TextRect> parse_response(const json::value& json, const TextRectProc& pred = nullptr);
bool request_ocr_and_parse(std::string_view cmd_fmt, const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
bool parse_response(const json::value& json, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
std::string m_access_token;
};

View File

@@ -402,10 +402,10 @@ void asst::Assistant::set_penguin_id(const std::string& id)
{
auto& opt = Resrc.cfg().get_options();
if (id.empty()) {
opt.penguin_report_extra_param.clear();
opt.penguin_report.extra_param.clear();
}
else {
opt.penguin_report_extra_param = "-H \"authorization: PenguinID " + id + "\"";
opt.penguin_report.extra_param = "-H \"authorization: PenguinID " + id + "\"";
}
}

View File

@@ -6,22 +6,28 @@ bool asst::GeneralConfiger::parse(const json::value& json)
{
m_version = json.at("version").as_string();
const json::value& options_json = json.at("options");
{
const json::value& options_json = json.at("options");
m_options.connect_type = static_cast<ConnectType>(options_json.at("connectType").as_integer());
m_options.task_delay = options_json.at("taskDelay").as_integer();
m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer();
m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer();
m_options.print_window = options_json.at("printWindow").as_boolean();
m_options.penguin_report = options_json.at("penguinReport").as_boolean();
m_options.penguin_report_cmd_line = options_json.at("penguinReportCmdLine").as_string();
m_options.penguin_report_server = options_json.get("penguinReportServer", "CN");
//m_options.ocr_gpu_index = options_json.get("ocrGpuIndex", -1);
//m_options.ocr_thread_number = options_json.at("ocrThreadNumber").as_integer();
//m_options.print_window = options_json.at("printWindow").as_boolean();
m_options.adb_extra_swipe_dist = options_json.get("adbExtraSwipeDist", 100);
m_options.adb_extra_swipe_duration = options_json.get("adbExtraSwipeDuration", -1);
m_options.adb_extra_swipe_duration = options_json.get("adbExtraSwipeDuration", -1);
auto& penguin_report = options_json.at("penguinReport");
m_options.penguin_report.enable = penguin_report.get("enable", true);
m_options.penguin_report.cmd_format = penguin_report.get("cmdFormat", std::string());
m_options.penguin_report.server = penguin_report.get("server", "CN");
if (options_json.exist("aipOcr")) {
auto& aip_ocr = options_json.at("aipOcr");
m_options.aip_ocr.enable = aip_ocr.get("enable", false);
m_options.aip_ocr.accurate = aip_ocr.get("accurate", false);
m_options.aip_ocr.client_id = aip_ocr.get("clientId", std::string());
m_options.aip_ocr.client_secret = aip_ocr.get("clientSerect", std::string());
}
}
for (const auto& [name, emulator_json] : json.at("emulator").as_object()) {
@@ -52,4 +58,4 @@ bool asst::GeneralConfiger::parse(const json::value& json)
}
return true;
}
}

View File

@@ -14,6 +14,22 @@ namespace asst
{
Emulator,
Custom
};
struct AipOcrCfg // 百度 OCR API 的配置
{
bool enable = false;
bool accurate = false; // 是否使用高精度识别
std::string client_id;
std::string client_secret;
};
struct PenguinReportCfg // 企鹅物流数据汇报 的配置
{
bool enable = false;
std::string cmd_format; // 命令格式
std::string extra_param; // 额外参数
std::string server; // 上传参数中"server"字段,"CN", "US", "JP" and "KR".
};
struct Options
@@ -22,15 +38,11 @@ namespace asst
int task_delay = 0; // 任务间延时越快操作越快但会增加CPU消耗
int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时
int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时
bool print_window = false; // 截图功能开启后每次结算界面会截图到screenshot目录下
bool penguin_report = false; // 企鹅数据汇报:每次到结算界面,是否汇报掉落数据至企鹅数据 https://penguin-stats.cn/
std::string penguin_report_cmd_line; // 企鹅数据汇报的命令
std::string penguin_report_extra_param; // 企鹅数据汇报的命令
std::string penguin_report_server; // 企鹅数据汇报接口"server"字段,"CN", "US", "JP" and "KR".
//int ocr_gpu_index = -1; // OcrLite使用GPU编号-1(使用CPU)/0(使用GPU0)/1(使用GPU1)/...
//int ocr_thread_number = 0; // OcrLite线程数量
//bool print_window = false; // 截图功能开启后每次结算界面会截图到screenshot目录下
int adb_extra_swipe_dist = 0; // 额外的滑动距离adb有bug同样的参数偶尔会划得非常远。额外做一个短程滑动把之前的停下来
int adb_extra_swipe_duration = -1; // 额外的滑动持续时间adb有bug同样的参数偶尔会划得非常远。额外做一个短程滑动把之前的停下来。若小于0则关闭额外滑动功能
int adb_extra_swipe_duration = -1; // 额外的滑动持续时间adb有bug同样的参数偶尔会划得非常远。额外做一个短程滑动把之前的停下来。若小于0则关闭额外滑动功能
PenguinReportCfg penguin_report; // 企鹅数据汇报:每次到结算界面,汇报掉落数据至企鹅数据 https://penguin-stats.cn/
AipOcrCfg aip_ocr; // 百度 OCR API 的配置
};
class GeneralConfiger : public AbstractConfiger

View File

@@ -3,7 +3,8 @@
#include <regex>
#include "Logger.hpp"
#include "Resource.h"
#include "Resource.h"
#include "AipOcr.h"
bool asst::OcrImageAnalyzer::analyze()
{
@@ -48,8 +49,21 @@ bool asst::OcrImageAnalyzer::analyze()
}
}
return true;
};
m_ocr_result = Resrc.ocr().recognize(m_image, m_roi, all_pred, m_without_det);
};
auto& aip_ocr = Resrc.cfg().get_options().aip_ocr;
bool need_local = true;
if (aip_ocr.enable) {
if (aip_ocr.accurate) {
need_local = !AipOcr::get_instance().request_ocr_accurate(m_image, m_ocr_result, all_pred);
}
else {
need_local = !AipOcr::get_instance().request_ocr_general(m_image, m_ocr_result, all_pred);
}
}
if (need_local) {
m_ocr_result = Resrc.ocr().recognize(m_image, m_roi, all_pred, m_without_det);
}
//log.trace("ocr result", m_ocr_result);
return !m_ocr_result.empty();
}
}

View File

@@ -26,7 +26,7 @@ std::string asst::PenguinUploader::cvt_json(const std::string& rec_res)
// Doc: https://developer.penguin-stats.io/public-api/api-v2-instruction/report-api
json::value body;
auto& opt = Resrc.cfg().get_options();
body["server"] = opt.penguin_report_server;
body["server"] = opt.penguin_report.server;
body["stageId"] = rec["stage"]["stageId"];
// To fix: https://github.com/MistEO/MeoAssistantArknights/issues/40
body["drops"] = json::array();
@@ -45,8 +45,8 @@ bool asst::PenguinUploader::request_penguin(const std::string& body)
{
auto& opt = Resrc.cfg().get_options();
std::string body_escape = utils::string_replace_all(body, "\"", "\\\"");
std::string cmd_line = utils::string_replace_all(opt.penguin_report_cmd_line, "[body]", body_escape);
cmd_line = utils::string_replace_all(cmd_line, "[extra]", opt.penguin_report_extra_param);
std::string cmd_line = utils::string_replace_all(opt.penguin_report.cmd_format, "[body]", body_escape);
cmd_line = utils::string_replace_all(cmd_line, "[extra]", opt.penguin_report.extra_param);
Log.trace("request_penguin |", cmd_line);

View File

@@ -133,11 +133,11 @@ bool ProcessTask::_run()
m_callback(AsstMsg::StageDrops, json::parse(res).value(), m_callback_arg);
auto& opt = Resrc.cfg().get_options();
if (opt.print_window) {
//static const std::string dirname = utils::get_cur_dir() + "screenshot\\";
//save_image(image, dirname);
}
if (opt.penguin_report) {
//if (opt.print_window) {
// //static const std::string dirname = utils::get_cur_dir() + "screenshot\\";
// //save_image(image, dirname);
//}
if (opt.penguin_report.enable) {
PenguinUploader::upload(res);
}
} break;
@@ -208,4 +208,4 @@ void asst::ProcessTask::exec_swipe_task(ProcessTaskAction action)
default: // 走不到这里TODO 报个错
break;
}
}
}

View File

@@ -71,7 +71,7 @@ bool asst::Resource::load(const std::string& dir)
return false;
}
/* 加载企鹅数据识别库所需要的资源 */
m_penguin_pack_unique_ins.set_language(opt.penguin_report_server);
m_penguin_pack_unique_ins.set_language(opt.penguin_report.server);
if (!m_penguin_pack_unique_ins.load(dir + PenguinResourceFilename)) {
m_last_error = m_penguin_pack_unique_ins.get_last_error();
return false;