perf: 优化干员识别 flag 检测
@@ -2323,30 +2323,6 @@
|
||||
"[Uu]-[O0o]f{1,2}icial",
|
||||
"U-Official"
|
||||
],
|
||||
[
|
||||
"^4",
|
||||
""
|
||||
],
|
||||
[
|
||||
"^α",
|
||||
""
|
||||
],
|
||||
[
|
||||
"^-",
|
||||
""
|
||||
],
|
||||
[
|
||||
"—",
|
||||
""
|
||||
],
|
||||
[
|
||||
".*12F",
|
||||
"12F"
|
||||
],
|
||||
[
|
||||
"^_",
|
||||
""
|
||||
],
|
||||
[
|
||||
".*威龙陈",
|
||||
"假日威龙陈"
|
||||
@@ -9862,15 +9838,33 @@
|
||||
20
|
||||
]
|
||||
},
|
||||
"OperBoxFlagLV": {
|
||||
"templThreshold": 0.6,
|
||||
"OperBoxFlagRoleTopROI": {
|
||||
"template": "empty.png",
|
||||
"roi": [
|
||||
40,
|
||||
310,
|
||||
1128,
|
||||
327
|
||||
0,
|
||||
78,
|
||||
1145,
|
||||
50
|
||||
]
|
||||
},
|
||||
"OperBoxFlagRoleBottomROI": {
|
||||
"template": "empty.png",
|
||||
"roi": [
|
||||
0,
|
||||
394,
|
||||
1145,
|
||||
50
|
||||
]
|
||||
},
|
||||
"OperBoxFlagRole1": {},
|
||||
"OperBoxFlagRole2": {},
|
||||
"OperBoxFlagRole3": {},
|
||||
"OperBoxFlagRole4": {},
|
||||
"OperBoxFlagRole5": {},
|
||||
"OperBoxFlagRole6": {},
|
||||
"OperBoxFlagRole7": {},
|
||||
"OperBoxFlagRole8": {},
|
||||
"OperBoxFlagRole9": {},
|
||||
"OperBoxFlagElite1": {
|
||||
"doc": "精英一 模板"
|
||||
},
|
||||
@@ -9882,8 +9876,8 @@
|
||||
"template": "empty.png",
|
||||
"templThreshold": 0.9,
|
||||
"roi": [
|
||||
-7,
|
||||
-52,
|
||||
11,
|
||||
171,
|
||||
24,
|
||||
35
|
||||
]
|
||||
@@ -9893,8 +9887,8 @@
|
||||
"template": "empty.png",
|
||||
"templThreshold": 0.85,
|
||||
"roi": [
|
||||
81,
|
||||
-29,
|
||||
99,
|
||||
194,
|
||||
24,
|
||||
24
|
||||
]
|
||||
@@ -9905,16 +9899,14 @@
|
||||
"OperBoxPotential4": {},
|
||||
"OperBoxPotential5": {},
|
||||
"OperBoxNameOCR": {
|
||||
"algorithm": "OcrDetect",
|
||||
"fullMatch": true,
|
||||
"baseTask": "CharsNameOcrReplace",
|
||||
"text": [],
|
||||
"roi": [
|
||||
5,
|
||||
42,
|
||||
105,
|
||||
20
|
||||
],
|
||||
"postDelay": 100
|
||||
4,
|
||||
269,
|
||||
122,
|
||||
14
|
||||
]
|
||||
},
|
||||
"OperBoxLevelOCR": {
|
||||
"algorithm": "OcrDetect",
|
||||
@@ -9922,12 +9914,11 @@
|
||||
"isAscii": true,
|
||||
"text": [],
|
||||
"roi": [
|
||||
-13,
|
||||
7,
|
||||
5,
|
||||
230,
|
||||
37,
|
||||
23
|
||||
],
|
||||
"postDelay": 100
|
||||
]
|
||||
},
|
||||
"RoguelikeRecruitSwipeMaxTime": {
|
||||
"algorithm": "JustReturn",
|
||||
|
||||
|
Before Width: | Height: | Size: 343 B |
BIN
resource/template/OperBoxFlagRole1.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
resource/template/OperBoxFlagRole2.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
resource/template/OperBoxFlagRole3.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
resource/template/OperBoxFlagRole4.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
resource/template/OperBoxFlagRole5.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
resource/template/OperBoxFlagRole6.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
resource/template/OperBoxFlagRole7.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
resource/template/OperBoxFlagRole8.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
resource/template/OperBoxFlagRole9.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
@@ -118,29 +118,5 @@ std::vector<BattlefieldDetector::OperatorResult> BattlefieldDetector::operator_a
|
||||
all_results.emplace_back(std::move(box));
|
||||
}
|
||||
|
||||
// NMS
|
||||
constexpr double NmsThreshold = 0.7f;
|
||||
std::sort(all_results.begin(), all_results.end(),
|
||||
[](const OperatorResult& a, const OperatorResult& b) { return a.score > b.score; });
|
||||
|
||||
std::vector<OperatorResult> nms_results;
|
||||
for (size_t i = 0; i < all_results.size(); ++i) {
|
||||
const auto& box = all_results[i];
|
||||
if (box.score < 0.1f) {
|
||||
continue;
|
||||
}
|
||||
nms_results.emplace_back(box);
|
||||
for (size_t j = i + 1; j < all_results.size(); ++j) {
|
||||
auto& box2 = all_results[j];
|
||||
if (box2.score < 0.1f) {
|
||||
continue;
|
||||
}
|
||||
int iou_area = (make_rect<cv::Rect>(box.rect) & make_rect<cv::Rect>(box2.rect)).area();
|
||||
if (iou_area > NmsThreshold * box2.rect.area()) {
|
||||
box2.score = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nms_results;
|
||||
return NMS(all_results);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Config/Miscellaneous/BattleDataConfig.h"
|
||||
#include "Config/TaskData.h"
|
||||
#include "Utils/ImageIo.hpp"
|
||||
#include "Utils/Logger.hpp"
|
||||
#include "Vision/BestMatcher.h"
|
||||
#include "Vision/Matcher.h"
|
||||
@@ -57,23 +58,44 @@ bool asst::OperBoxImageAnalyzer::analyzer_oper_box()
|
||||
|
||||
bool asst::OperBoxImageAnalyzer::opers_analyze()
|
||||
{
|
||||
const auto& ocr_replace = Task.get<OcrTaskInfo>("CharsNameOcrReplace");
|
||||
|
||||
TemplDetOCRer oper_name_analyzer(m_image);
|
||||
|
||||
oper_name_analyzer.set_task_info("OperBoxFlagLV", "OperBoxNameOCR");
|
||||
oper_name_analyzer.set_replace(ocr_replace->replace_map, ocr_replace->replace_full);
|
||||
oper_name_analyzer.set_bin_threshold(160);
|
||||
oper_name_analyzer.set_bin_expansion(4);
|
||||
oper_name_analyzer.set_bin_trim_threshold(4, 0);
|
||||
const auto& all_opers = BattleData.get_all_oper_names();
|
||||
oper_name_analyzer.set_required(std::vector(all_opers.begin(), all_opers.end()));
|
||||
if (!oper_name_analyzer.analyze()) {
|
||||
|
||||
TemplDetOCRer::ResultsVec results;
|
||||
|
||||
Rect roi_top = Task.get("OperBoxFlagRoleTopROI")->roi;
|
||||
Rect roi_bottom = Task.get("OperBoxFlagRoleBottomROI")->roi;
|
||||
|
||||
for (int i = 1; i < 10; ++i) {
|
||||
oper_name_analyzer.set_task_info("OperBoxFlagRole" + std::to_string(i), "OperBoxNameOCR");
|
||||
|
||||
oper_name_analyzer.set_roi(roi_top);
|
||||
auto top_result_opt = oper_name_analyzer.analyze();
|
||||
if (top_result_opt) {
|
||||
results.insert(results.end(), std::make_move_iterator(top_result_opt->begin()),
|
||||
std::make_move_iterator(top_result_opt->end()));
|
||||
}
|
||||
|
||||
oper_name_analyzer.set_roi(roi_bottom);
|
||||
auto bottom_result_opt = oper_name_analyzer.analyze();
|
||||
if (bottom_result_opt) {
|
||||
results.insert(results.end(), std::make_move_iterator(bottom_result_opt->begin()),
|
||||
std::make_move_iterator(bottom_result_opt->end()));
|
||||
}
|
||||
}
|
||||
|
||||
if (results.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto result_list = oper_name_analyzer.get_result();
|
||||
sort_by_horizontal_(result_list);
|
||||
results = NMS(results);
|
||||
sort_by_horizontal_(results);
|
||||
|
||||
for (const auto& oper : result_list) {
|
||||
for (const auto& oper : results) {
|
||||
const Rect& flag_rect = oper.flag_rect;
|
||||
const std::string& name = oper.text;
|
||||
|
||||
@@ -87,7 +109,7 @@ bool asst::OperBoxImageAnalyzer::opers_analyze()
|
||||
|
||||
#ifdef ASST_DEBUG
|
||||
cv::rectangle(m_image_draw, make_rect<cv::Rect>(flag_rect), cv::Scalar(0, 255, 0), 1);
|
||||
cv::putText(m_image_draw, std::to_string(oper.flag_score), cv::Point(flag_rect.x + 10, flag_rect.y),
|
||||
cv::putText(m_image_draw, std::to_string(oper.flag_score), cv::Point(flag_rect.x, flag_rect.y - 10),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1);
|
||||
cv::rectangle(m_image_draw, make_rect<cv::Rect>(oper.rect), cv::Scalar(0, 255, 0), 1);
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace asst
|
||||
Rect rect;
|
||||
bool own = false;
|
||||
};
|
||||
|
||||
class OperBoxImageAnalyzer final : public VisionHelper
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -109,4 +109,31 @@ namespace asst
|
||||
return lvalue < rvalue;
|
||||
});
|
||||
}
|
||||
|
||||
// Non-Maximum Suppression
|
||||
template <typename ResultsVec>
|
||||
inline static ResultsVec NMS(ResultsVec& results, double threshold = 0.7)
|
||||
{
|
||||
ranges::sort(results, [](const auto& a, const auto& b) { return a.score > b.score; });
|
||||
|
||||
ResultsVec nms_results;
|
||||
for (size_t i = 0; i < results.size(); ++i) {
|
||||
const auto& box = results[i];
|
||||
if (box.score < 0.1f) {
|
||||
continue;
|
||||
}
|
||||
nms_results.emplace_back(box);
|
||||
for (size_t j = i + 1; j < results.size(); ++j) {
|
||||
auto& box2 = results[j];
|
||||
if (box2.score < 0.1f) {
|
||||
continue;
|
||||
}
|
||||
int iou_area = (make_rect<cv::Rect>(box.rect) & make_rect<cv::Rect>(box2.rect)).area();
|
||||
if (iou_area > threshold * box2.rect.area()) {
|
||||
box2.score = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nms_results;
|
||||
}
|
||||
} // namespace asst
|
||||
|
||||