diff --git a/resource/tasks.json b/resource/tasks.json index 6445572a31..e626988f75 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -473,8 +473,14 @@ "ReturnToMall" ] }, - "CreditShop-CreditPoint": { - "template": "CreditPoint.png" + "CreditShop-Commoditys": { + "template": "CreditPoint.png", + "resultMove": [ + -60, + -180, + 220, + 220 + ] }, "CreditShop-SoldOut": { "template": "SoldOut.png" @@ -497,6 +503,20 @@ 110 ] }, + "CreditShop-NotToBuy": { + "algorithm": "OcrDetect", + "Doc": "这里的text,是子串搜索,即商品名中只要含有任一text,就不买", + "text": [ + "碳", + "家具" + ], + "roi": [ + 0, + -30, + 220, + 70 + ] + }, "Stop": { "algorithm": "justreturn", "action": "stop", diff --git a/src/MeoAssistance/CreditShopImageAnalyzer.cpp b/src/MeoAssistance/CreditShopImageAnalyzer.cpp index 8c7ab304a4..51f3d20896 100644 --- a/src/MeoAssistance/CreditShopImageAnalyzer.cpp +++ b/src/MeoAssistance/CreditShopImageAnalyzer.cpp @@ -9,82 +9,68 @@ bool asst::CreditShopImageAnalyzer::analyze() { - m_credit_points.clear(); + m_commoditys.clear(); m_need_to_buy.clear(); m_result.clear(); - return credit_point_analyze() - && commoditys_analyze() + return commoditys_analyze() + && whether_to_buy_analyze() && sold_out_analyze(); } -bool asst::CreditShopImageAnalyzer::credit_point_analyze() +bool asst::CreditShopImageAnalyzer::commoditys_analyze() { - const static auto credit_point_task_ptr = std::dynamic_pointer_cast( - resource.task().task_ptr("CreditShop-CreditPoint")); + const static auto commodity_task_ptr = std::dynamic_pointer_cast( + resource.task().task_ptr("CreditShop-Commoditys")); // 识别信用点的图标 MultiMatchImageAnalyzer mm_annlyzer( m_image, - credit_point_task_ptr->roi, - credit_point_task_ptr->templ_name, - credit_point_task_ptr->templ_threshold); + commodity_task_ptr->roi, + commodity_task_ptr->templ_name, + commodity_task_ptr->templ_threshold); if (!mm_annlyzer.analyze()) { return false; } + mm_annlyzer.sort_result(); auto credit_points_result = mm_annlyzer.get_result(); if (credit_points_result.empty()) { return false; } - // 按位置排个序 - std::sort(credit_points_result.begin(), credit_points_result.end(), - [](const MatchRect& lhs, const MatchRect& rhs) -> bool { - if (std::abs(lhs.rect.y - rhs.rect.y) < 5) { // y差距较小则理解为是同一排的,按x排序 - return lhs.rect.x < rhs.rect.x; - } - else { - return lhs.rect.y < rhs.rect.y; - } - } - ); - m_credit_points.reserve(credit_points_result.size()); + + m_commoditys.reserve(credit_points_result.size()); for (const MatchRect& mr : credit_points_result) { - m_credit_points.emplace_back(mr.rect); + Rect commodity; + commodity.x = mr.rect.x + commodity_task_ptr->result_move.x; + commodity.y = mr.rect.y + commodity_task_ptr->result_move.y; + commodity.width = commodity_task_ptr->result_move.width; + commodity.height = commodity_task_ptr->result_move.height; + m_commoditys.emplace_back(std::move(commodity)); } return true; } -bool asst::CreditShopImageAnalyzer::commoditys_analyze() +bool asst::CreditShopImageAnalyzer::whether_to_buy_analyze() { - for (const Rect& credit_point : m_credit_points) { + const static auto not_to_buy_task_ptr = std::dynamic_pointer_cast( + resource.task().task_ptr("CreditShop-NotToBuy")); + + for (const Rect& commodity : m_commoditys) { // 商品名的区域 - Rect name(credit_point.x - 80, credit_point.y - 210, 230, 70); - if (name.x < 0) { - name.x = 0; - } + Rect name_roi = not_to_buy_task_ptr->roi; + name_roi.x += commodity.x; + name_roi.y += commodity.y; - // TODO,哪些要买哪些不买,提供个接口出去 - static const std::vector not_to_buy_names = { "碳", "家具" }; - - OcrImageAnalyzer ocr_analyzer(m_image, name); - if (!ocr_analyzer.analyze()) { + OcrImageAnalyzer ocr_analyzer(m_image, name_roi); + ocr_analyzer.set_required(not_to_buy_task_ptr->text); + if (ocr_analyzer.analyze()) { + //因为是不买的,有识别结果说明这个商品不买,直接跳过 continue; } const auto& ocr_res = ocr_analyzer.get_result(); - auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), not_to_buy_names.cbegin(), not_to_buy_names.cend(), - [](const auto& lhs, const std::string& rhs) -> bool { - return lhs.text.find(rhs) != std::string::npos; - }); - if (find_iter != ocr_res.cend()) { // 找到了不需要买的名字 -#ifdef LOG_TRACE - cv::putText(m_image, "Not to buy", cv::Point(credit_point.x, credit_point.y), 1, 2, cv::Scalar(255, 0, 0)); -#endif // LOG_TRACE - continue; - } - Rect commodity(credit_point.x - 60, credit_point.y - 180, 220, 220); #ifdef LOG_TRACE cv::rectangle(m_image, utils::make_rect(commodity), cv::Scalar(0, 0, 255), 2); #endif diff --git a/src/MeoAssistance/CreditShopImageAnalyzer.h b/src/MeoAssistance/CreditShopImageAnalyzer.h index 7e4de30a83..1dd35ec768 100644 --- a/src/MeoAssistance/CreditShopImageAnalyzer.h +++ b/src/MeoAssistance/CreditShopImageAnalyzer.h @@ -14,11 +14,11 @@ namespace asst { return m_result; } protected: - bool credit_point_analyze(); bool commoditys_analyze(); + bool whether_to_buy_analyze(); bool sold_out_analyze(); - std::vector m_credit_points; + std::vector m_commoditys; std::vector m_need_to_buy; std::vector m_result; }; diff --git a/src/MeoAssistance/MultiMatchImageAnalyzer.cpp b/src/MeoAssistance/MultiMatchImageAnalyzer.cpp index e9542313ec..df52c1bdfb 100644 --- a/src/MeoAssistance/MultiMatchImageAnalyzer.cpp +++ b/src/MeoAssistance/MultiMatchImageAnalyzer.cpp @@ -23,6 +23,21 @@ bool asst::MultiMatchImageAnalyzer::analyze() return multi_match_templ(templ); } +void asst::MultiMatchImageAnalyzer::sort_result() +{ + // 按位置排个序 + std::sort(m_result.begin(), m_result.end(), + [](const MatchRect& lhs, const MatchRect& rhs) -> bool { + if (std::abs(lhs.rect.y - rhs.rect.y) < 5) { // y差距较小则理解为是同一排的,按x排序 + return lhs.rect.x < rhs.rect.x; + } + else { + return lhs.rect.y < rhs.rect.y; + } + } + ); +} + bool asst::MultiMatchImageAnalyzer::multi_match_templ(const cv::Mat& templ) { cv::Mat matched; diff --git a/src/MeoAssistance/MultiMatchImageAnalyzer.h b/src/MeoAssistance/MultiMatchImageAnalyzer.h index 64cb67f2d7..4aba334d7e 100644 --- a/src/MeoAssistance/MultiMatchImageAnalyzer.h +++ b/src/MeoAssistance/MultiMatchImageAnalyzer.h @@ -11,6 +11,7 @@ namespace asst { virtual bool analyze() override; + void sort_result(); void set_templ_name(std::string templ_name) noexcept { m_templ_name = std::move(templ_name); }