|
14 | 14 | #include "CommonFramework/ProgramStats/StatsTracking.h" |
15 | 15 | #include "CommonFramework/VideoPipeline/VideoFeed.h" |
16 | 16 | #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" |
| 17 | +#include "CommonTools/ImageMatch/ImageCropper.h" |
17 | 18 | #include "CommonTools/Images/BinaryImage_FilterRgb32.h" |
18 | 19 | #include "CommonTools/OCR/OCR_NumberReader.h" |
19 | 20 | #include "CommonTools/Async/InferenceRoutines.h" |
|
31 | 32 | #include "PokemonSwSh/Commands/PokemonSwSh_Commands_DateSpam.h" |
32 | 33 | #include "PokemonSV_AuctionFarmer.h" |
33 | 34 |
|
| 35 | +#include "Common/Cpp/PrettyPrint.h" |
| 36 | + |
34 | 37 |
|
35 | 38 | namespace PokemonAutomation{ |
36 | 39 | namespace NintendoSwitch{ |
@@ -366,17 +369,78 @@ void AuctionFarmer::reset_position(SingleSwitchProgramEnvironment& env, ProContr |
366 | 369 | } |
367 | 370 |
|
368 | 371 |
|
369 | | -uint64_t read_next_bid(VideoStream& stream, ProControllerContext& context, bool high){ |
| 372 | +uint64_t read_next_bid(VideoStream& stream, ProControllerContext& context, Language language, bool high){ |
| 373 | + // How much to cut off from the bid text in order to not read currencies and exclamation marks as numbers. |
| 374 | + // Values are pixels for a 1920x1080 screen, negative values are padding |
| 375 | + static const std::map<Language, std::pair<int8_t, int8_t>> cutoffs = { |
| 376 | + { Language::English, {22, 7} }, |
| 377 | + { Language::Japanese, {-5, 54} }, |
| 378 | + { Language::Spanish, {6, 32} }, |
| 379 | + { Language::French, {-5, 45} }, |
| 380 | + { Language::German, {-5, 22} }, |
| 381 | + { Language::Italian, {-5, 35} }, |
| 382 | + { Language::Korean, {-5, 42} }, |
| 383 | + { Language::ChineseSimplified, {22, 7} }, |
| 384 | + { Language::ChineseTraditional, {22,7} } |
| 385 | + }; |
| 386 | + |
| 387 | + static const std::map<Language, float> high_x = { |
| 388 | + { Language::English, 0.75f }, |
| 389 | + { Language::Japanese, 0.75f }, |
| 390 | + { Language::Spanish, 0.73f }, |
| 391 | + { Language::French, 0.68f }, |
| 392 | + { Language::German, 0.73f }, |
| 393 | + { Language::Italian, 0.75f }, |
| 394 | + { Language::Korean, 0.75f }, |
| 395 | + { Language::ChineseSimplified, 0.75f }, |
| 396 | + { Language::ChineseTraditional, 0.75f } |
| 397 | + }; |
| 398 | + |
| 399 | + static const std::map<Language, float> low_x = { |
| 400 | + { Language::English, 0.75f }, |
| 401 | + { Language::Japanese, 0.75f }, |
| 402 | + { Language::Spanish, 0.75f }, |
| 403 | + { Language::French, 0.75f }, |
| 404 | + { Language::German, 0.73f }, |
| 405 | + { Language::Italian, 0.75f }, |
| 406 | + { Language::Korean, 0.75f }, |
| 407 | + { Language::ChineseSimplified, 0.75f }, |
| 408 | + { Language::ChineseTraditional, 0.75f } |
| 409 | + }; |
| 410 | + |
| 411 | + |
370 | 412 | float box_y = high ? 0.42f : 0.493f; |
371 | | - OverlayBoxScope box(stream.overlay(), { 0.73, box_y, 0.17, 0.048 }); |
| 413 | + float box_x = high ? high_x.at(language) : low_x.at(language); |
| 414 | + float width = 0.9f - box_x; // max_x is always the same for all languages |
| 415 | + OverlayBoxScope box(stream.overlay(), { box_x, box_y, width, 0.048 }); |
| 416 | + |
372 | 417 | std::unordered_map<uint64_t, size_t> read_bids; |
373 | 418 | size_t highest_read = 0; |
374 | 419 | uint64_t read_value = 0; |
375 | 420 |
|
376 | 421 | // read next bid multiple times since the selection arrow sometimes blocks the first digit |
377 | 422 | for (size_t i = 0; i < 10; i++){ |
378 | 423 | VideoSnapshot screen = stream.video().snapshot(); |
379 | | - uint64_t read_bid = OCR::read_number(stream.logger(), extract_box_reference(screen, box)); |
| 424 | + double screen_scale = (double)screen->width() / 1920.0; |
| 425 | + double vertical_padding = 5.0; // small amount of pixels so numbers do not touch the edge of the view when reading them |
| 426 | + float left_cutoff = cutoffs.at(language).first; |
| 427 | + float right_cutoff = cutoffs.at(language).second; |
| 428 | + |
| 429 | + ImageViewRGB32 raw_bid_image = extract_box_reference(screen, box); |
| 430 | + ImagePixelBox bid_bounding_box = ImageMatch::enclosing_rectangle_with_pixel_filter( |
| 431 | + raw_bid_image, |
| 432 | + [](Color pixel) { |
| 433 | + return (uint32_t)pixel.red() + pixel.green() + pixel.blue() < 250; |
| 434 | + }); |
| 435 | + |
| 436 | + ImagePixelBox cut_bid_bounding_box( |
| 437 | + bid_bounding_box.min_x + (size_t)(left_cutoff * screen_scale), |
| 438 | + bid_bounding_box.min_y - (size_t)(vertical_padding * screen_scale), |
| 439 | + bid_bounding_box.max_x - (size_t)(right_cutoff * screen_scale), |
| 440 | + bid_bounding_box.max_y + (size_t)(vertical_padding * screen_scale) |
| 441 | + ); |
| 442 | + |
| 443 | + uint64_t read_bid = OCR::read_number(stream.logger(), extract_box_reference(raw_bid_image, cut_bid_bounding_box)); |
380 | 444 |
|
381 | 445 | if (read_bids.find(read_bid) == read_bids.end()){ |
382 | 446 | read_bids[read_bid] = 0; |
@@ -418,11 +482,11 @@ void AuctionFarmer::bid_on_item(SingleSwitchProgramEnvironment& env, ProControll |
418 | 482 | pbf_press_button(context, BUTTON_A, 20, TICKS_PER_SECOND); |
419 | 483 | break; |
420 | 484 | case 1: |
421 | | - current_bid = read_next_bid(env.console, context, true); |
| 485 | + current_bid = read_next_bid(env.console, context, LANGUAGE, true); |
422 | 486 | pbf_press_button(context, BUTTON_A, 20, TICKS_PER_SECOND); |
423 | 487 | break; |
424 | 488 | case 2: |
425 | | - current_bid = read_next_bid(env.console, context, false); |
| 489 | + current_bid = read_next_bid(env.console, context, LANGUAGE, false); |
426 | 490 | pbf_press_button(context, BUTTON_A, 20, TICKS_PER_SECOND); |
427 | 491 | break; |
428 | 492 | case 3: |
|
0 commit comments