diff --git a/MeoAssistance/Assistance.cpp b/MeoAssistance/Assistance.cpp index 6e5b08c5bc..5b24f293d0 100644 --- a/MeoAssistance/Assistance.cpp +++ b/MeoAssistance/Assistance.cpp @@ -243,6 +243,28 @@ bool Assistance::start_open_recruit(const std::vector& required_level, bool return true; } +bool asst::Assistance::start_to_identify_opers() +{ + DebugTraceFunction; + if (!m_thread_idle || !m_inited) + { + return false; + } + + std::unique_lock lock(m_mutex); + + auto task_ptr = std::make_shared(task_callback, (void*)this); + // TODO 这个参数写到配置文件里,TODO 滑动位置要根据分辨率缩放 + task_ptr->set_swipe_param(Rect(2400, 800, 0, 0), Rect(400, 800, 0, 0), 2100); + task_ptr->set_task_chain("IdentifyOpers"); + m_tasks_queue.emplace(task_ptr); + + m_thread_idle = false; + m_condvar.notify_one(); + + return true; +} + bool asst::Assistance::start_infrast() { DebugTraceFunction; diff --git a/MeoAssistance/Assistance.h b/MeoAssistance/Assistance.h index 828cdd2020..c6e649a98b 100644 --- a/MeoAssistance/Assistance.h +++ b/MeoAssistance/Assistance.h @@ -34,6 +34,8 @@ namespace asst { // 开始公开招募操作 bool start_open_recruit(const std::vector& required_level, bool set_time = true); + // 开始干员识别任务 + bool start_to_identify_opers(); // 开始基建换班任务 bool start_infrast(); diff --git a/MeoAssistance/AsstCaller.cpp b/MeoAssistance/AsstCaller.cpp index afb10806c4..aafe4e8114 100644 --- a/MeoAssistance/AsstCaller.cpp +++ b/MeoAssistance/AsstCaller.cpp @@ -129,14 +129,14 @@ bool AsstTestOcr(asst::Assistance* p_asst, const char** text_array, int array_si return false; } - std::vector text_vec; - for (int i = 0; i != array_size; ++i) { - if (text_array[i] == nullptr) { - return false; - } - text_vec.emplace_back(asst::GbkToUtf8(text_array[i])); - } - p_asst->start_ocr_test_task(std::move(text_vec), need_click); + //std::vector text_vec; + //for (int i = 0; i != array_size; ++i) { + // if (text_array[i] == nullptr) { + // return false; + // } + // text_vec.emplace_back(asst::GbkToUtf8(text_array[i])); + //} + p_asst->start_to_identify_opers(); return true; } diff --git a/MeoAssistance/IdentifyOperTask.cpp b/MeoAssistance/IdentifyOperTask.cpp new file mode 100644 index 0000000000..ee39425165 --- /dev/null +++ b/MeoAssistance/IdentifyOperTask.cpp @@ -0,0 +1,175 @@ +#include "IdentifyOperTask.h" + +#include +#include +#include +#include +#include + +#include + +#include "Configer.h" +#include "InfrastConfiger.h" +#include "Identify.h" +#include "WinMacro.h" + +using namespace asst; + +asst::IdentifyOperTask::IdentifyOperTask(AsstCallback callback, void* callback_arg) + : OcrAbstractTask(callback, callback_arg) +{ + ; +} + +bool asst::IdentifyOperTask::run() +{ + if (m_view_ptr == nullptr + || m_identify_ptr == nullptr + || m_control_ptr == nullptr) + { + m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg); + return false; + } + + json::value task_start_json = json::object{ + { "task_type", "InfrastStationTask" }, + { "task_chain", OcrAbstractTask::m_task_chain}, + }; + m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg); + + std::unordered_map feature_cond = InfrastConfiger::get_instance().m_oper_name_feat; + std::unordered_set feature_whatever = InfrastConfiger::get_instance().m_oper_name_feat_whatever; + std::unordered_set detected_opers; + //auto swipe_foo = std::bind(&IdentifyOperTask::swipe, *this); + + // 一边识别一边滑动,把所有干员名字抓出来 + while (true) { + const cv::Mat& image = OcrAbstractTask::get_format_image(true); + // 异步进行滑动操作 + std::future swipe_future = std::async(std::launch::async, &IdentifyOperTask::swipe, this, false); + + auto cur_name_textarea = detect_opers(image, feature_cond, feature_whatever); + + int oper_numer = detected_opers.size(); + for (const TextArea& textarea : cur_name_textarea) + { + cv::Rect elite_rect; + // 因为有的名字长有的名字短,但是右对齐的,所以跟着右边走 + // TODO,这些长宽的参数要跟着分辨率缩放,最好放到配置文件里 + elite_rect.x = textarea.rect.x + textarea.rect.width - 250; + elite_rect.y = textarea.rect.y - 200; + if (elite_rect.x < 0 || elite_rect.y < 0) { + continue; + } + elite_rect.width = 100; + elite_rect.height = 150; + cv::Mat elite_mat = image(elite_rect); + + // for debug + static cv::Mat elite1 = cv::imread(GetResourceDir() + "operators\\Elite1.png"); + static cv::Mat elite2 = cv::imread(GetResourceDir() + "operators\\Elite2.png"); + auto&& [score1, point1] = OcrAbstractTask::m_identify_ptr->match_template(elite_mat, elite1); + auto&& [score2, point2] = OcrAbstractTask::m_identify_ptr->match_template(elite_mat, elite2); +#ifdef LOG_TRACE + std::cout << "elite1:" << score1 << ", elite2:" << score2 << std::endl; +#endif + OperInfrastInfo info; + info.name = textarea.text; + if (score1 > score2 && score1 > 0.7) { + info.elite = 1; + } + else if (score2 > score1 && score2 > 0.7) { + info.elite = 2; + } + else { + info.elite = 0; + } + detected_opers.emplace(std::move(info)); + } + + json::value opers_json; + std::vector opers_json_vec; + for (const OperInfrastInfo& info : detected_opers) { + json::value info_json; + info_json["name"] = Utf8ToGbk(info.name); + info_json["elite"] = info.elite; + //info_json["level"] = info.level; + opers_json_vec.emplace_back(std::move(info_json)); + } + opers_json["all"] = json::array(opers_json_vec); + m_callback(AsstMsg::InfrastOpers, opers_json, m_callback_arg); + + // 阻塞等待滑动结束 + if (!swipe_future.get()) { + return false; + } + // 说明本次识别一个新的都没识别到,应该是滑动到最后了,直接结束循环 + if (oper_numer == detected_opers.size()) { + break; + } + } + + return true; +} + +std::vector