Skip to content

Commit e8b7349

Browse files
author
Gin
committed
add hyperspace calorie detector
1 parent 863f85a commit e8b7349

File tree

6 files changed

+145
-0
lines changed

6 files changed

+145
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* Hyperspace Calorie Detector
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "CommonFramework/ImageTools/ImageStats.h"
8+
#include "CommonFramework/VideoPipeline/VideoOverlay.h"
9+
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
10+
#include "CommonTools/Images/SolidColorTest.h"
11+
#include "CommonTools/OCR/OCR_NumberReader.h"
12+
#include "PokemonLZA_HyperspaceCalorieDetector.h"
13+
14+
namespace PokemonAutomation{
15+
namespace NintendoSwitch{
16+
namespace PokemonLZA{
17+
18+
19+
HyperspaceCalorieDetector::HyperspaceCalorieDetector(Logger& logger)
20+
: m_logger(logger)
21+
, m_calorie_number_box{0.036, 0.118, 0.119, 0.059}
22+
{}
23+
24+
void HyperspaceCalorieDetector::make_overlays(VideoOverlaySet& items) const{
25+
items.add(COLOR_WHITE, m_calorie_number_box);
26+
}
27+
28+
bool HyperspaceCalorieDetector::detect(const ImageViewRGB32& screen){
29+
const ImageViewRGB32 calorie_image_crop = extract_box_reference(screen, m_calorie_number_box);
30+
31+
const bool text_inside_range = true;
32+
const bool prioritize_numeric_only_results = true;
33+
const size_t width_max = SIZE_MAX;
34+
// The calorie crop includes the "," in Calorie numbers like "1,000".
35+
// We have to use `min_digit_area` to filter out "," when doing OCR.
36+
// The min digit area computation is that any dot with size smaller than calorie_image_crop.height()/5 is filtered out when OCR.
37+
const size_t min_digit_area = calorie_image_crop.height()*calorie_image_crop.height() / 25;
38+
m_calorie_number = 0;
39+
int number = OCR::read_number_waterfill_multifilter(m_logger, calorie_image_crop,
40+
{
41+
{0xff808080, 0xffffffff},
42+
{0xffa0a0a0, 0xffffffff},
43+
{0xffc0c0c0, 0xffffffff},
44+
{0xffe0e0e0, 0xffffffff},
45+
{0xfff0f0f0, 0xffffffff},
46+
},
47+
text_inside_range, prioritize_numeric_only_results, width_max, min_digit_area
48+
);
49+
if (number <= 0 || number > 9999){
50+
return false;
51+
}
52+
m_calorie_number = static_cast<uint16_t>(number);
53+
return true;
54+
}
55+
56+
57+
58+
59+
}
60+
}
61+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* Hyperspace Calorie Detector
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_PokemonLZA_HyperspaceCalorieDetector_H
8+
#define PokemonAutomation_PokemonLZA_HyperspaceCalorieDetector_H
9+
10+
//#include <optional>
11+
#include "Common/Cpp/Color.h"
12+
#include "CommonFramework/ImageTools/ImageBoxes.h"
13+
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
14+
#include "CommonTools/VisualDetector.h"
15+
#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h"
16+
17+
namespace PokemonAutomation{
18+
class Logger;
19+
namespace NintendoSwitch{
20+
namespace PokemonLZA{
21+
22+
23+
class HyperspaceCalorieDetector : public StaticScreenDetector{
24+
public:
25+
HyperspaceCalorieDetector(Logger& logger);
26+
27+
virtual void make_overlays(VideoOverlaySet& items) const override;
28+
29+
// This is not const so that detectors can save/cache state.
30+
virtual bool detect(const ImageViewRGB32& screen) override;
31+
32+
uint16_t calorie_number() const { return m_calorie_number; }
33+
34+
private:
35+
Logger& m_logger;
36+
ImageFloatBox m_calorie_number_box;
37+
38+
uint16_t m_calorie_number = 0;
39+
};
40+
41+
42+
43+
44+
}
45+
}
46+
}
47+
#endif

SerialPrograms/Source/Tests/PokemonLZA_Tests.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h"
1212
#include "PokemonLZA/Inference/PokemonLZA_AlertEyeDetector.h"
1313
#include "PokemonLZA/Inference/PokemonLZA_MainMenuDetector.h"
14+
#include "PokemonLZA/Inference/PokemonLZA_HyperspaceCalorieDetector.h"
1415
#include "PokemonLZA/Inference/Boxes/PokemonLZA_BoxDetection.h"
1516
#include "PokemonLZA/Inference/Boxes/PokemonLZA_BoxInfoDetector.h"
1617
#include "PokemonLZA/Inference/Map/PokemonLZA_MapIconDetector.h"
@@ -597,5 +598,36 @@ int test_pokemonLZA_MapDetector(const ImageViewRGB32& image, bool target){
597598
return 0;
598599
}
599600

601+
int test_pokemonLZA_HyperspaceCalorieDetector(const ImageViewRGB32& image, int expected_calorie){
602+
// Expected filename format: <...>_<calorie_number>.png
603+
// Where calorie_number is an integer in range [1, 9999]
604+
// Examples:
605+
// calorie_100.png -> 100 calories
606+
// calorie_1500.png -> 1500 calories
607+
// calorie_9999.png -> 9999 calories
608+
609+
if (expected_calorie <= 0 || expected_calorie > 9999){
610+
cerr << "Error: expected calorie must be in range [1, 9999], got " << expected_calorie << "." << endl;
611+
return 1;
612+
}
613+
614+
// Run detector
615+
HyperspaceCalorieDetector detector(global_logger_command_line());
616+
bool detected = detector.detect(image);
617+
618+
if (!detected){
619+
cerr << "Error: detector failed to detect calorie number in image." << endl;
620+
return 1;
621+
}
622+
623+
uint16_t detected_calorie = detector.calorie_number();
624+
625+
cout << "Expected calorie: " << expected_calorie << ", Detected calorie: " << detected_calorie << endl;
626+
627+
TEST_RESULT_EQUAL((int)detected_calorie, expected_calorie);
628+
629+
return 0;
630+
}
631+
600632

601633
}

