Skip to content

Commit 6d63eaa

Browse files
committed
Improve star detection for SV tera cards.
1 parent 807f87a commit 6d63eaa

File tree

3 files changed

+83
-12
lines changed

3 files changed

+83
-12
lines changed

SerialPrograms/Source/Kernels/Waterfill/Kernels_Waterfill_Types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <stdint.h>
1212
//#include <map>
1313
//#include <iostream>
14+
#include "Common/Cpp/Rectangle.h"
1415
#include "Kernels/BinaryMatrix/Kernels_BinaryMatrix.h"
1516

1617
namespace PokemonAutomation{
@@ -56,6 +57,10 @@ class WaterfillObject{
5657
double aspect_ratio() const{ return (double)width() / height(); }
5758
double area_ratio() const{ return (double)area / (width() * height()); }
5859

60+
Rectangle<size_t> rectangle() const{
61+
return Rectangle<size_t>(min_x, min_y, max_x, max_y);
62+
}
63+
5964
// Note: `object` must be constructed before calling this function.
6065
std::unique_ptr<PackedBinaryMatrix_IB> packed_matrix() const{
6166
return object->submatrix(min_x, min_y, max_x - min_x, max_y - min_y);

SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
269269
using namespace Pokemon;
270270
// using namespace PokemonSwSh;
271271
// using namespace PokemonBDSP;
272-
using namespace PokemonLA;
273-
// using namespace PokemonSV;
272+
// using namespace PokemonLA;
273+
using namespace PokemonSV;
274274

275275
[[maybe_unused]] Logger& logger = env.logger();
276276
[[maybe_unused]] ConsoleHandle& console = env.consoles[0];
@@ -281,14 +281,24 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
281281
VideoOverlaySet overlays(overlay);
282282

283283

284+
// ImageRGB32 image("screenshot-20250113-214042699528.png");
285+
ImageRGB32 image("raidecho1.jpg");
286+
// auto image = feed.snapshot();
287+
288+
TeraCardReader reader;
289+
cout << (int)reader.stars(logger, env.program_info(), image) << endl;
290+
291+
292+
293+
#if 0
284294
ImageRGB32 image("20250112-194339635973.png");
285295

286296
PokemonBDSP::SelectionArrowFinder detector0(console, {0.50, 0.58, 0.40, 0.10}, COLOR_RED);
287297
PokemonBDSP::SelectionArrowFinder detector1(console, {0.50, 0.52, 0.40, 0.10}, COLOR_RED);
288298

289299
cout << detector0.detect(image) << endl;
290300
cout << detector1.detect(image) << endl;
291-
301+
#endif
292302

293303

294304

SerialPrograms/Source/PokemonSV/Inference/Tera/PokemonSV_TeraCardDetector.cpp

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <cmath>
88
#include <array>
9+
#include <list>
910
#include <map>
1011
#include "Common/Cpp/PrettyPrint.h"
1112
//#include "Kernels/Waterfill/Kernels_Waterfill.h"
@@ -127,25 +128,80 @@ uint8_t TeraCardReader::stars(
127128

128129
ImageViewRGB32 cropped = extract_box_reference(screen, m_stars);
129130

130-
{
131-
ImageStats background = image_stats(extract_box_reference(screen, ImageFloatBox{0.55, 0.62, 0.20, 0.03}));
132-
Color background_average = background.average.round();
131+
ImageViewRGB32 background = extract_box_reference(screen, ImageFloatBox{0.55, 0.62, 0.20, 0.03});
132+
// background.save("background.png");
133+
ImageStats background_stats = image_stats(background);
134+
Color background_average = background_stats.average.round();
135+
136+
// Iterate through several difference distance filters and find how many
137+
// possible stars are in each one. Then do a majority vote.
138+
const std::vector<double> DISTANCES{70, 80, 90, 100, 110, 120, 130};
139+
140+
std::map<size_t, size_t> count_map;
133141

134-
PackedBinaryMatrix matrix = compress_rgb32_to_binary_euclidean(cropped, (uint32_t)background_average, 100);
142+
for (double distance : DISTANCES){
143+
PackedBinaryMatrix matrix = compress_rgb32_to_binary_euclidean(cropped, (uint32_t)background_average, distance);
135144

136145
matrix.invert();
137146
// cout << matrix.dump() << endl;
138147
std::unique_ptr<WaterfillSession> session = make_WaterfillSession(matrix);
139148
auto iter = session->make_iterator(100);
140149
WaterfillObject object;
141-
size_t count = 0;
150+
151+
std::list<ImagePixelBox> objects;
142152
while (iter->find_next(object, false)){
143-
// extract_box_reference(cropped, object).save("test-" + std::to_string(count) + ".png");
144-
count++;
153+
// Attempt to merge with existing objects.
154+
ImagePixelBox current(object);
155+
bool changed;
156+
do{
157+
changed = false;
158+
for (auto iter1 = objects.begin(); iter1 != objects.end();){
159+
if (current.overlaps_with(*iter1)){
160+
changed = true;
161+
current.merge_with(*iter1);
162+
objects.erase(iter1);
163+
break;
164+
}else{
165+
++iter1;
166+
}
167+
}
168+
}while (changed);
169+
objects.emplace_back(std::move(current));
145170
}
146-
if (1 <= count && count <= 7){
147-
return (uint8_t)count;
171+
172+
#if 0
173+
static size_t count = 0;
174+
for (const ImagePixelBox& obj : objects){
175+
extract_box_reference(cropped, obj).save("test-" + std::to_string(count++) + ".png");
148176
}
177+
cout << "objects.size() = " << objects.size() << endl;
178+
#endif
179+
180+
181+
count_map[objects.size()]++;
182+
}
183+
184+
count_map.erase(0);
185+
186+
if (count_map.empty()){
187+
dump_image(logger, info, "ReadStarsFailed", screen);
188+
return 0;
189+
}
190+
191+
auto best = count_map.begin();
192+
for (auto iter = count_map.begin(); iter != count_map.end(); ++iter){
193+
if (iter->first == 0){
194+
continue;
195+
}
196+
if (iter->second > best->second){
197+
best = iter;
198+
}
199+
}
200+
201+
size_t stars = best->first;
202+
203+
if (1 <= stars && stars <= 7){
204+
return (uint8_t)stars;
149205
}
150206

151207
dump_image(logger, info, "ReadStarsFailed", screen);

0 commit comments

Comments
 (0)