Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Common/Cpp/Exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ MLModelSessionCreationError::MLModelSessionCreationError(Logger* logger, std::st
std::string MLModelSessionCreationError::message() const{
return std::format(
"Failed to create a model session from {}. "
"Probably failure loading the model or not enough GPU memory",
"Probably failure loading the model or not enough GPU memory. Also, ensure that the corresponding ONNX model has been downloaded.",
m_model_path
);
}
Expand Down
24 changes: 16 additions & 8 deletions SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,18 @@ GlobalSettings::GlobalSettings()
#endif
)
, THEME(CONSTRUCT_TOKEN)
, USE_PADDLE_OCR(
"<b>Enable PaddleOCR:</b><br>"
"Use PaddleOCR instead of Tesseract for OCR.",
LockMode::UNLOCK_WHILE_RUNNING,
false
, OCR_LIBRARY(
"<b>OCR library:",
{
{OcrLibrary::PADDLE_OCR, "paddle-ocr", "Paddle OCR"},
{OcrLibrary::TESSERACT, "tesseract", "Tesseract"},
},
LockMode::LOCK_WHILE_RUNNING,
OcrLibrary::TESSERACT
)
, OCR_WARNING(
"WARNING: If you change the OCR library away from the default (PaddleOCR), you must ensure that you have the necessary resource downloaded. "
"Otherwise, the programs that use OCR will throw an error."
)
, USE_GPU_FOR_ML_INFERENCE(
"<b>Use GPU for Machine learning inference:</b><br>"
Expand Down Expand Up @@ -275,7 +282,8 @@ GlobalSettings::GlobalSettings()
PA_ADD_OPTION(USE_GPU_FOR_ML_INFERENCE);

// gated behind Dev mode. see GlobalSettings::load_json
PA_ADD_OPTION(USE_PADDLE_OCR);
PA_ADD_OPTION(OCR_LIBRARY);
// PA_ADD_OPTION(OCR_WARNING); // TODO: enable this when Tesseract is no longer a default resource.
PA_ADD_OPTION(RESOURCE_DOWNLOAD_TABLE);
PA_ADD_OPTION(DOWNLOAD_ERROR);

Expand Down Expand Up @@ -324,7 +332,7 @@ GlobalSettings::GlobalSettings()

PA_ADD_OPTION(DEVELOPER_TOKEN);

USE_PADDLE_OCR.set_visibility(ConfigOptionState::HIDDEN);
OCR_LIBRARY.set_visibility(ConfigOptionState::HIDDEN);
RESOURCE_DOWNLOAD_TABLE.set_visibility(ConfigOptionState::HIDDEN);
DOWNLOAD_ERROR.set_visibility(ConfigOptionState::HIDDEN);
SAVE_DEBUG_VIDEOS_ON_SWITCH.set_visibility(ConfigOptionState::HIDDEN);
Expand All @@ -348,7 +356,7 @@ void GlobalSettings::load_json(const JsonValue& json){
ConfigOptionState devmode_visibility = developer_mode
? ConfigOptionState::ENABLED
: ConfigOptionState::HIDDEN;
USE_PADDLE_OCR.set_visibility(devmode_visibility);
OCR_LIBRARY.set_visibility(devmode_visibility);
RESOURCE_DOWNLOAD_TABLE.set_visibility(devmode_visibility);
DOWNLOAD_ERROR.set_visibility(devmode_visibility);
SAVE_DEBUG_VIDEOS_ON_SWITCH.set_visibility(devmode_visibility);
Expand Down
8 changes: 7 additions & 1 deletion SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <vector>
#include "Common/Cpp/Containers/Pimpl.h"
#include "Common/Cpp/Options/EnumDropdownOption.h"
#include "Common/Cpp/Options/ConfigOption.h"
#include "Common/Cpp/Options/StaticTextOption.h"
#include "Common/Cpp/Options/BooleanCheckBoxOption.h"
Expand Down Expand Up @@ -42,6 +43,10 @@ class ErrorReportOption;
class ResourceDownload;


enum class OcrLibrary{
PADDLE_OCR,
TESSERACT,
};

class FolderInputOption : public StringOption{
public:
Expand Down Expand Up @@ -127,7 +132,8 @@ class GlobalSettings : public BatchOption, private ConfigOption::Listener, priva
FolderInputOption TEMP_FOLDER;

Pimpl<ThemeSelectorOption> THEME;
BooleanCheckBoxOption USE_PADDLE_OCR;
EnumDropdownOption<OcrLibrary> OCR_LIBRARY;
StaticTextOption OCR_WARNING;
BooleanCheckBoxOption USE_GPU_FOR_ML_INFERENCE;
SettingsResourceDownloadTable RESOURCE_DOWNLOAD_TABLE;
SettingsDownloadError DOWNLOAD_ERROR;
Expand Down
4 changes: 2 additions & 2 deletions SerialPrograms/Source/CommonTools/OCR/OCR_DictionaryMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class DictionaryMatcher{
Language language,
const ImageViewRGB32& image,
double max_log10p, double log10p_spread = 0.5,
OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_BLOCK
OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_LINE
) const;

// Match a substring from `image` using multiple black-white filters.
Expand Down Expand Up @@ -77,7 +77,7 @@ class DictionaryMatcher{
const std::vector<OCR::TextColorRange>& text_color_ranges,
double max_log10p, double log10p_spread = 0.5,
double min_text_ratio = 0.01, double max_text_ratio = 0.50,
OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_BLOCK
OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_LINE
) const;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class TesseractPool{
new TesseractAPI(m_training_data_path.c_str(), m_language_code.c_str())
);
if (!api->valid()){
throw InternalSystemError(nullptr, PA_CURRENT_FUNCTION, "Could not initialize TesseractAPI.");
throw InternalSystemError(nullptr, PA_CURRENT_FUNCTION, "Could not initialize TesseractAPI. Ensure that Tesseract has been downloaded.");
}

// Add to pool under lock.
Expand Down
4 changes: 2 additions & 2 deletions SerialPrograms/Source/CommonTools/OCR/OCR_RawTesseractOCR.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ bool tesseract_language_available(Language language);
// call `ensure_tesseract_instances()` to pre-warm to pool with a given number of instances.
//
// psm: Page segmentation mode - controls how Tesseract interprets the image layout.
// Defaults to SINGLE_BLOCK (Tesseract C++ API's default) for best performance.
// Defaults to SINGLE_LINE
std::string tesseract_ocr_read(
Language language,
const ImageViewRGB32& image,
PageSegMode psm = PageSegMode::SINGLE_BLOCK
PageSegMode psm = PageSegMode::SINGLE_LINE
);


Expand Down
26 changes: 11 additions & 15 deletions SerialPrograms/Source/CommonTools/OCR/OCR_Routines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,9 @@ using std::endl;
namespace PokemonAutomation{
namespace OCR{

// return true if the user enabled PaddleOCR and its resource has been downloaded
// NOTE: we are making the assumption that if English is downloaded,
// that all the other languages are downloaded too, since they're all downloaded
// as a bundle.
bool use_paddle_ocr(){
static bool use_paddle_ocr = GlobalSettings::instance().USE_PADDLE_OCR && paddle_ocr_language_available(Language::English);

return use_paddle_ocr;
}

bool ocr_language_available(Language language){
if (use_paddle_ocr()){
if (GlobalSettings::instance().OCR_LIBRARY == OcrLibrary::PADDLE_OCR){
return OCR::paddle_ocr_language_available(language);
}else{
return OCR::tesseract_language_available(language);
Expand All @@ -44,24 +35,29 @@ bool ocr_language_available(Language language){

std::string ocr_read(Language language, const ImageViewRGB32& image, PageSegMode psm){
std::string ocr_text = "";
if (use_paddle_ocr()){
ocr_text = OCR::paddle_ocr_read(language, image);
}else{
if (psm == PageSegMode::AUTO || psm == PageSegMode::SINGLE_BLOCK || psm == PageSegMode::SINGLE_COLUMN){
// if using multiline detection, force Tesseract
ocr_text = OCR::tesseract_ocr_read(language, image, psm);
}else{
if (GlobalSettings::instance().OCR_LIBRARY == OcrLibrary::PADDLE_OCR){
ocr_text = OCR::paddle_ocr_read(language, image);
}else{
ocr_text = OCR::tesseract_ocr_read(language, image, psm);
}
}
return ocr_text;
}

void ensure_ocr_instances(Language language, size_t instances){
if (use_paddle_ocr()){
if (GlobalSettings::instance().OCR_LIBRARY == OcrLibrary::PADDLE_OCR){
OCR::ensure_paddle_ocr_instance(language);
}else{
OCR::ensure_tesseract_instances(language, instances);
}
}

void clear_ocr_cache(){
if (use_paddle_ocr()){
if (GlobalSettings::instance().OCR_LIBRARY == OcrLibrary::PADDLE_OCR){
OCR::clear_paddle_ocr_cache();
}else{
OCR::clear_tesseract_cache();
Expand Down
9 changes: 6 additions & 3 deletions SerialPrograms/Source/CommonTools/OCR/OCR_Routines.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ struct TextColorRange{

bool ocr_language_available(Language language);

std::string ocr_read(Language language, const ImageViewRGB32& image, PageSegMode psm = PageSegMode::SINGLE_BLOCK);
// will use the OCR library as per the dropdown in GlobalSettings
// if the preferred library's resource is missing (i.e. it has not been downloaded),
// an error will be thrown within OCR initialization infra.
std::string ocr_read(Language language, const ImageViewRGB32& image, PageSegMode psm = PageSegMode::SINGLE_LINE);

void ensure_ocr_instances(Language language, size_t instances = 1);

Expand All @@ -45,12 +48,12 @@ StringMatchResult multifiltered_OCR(
const std::vector<TextColorRange>& text_color_ranges,
double log10p_spread,
double min_text_ratio = 0.01, double max_text_ratio = 0.50,
OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_BLOCK
OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_LINE
);

StringMatchResult dictionary_OCR(
Language language, const DictionaryMatcher& dictionary, const ImageViewRGB32& image,
double log10p_spread, OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_BLOCK
double log10p_spread, OCR::PageSegMode psm = OCR::PageSegMode::SINGLE_LINE
);


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ StatReads BattleLevelUpReader::read_stats(Logger &logger, const ImageViewRGB32&
auto read_stat = [&](const ImageFloatBox &box, const std::string &name){
ImageViewRGB32 stat_region = extract_box_reference(game_screen, box);

if (!GlobalSettings::instance().USE_PADDLE_OCR){
if (GlobalSettings::instance().OCR_LIBRARY != OcrLibrary::PADDLE_OCR){
// Tesseract-free path: waterfill segmentation + template matching
// against the PokemonFRLG/Digits/0-9.png templates.
return read_digits_waterfill_template(logger, stat_region);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* then template-matches each cropped digit against the pre-stored digit
* templates (Resources/PokemonFRLG/Digits/0-9.png) on the unblurred original.
*
* This is the Tesseract/PaddleOCR-free fallback path for USE_PADDLE_OCR=false.
* This is the Tesseract (PaddleOCR-free) fallback path.
*/

#ifndef PokemonAutomation_PokemonFRLG_DigitReader_H
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ StatReads PartyLevelUpReader::read_stats(Logger &logger, const ImageViewRGB32& f
auto read_stat = [&](const ImageFloatBox &box, const std::string &name){
ImageViewRGB32 stat_region = extract_box_reference(game_screen, box);

if (!GlobalSettings::instance().USE_PADDLE_OCR){
if (GlobalSettings::instance().OCR_LIBRARY != OcrLibrary::PADDLE_OCR){
// Tesseract-free path: waterfill segmentation + template matching
// against the PokemonFRLG/Digits/0-9.png templates.
return read_digits_waterfill_template(logger, stat_region);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ void StatsReader::read_level(

ImageViewRGB32 level_box = extract_box_reference(game_screen, jpn ? m_box_level_jpn : m_box_level);

if (!GlobalSettings::instance().USE_PADDLE_OCR){
if (GlobalSettings::instance().OCR_LIBRARY != OcrLibrary::PADDLE_OCR){
// The level uses white text with dark shadow on a lilac background.
// The digit reader's binarizer captures dark pixels (<=190 on all channels)
// but NOT the white text (all channels 255 -> excluded). This leaves the
Expand Down Expand Up @@ -335,7 +335,7 @@ void StatsReader::read_page2(
auto read_stat = [&](const ImageFloatBox& box, const std::string& name){
ImageViewRGB32 stat_region = extract_box_reference(game_screen, box);

if (!GlobalSettings::instance().USE_PADDLE_OCR){
if (GlobalSettings::instance().OCR_LIBRARY != OcrLibrary::PADDLE_OCR){
// Tesseract-free path: waterfill segmentation + template matching
// against the PokemonFRLG/Digits/0-9.png templates.
return read_digits_waterfill_template(logger, stat_region);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ uint16_t TrainerIdReader::read_tid(

ImageViewRGB32 tid_region = extract_box_reference(game_screen, language == Language::Japanese ? m_box_tid_jpn : m_box_tid);

if (!GlobalSettings::instance().USE_PADDLE_OCR){
if (GlobalSettings::instance().OCR_LIBRARY != OcrLibrary::PADDLE_OCR){
// Tesseract-free path: waterfill segmentation + template matching
// against the PokemonFRLG/Digits/0-9.png templates.
return uint16_t(read_digits_waterfill_template(logger, tid_region));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ OCR::StringMatchResult BlueberryQuestReader::read_substring(
) const{
return match_substring_from_image_multifiltered(
&logger, language, image, text_color_ranges,
MAX_LOG10P, MAX_LOG10P_SPREAD, min_text_ratio, max_text_ratio
MAX_LOG10P, MAX_LOG10P_SPREAD, min_text_ratio, max_text_ratio,
OCR::PageSegMode::SINGLE_BLOCK
);
}

Expand Down
Loading