SerialPrograms/Source/Tests/PokemonLZA_Tests.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343

4444
int test_pokemonLZA_MapDetector(const ImageViewRGB32& image, bool target);
4545

46+
int test_pokemonLZA_HyperspaceCalorieDetector(const ImageViewRGB32& image, int expected_calorie);
47+
4648
}
4749

4850
#endif

SerialPrograms/Source/Tests/TestMap.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ const std::map<std::string, TestFunction> TEST_MAP = {
303303
{"PokemonLZA_OverworldPartySelectionDetector", std::bind(image_words_detector_helper, test_pokemonLZA_OverworldPartySelectionDetector, _1)},
304304
{"PokemonLZA_DirectionArrowDetector", std::bind(image_int_detector_helper, test_pokemonLZA_DirectionArrowDetector, _1)},
305305
{"PokemonLZA_MapDetector", std::bind(image_bool_detector_helper, test_pokemonLZA_MapDetector, _1)},
306+
{"PokemonLZA_HyperspaceCalorieDetector", std::bind(image_int_detector_helper, test_pokemonLZA_HyperspaceCalorieDetector, _1)},
306307
};
307308

308309
TestFunction find_test_function(const std::string& test_space, const std::string& test_name){

SerialPrograms/cmake/SourceFiles.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,8 @@ file(GLOB LIBRARY_SOURCES
16171617
Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.h
16181618
Source/PokemonLZA/Inference/PokemonLZA_HyperspaceRewardNameReader.cpp
16191619
Source/PokemonLZA/Inference/PokemonLZA_HyperspaceRewardNameReader.h
1620+
Source/PokemonLZA/Inference/PokemonLZA_HyperspaceCalorieDetector.cpp
1621+
Source/PokemonLZA/Inference/PokemonLZA_HyperspaceCalorieDetector.h
16201622
Source/PokemonLZA/Inference/PokemonLZA_MainMenuDetector.cpp
16211623
Source/PokemonLZA/Inference/PokemonLZA_MainMenuDetector.h
16221624
Source/PokemonLZA/Inference/PokemonLZA_OverworldPartySelectionDetector.cpp

0 commit comments

Comments
 (0)