Skip to content

Commit a4d30be

Browse files
committed
fix: 修复 and, or 算法中 reco_id 冲突
1 parent 2ef8b56 commit a4d30be

4 files changed

Lines changed: 140 additions & 95 deletions

File tree

source/MaaFramework/Task/Component/Recognizer.cpp

Lines changed: 98 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,90 @@ Recognizer::Recognizer(Tasker* tasker, Context& context, const cv::Mat& image_)
1919
: tasker_(tasker)
2020
, context_(context)
2121
, image_(image_)
22+
, sub_filtered_boxes_(std::make_shared<typename decltype(sub_filtered_boxes_)::element_type>())
23+
, sub_best_box_(std::make_shared<typename decltype(sub_best_box_)::element_type>())
2224
{
2325
}
2426

25-
RecoResult Recognizer::recognize(const PipelineData& pipeline_data)
27+
Recognizer::Recognizer(const Recognizer& recognizer)
28+
: tasker_(recognizer.tasker_)
29+
, context_(recognizer.context_)
30+
, image_(recognizer.image_)
31+
// do not copy reco_id_
32+
, sub_filtered_boxes_(recognizer.sub_filtered_boxes_)
33+
, sub_best_box_(recognizer.sub_best_box_)
2634
{
35+
}
36+
37+
RecoResult Recognizer::recognize(MAA_RES_NS::Recognition::Type type, const MAA_RES_NS::Recognition::Param& param, const std::string& name)
38+
{
39+
using namespace MAA_RES_NS::Recognition;
40+
using namespace MAA_VISION_NS;
41+
2742
if (!tasker_) {
2843
LogError << "tasker is null";
2944
return {};
3045
}
3146

32-
RecoResult result = run_recognition(pipeline_data.reco_type, pipeline_data.reco_param, pipeline_data.name);
47+
RecoResult result;
48+
49+
switch (type) {
50+
case Type::DirectHit:
51+
result = direct_hit(std::get<DirectHitParam>(param), name);
52+
break;
53+
54+
case Type::TemplateMatch:
55+
result = template_match(std::get<TemplateMatcherParam>(param), name);
56+
break;
57+
58+
case Type::FeatureMatch:
59+
result = feature_match(std::get<FeatureMatcherParam>(param), name);
60+
break;
61+
62+
case Type::ColorMatch:
63+
result = color_match(std::get<ColorMatcherParam>(param), name);
64+
break;
65+
66+
case Type::OCR:
67+
result = ocr(std::get<OCRerParam>(param), name);
68+
break;
69+
70+
case Type::NeuralNetworkClassify:
71+
result = nn_classify(std::get<NeuralNetworkClassifierParam>(param), name);
72+
break;
73+
74+
case Type::NeuralNetworkDetect:
75+
result = nn_detect(std::get<NeuralNetworkDetectorParam>(param), name);
76+
break;
77+
78+
case Type::And:
79+
result = and_(std::get<std::shared_ptr<AndParam>>(param), name);
80+
break;
81+
82+
case Type::Or:
83+
result = or_(std::get<std::shared_ptr<OrParam>>(param), name);
84+
break;
85+
86+
case Type::Custom:
87+
result = custom_recognize(std::get<CustomRecognitionParam>(param), name);
88+
break;
89+
90+
default:
91+
LogError << "Unknown recognition type" << VAR(static_cast<int>(type)) << VAR(name);
92+
break;
93+
}
3394

3495
if (debug_mode()) {
3596
ImageEncodedBuffer png;
3697
cv::imencode(".png", image_, png);
3798
result.raw = std::move(png);
3899
}
39100

40-
if (pipeline_data.inverse) {
41-
LogDebug << "pipeline_data.inverse is true, reverse the result" << VAR(pipeline_data.name) << VAR(result.box);
42-
result.box = result.box ? std::nullopt : std::make_optional<cv::Rect>();
43-
}
44-
45101
LogInfo << "reco" << VAR(result);
46102
auto& rt_cache = tasker_->runtime_cache();
47103
rt_cache.set_reco_detail(result.reco_id, result);
48104

49-
save_draws(pipeline_data.name, result);
105+
save_draws(name, result);
50106

51107
return result;
52108
}
@@ -82,8 +138,8 @@ RecoResult Recognizer::direct_hit(const MAA_VISION_NS::DirectHitParam& param, co
82138
// DirectHit: 使用第一个 ROI 作为 box
83139
cv::Rect box = rois.empty() ? cv::Rect {} : rois.front();
84140

85-
sub_filtered_boxes_.insert_or_assign(name, rois);
86-
sub_best_box_.insert_or_assign(name, box);
141+
sub_filtered_boxes_->insert_or_assign(name, rois);
142+
sub_best_box_->insert_or_assign(name, box);
87143

88144
return RecoResult {
89145
.reco_id = reco_id_,
@@ -102,8 +158,8 @@ RecoResult Recognizer::template_match(const MAA_VISION_NS::TemplateMatcherParam&
102158
auto templs = context_.get_images(param.template_);
103159
TemplateMatcher analyzer(image_, rois, param, templs, name);
104160

105-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
106-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
161+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
162+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
107163

108164
std::optional<cv::Rect> box = std::nullopt;
109165
if (analyzer.best_result()) {
@@ -127,8 +183,8 @@ RecoResult Recognizer::feature_match(const MAA_VISION_NS::FeatureMatcherParam& p
127183
auto templs = context_.get_images(param.template_);
128184
FeatureMatcher analyzer(image_, rois, param, templs, name);
129185

130-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
131-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
186+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
187+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
132188

133189
std::optional<cv::Rect> box = std::nullopt;
134190
if (analyzer.best_result()) {
@@ -151,8 +207,8 @@ RecoResult Recognizer::color_match(const MAA_VISION_NS::ColorMatcherParam& param
151207

152208
ColorMatcher analyzer(image_, rois, param, name);
153209

154-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
155-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
210+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
211+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
156212

157213
std::optional<cv::Rect> box = std::nullopt;
158214
if (analyzer.best_result()) {
@@ -184,8 +240,8 @@ RecoResult Recognizer::ocr(const MAA_VISION_NS::OCRerParam& param, const std::st
184240

185241
OCRer analyzer(image_, rois, param, det_session, reco_session, ocr_session, name);
186242

187-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
188-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
243+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
244+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
189245

190246
std::optional<cv::Rect> box = std::nullopt;
191247
if (analyzer.best_result()) {
@@ -217,8 +273,8 @@ RecoResult Recognizer::nn_classify(const MAA_VISION_NS::NeuralNetworkClassifierP
217273

218274
NeuralNetworkClassifier analyzer(image_, rois, param, session, mem_info, name);
219275

220-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
221-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
276+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
277+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
222278

223279
std::optional<cv::Rect> box = std::nullopt;
224280
if (analyzer.best_result()) {
@@ -250,8 +306,8 @@ RecoResult Recognizer::nn_detect(const MAA_VISION_NS::NeuralNetworkDetectorParam
250306

251307
NeuralNetworkDetector analyzer(image_, rois, param, session, mem_info, name);
252308

253-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
254-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
309+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
310+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
255311

256312
std::optional<cv::Rect> box = std::nullopt;
257313
if (analyzer.best_result()) {
@@ -280,8 +336,8 @@ RecoResult Recognizer::custom_recognize(const MAA_VISION_NS::CustomRecognitionPa
280336
auto session = resource()->custom_recognition(param.name);
281337
CustomRecognition analyzer(image_, rois.empty() ? cv::Rect {} : rois.front(), param, session, context_, name);
282338

283-
sub_filtered_boxes_.insert_or_assign(name, get_boxes(analyzer.filtered_results()));
284-
sub_best_box_.insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
339+
sub_filtered_boxes_->insert_or_assign(name, get_boxes(analyzer.filtered_results()));
340+
sub_best_box_->insert_or_assign(name, analyzer.best_result() ? analyzer.best_result()->box : cv::Rect {});
285341

286342
std::optional<cv::Rect> box = std::nullopt;
287343
if (analyzer.best_result()) {
@@ -310,7 +366,8 @@ RecoResult Recognizer::and_(const std::shared_ptr<MAA_RES_NS::Recognition::AndPa
310366

311367
for (const auto& sub_reco : param->all_of) {
312368
LogDebug << "And: run sub recognition" << VAR(sub_reco.type) << VAR(sub_reco.sub_name);
313-
RecoResult res = run_recognition(sub_reco.type, sub_reco.param, sub_reco.sub_name);
369+
Recognizer sub_recognizer(*this);
370+
RecoResult res = sub_recognizer.recognize(sub_reco.type, sub_reco.param, sub_reco.sub_name);
314371
all_hit &= res.box.has_value();
315372

316373
sub_results.emplace_back(std::move(res));
@@ -336,25 +393,25 @@ RecoResult Recognizer::and_(const std::shared_ptr<MAA_RES_NS::Recognition::AndPa
336393

337394
if (!all_hit) {
338395
LogDebug << "And recognition failed" << VAR(name);
339-
sub_filtered_boxes_.insert_or_assign(name, std::vector<cv::Rect> {});
340-
sub_best_box_.insert_or_assign(name, cv::Rect {});
396+
sub_filtered_boxes_->insert_or_assign(name, std::vector<cv::Rect> {});
397+
sub_best_box_->insert_or_assign(name, cv::Rect {});
341398
return result;
342399
}
343400

344401
if (static_cast<int>(sub_results.size()) <= param->box_index) {
345402
LogError << "all hit, but box_index is out of range" << VAR(name) << VAR(sub_results.size()) << VAR(param->box_index);
346403
result.box = std::nullopt;
347-
sub_filtered_boxes_.insert_or_assign(name, std::vector<cv::Rect> {});
348-
sub_best_box_.insert_or_assign(name, cv::Rect {});
404+
sub_filtered_boxes_->insert_or_assign(name, std::vector<cv::Rect> {});
405+
sub_best_box_->insert_or_assign(name, cv::Rect {});
349406
return result;
350407
}
351408

352409
result.box = std::move(sub_results[param->box_index].box);
353410

354411
cv::Rect final_box = result.box.value_or(cv::Rect {});
355412
// 按理说这里要从 sub 取的,但是太麻烦而且是 corner case,先不管了,后面有需要再加
356-
sub_filtered_boxes_.insert_or_assign(name, std::vector<cv::Rect> { final_box });
357-
sub_best_box_.insert_or_assign(name, final_box);
413+
sub_filtered_boxes_->insert_or_assign(name, std::vector<cv::Rect> { final_box });
414+
sub_best_box_->insert_or_assign(name, final_box);
358415

359416
return result;
360417
}
@@ -374,7 +431,8 @@ RecoResult Recognizer::or_(const std::shared_ptr<MAA_RES_NS::Recognition::OrPara
374431

375432
for (const auto& sub_reco : param->any_of) {
376433
LogDebug << "Or: run sub recognition" << VAR(sub_reco.type) << VAR(sub_reco.sub_name);
377-
RecoResult res = run_recognition(sub_reco.type, sub_reco.param, sub_reco.sub_name);
434+
Recognizer sub_recognizer(*this);
435+
RecoResult res = sub_recognizer.recognize(sub_reco.type, sub_reco.param, sub_reco.sub_name);
378436
has_hit = res.box.has_value();
379437
sub_results.emplace_back(std::move(res));
380438

@@ -398,71 +456,28 @@ RecoResult Recognizer::or_(const std::shared_ptr<MAA_RES_NS::Recognition::OrPara
398456

399457
if (!has_hit) {
400458
LogDebug << "Or recognition failed" << VAR(name);
401-
sub_filtered_boxes_.insert_or_assign(name, std::vector<cv::Rect> {});
402-
sub_best_box_.insert_or_assign(name, cv::Rect {});
459+
sub_filtered_boxes_->insert_or_assign(name, std::vector<cv::Rect> {});
460+
sub_best_box_->insert_or_assign(name, cv::Rect {});
403461
return result;
404462
}
405463

406464
if (sub_results.empty()) {
407465
LogError << "has hit, but no sub results" << VAR(name);
408-
sub_filtered_boxes_.insert_or_assign(name, std::vector<cv::Rect> {});
409-
sub_best_box_.insert_or_assign(name, cv::Rect {});
466+
sub_filtered_boxes_->insert_or_assign(name, std::vector<cv::Rect> {});
467+
sub_best_box_->insert_or_assign(name, cv::Rect {});
410468
return {};
411469
}
412470

413471
result.box = std::move(sub_results.back().box);
414472

415473
cv::Rect final_box = result.box.value_or(cv::Rect {});
416474
// 按理说这里要从 sub 取的,但是太麻烦而且是 corner case,先不管了,后面有需要再加
417-
sub_filtered_boxes_.insert_or_assign(name, std::vector<cv::Rect> { final_box });
418-
sub_best_box_.insert_or_assign(name, final_box);
475+
sub_filtered_boxes_->insert_or_assign(name, std::vector<cv::Rect> { final_box });
476+
sub_best_box_->insert_or_assign(name, final_box);
419477

420478
return result;
421479
}
422480

423-
RecoResult
424-
Recognizer::run_recognition(MAA_RES_NS::Recognition::Type type, const MAA_RES_NS::Recognition::Param& param, const std::string& name)
425-
{
426-
using namespace MAA_RES_NS::Recognition;
427-
using namespace MAA_VISION_NS;
428-
429-
switch (type) {
430-
case Type::DirectHit:
431-
return direct_hit(std::get<DirectHitParam>(param), name);
432-
433-
case Type::TemplateMatch:
434-
return template_match(std::get<TemplateMatcherParam>(param), name);
435-
436-
case Type::FeatureMatch:
437-
return feature_match(std::get<FeatureMatcherParam>(param), name);
438-
439-
case Type::ColorMatch:
440-
return color_match(std::get<ColorMatcherParam>(param), name);
441-
442-
case Type::OCR:
443-
return ocr(std::get<OCRerParam>(param), name);
444-
445-
case Type::NeuralNetworkClassify:
446-
return nn_classify(std::get<NeuralNetworkClassifierParam>(param), name);
447-
448-
case Type::NeuralNetworkDetect:
449-
return nn_detect(std::get<NeuralNetworkDetectorParam>(param), name);
450-
451-
case Type::And:
452-
return and_(std::get<std::shared_ptr<AndParam>>(param), name);
453-
454-
case Type::Or:
455-
return or_(std::get<std::shared_ptr<OrParam>>(param), name);
456-
457-
case Type::Custom:
458-
return custom_recognize(std::get<CustomRecognitionParam>(param), name);
459-
460-
default:
461-
LogError << "Unknown recognition type" << VAR(static_cast<int>(type)) << VAR(name);
462-
return {};
463-
}
464-
}
465-
466481
std::vector<cv::Rect> Recognizer::get_rois(const MAA_VISION_NS::Target& roi, bool use_best)
467482
{
468483
if (!tasker_) {
@@ -504,13 +519,13 @@ std::vector<cv::Rect> Recognizer::get_rois(const MAA_VISION_NS::Target& roi, boo
504519
std::vector<cv::Rect> Recognizer::get_rois_from_pretask(const std::string& name, bool use_best)
505520
{
506521
if (use_best) {
507-
if (auto it = sub_best_box_.find(name); it != sub_best_box_.end()) {
522+
if (auto it = sub_best_box_->find(name); it != sub_best_box_->end()) {
508523
LogDebug << "pre task from sub_best_box_" << VAR(name) << VAR(it->second);
509524
return { it->second };
510525
}
511526
}
512527
else {
513-
if (auto it = sub_filtered_boxes_.find(name); it != sub_filtered_boxes_.end()) {
528+
if (auto it = sub_filtered_boxes_->find(name); it != sub_filtered_boxes_->end()) {
514529
LogDebug << "pre task from sub_filtered_boxes_" << VAR(name) << VAR(it->second.size());
515530
return it->second;
516531
}

source/MaaFramework/Task/Component/Recognizer.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212

1313
MAA_TASK_NS_BEGIN
1414

15-
class Recognizer : public NonCopyable
15+
class Recognizer
1616
{
1717
public:
18-
explicit Recognizer(Tasker* tasker, Context& context, const cv::Mat& image);
18+
Recognizer(Tasker* tasker, Context& context, const cv::Mat& image);
19+
Recognizer(const Recognizer& recognizer);
1920

2021
public:
21-
RecoResult recognize(const PipelineData& pipeline_data);
22+
RecoResult recognize(MAA_RES_NS::Recognition::Type type, const MAA_RES_NS::Recognition::Param& param, const std::string& name);
2223

2324
MaaRecoId get_id() const { return reco_id_; }
2425

@@ -34,8 +35,6 @@ class Recognizer : public NonCopyable
3435
RecoResult or_(const std::shared_ptr<MAA_RES_NS::Recognition::OrParam>& param, const std::string& name);
3536
RecoResult custom_recognize(const MAA_VISION_NS::CustomRecognitionParam& param, const std::string& name);
3637

37-
RecoResult run_recognition(MAA_RES_NS::Recognition::Type type, const MAA_RES_NS::Recognition::Param& param, const std::string& name);
38-
3938
std::vector<cv::Rect> get_rois(const MAA_VISION_NS::Target& roi, bool use_best = false);
4039
std::vector<cv::Rect> get_rois_from_pretask(const std::string& name, bool use_best);
4140
void save_draws(const std::string& node_name, const RecoResult& result) const;
@@ -53,8 +52,8 @@ class Recognizer : public NonCopyable
5352
const MaaRecoId reco_id_ = ++s_global_reco_id;
5453

5554
// for AND recognition sub-box caching
56-
std::unordered_map<std::string, std::vector<cv::Rect>> sub_filtered_boxes_;
57-
std::unordered_map<std::string, cv::Rect> sub_best_box_;
55+
std::shared_ptr<std::unordered_map<std::string, std::vector<cv::Rect>>> sub_filtered_boxes_;
56+
std::shared_ptr<std::unordered_map<std::string, cv::Rect>> sub_best_box_;
5857
};
5958

6059
MAA_TASK_NS_END

source/MaaFramework/Task/TaskBase.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,12 @@ RecoResult TaskBase::run_recognition(const cv::Mat& image, const PipelineData& d
8585

8686
notify(MaaMsg_Node_Recognition_Starting, cb_detail);
8787

88-
RecoResult result = recognizer.recognize(data);
88+
RecoResult result = recognizer.recognize(data.reco_type, data.reco_param, data.name);
89+
90+
if (data.inverse) {
91+
LogDebug << "pipeline_data.inverse is true, reverse the result" << VAR(data.name) << VAR(result.box);
92+
result.box = result.box ? std::nullopt : std::make_optional<cv::Rect>();
93+
}
8994

9095
cb_detail["reco_details"] = result;
9196
notify(result.box ? MaaMsg_Node_Recognition_Succeeded : MaaMsg_Node_Recognition_Failed, cb_detail);

0 commit comments

Comments
 (0)