Fix video condition not supporting variables properly

This commit is contained in:
WarmUpTill
2026-10-11 19:06:10 +02:00
committed by WarmUpTill
parent 1fdf37d0fb
commit e3b2cbd579
4 changed files with 73 additions and 50 deletions

View File

@@ -133,7 +133,7 @@ bool MacroConditionVideo::Save(obs_data_t *obj) const
_video.Save(obj);
obs_data_set_bool(obj, "keepActive", _keepActive);
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
obs_data_set_string(obj, "filePath", _file.c_str());
_file.Save(obj, "filePath");
obs_data_set_bool(obj, "blockUntilScreenshotDone",
_blockUntilScreenshotDone);
_brightnessThreshold.Save(obj, "brightnessThreshold");
@@ -154,7 +154,7 @@ bool MacroConditionVideo::Load(obs_data_t *obj)
_keepActive = obs_data_get_bool(obj, "keepActive");
SetCondition(static_cast<VideoCondition>(
obs_data_get_int(obj, "condition")));
_file = obs_data_get_string(obj, "filePath");
_file.Load(obj, "filePath");
_blockUntilScreenshotDone =
obs_data_get_bool(obj, "blockUntilScreenshotDone");
// TODO: Remove this fallback in a future version
@@ -202,12 +202,13 @@ void MacroConditionVideo::GetScreenshot(bool blocking)
bool MacroConditionVideo::LoadImageFromFile()
{
const QFileInfo info(QString::fromStdString(_file));
const std::string file = _file;
const QFileInfo info(QString::fromStdString(file));
_loadedFileLastModified = info.lastModified();
_loadedFile = _file;
_loadedFile = file;
if (!_matchImage.load(info.absoluteFilePath())) {
blog(LOG_WARNING, "Cannot load image data from file '%s'",
_file.c_str());
file.c_str());
(&_matchImage)->~QImage();
new (&_matchImage) QImage();
_patternImageData = {};
@@ -304,9 +305,10 @@ bool MacroConditionVideo::FileInputIsUpToDate() const
if (!requiresFileInput(_condition)) {
return true;
}
const QFileInfo info(QString::fromStdString(_file));
const std::string file = _file;
const QFileInfo info(QString::fromStdString(file));
return (_loadedFileLastModified == info.lastModified()) &&
(_file == _loadedFile);
(file == _loadedFile);
}
bool MacroConditionVideo::OutputChanged()
@@ -1099,7 +1101,7 @@ void MacroConditionVideoEdit::UpdateEntryData()
_condition->setCurrentIndex(_condition->findData(
static_cast<int>(_entryData->GetCondition())));
_reduceLatency->setChecked(_entryData->_blockUntilScreenshotDone);
_imagePath->SetPath(QString::fromStdString(_entryData->_file));
_imagePath->SetPath(_entryData->_file);
_usePatternForChangedCheck->setChecked(
_entryData->_patternMatchParameters.useForChangedCheck);
_patternThreshold->SetDoubleValue(

View File

@@ -60,7 +60,7 @@ public:
VideoInput _video;
bool _keepActive = false;
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
// Enabling this will reduce matching latency, but slow down the
// the condition checks of all macros overall.
//

View File

@@ -62,13 +62,14 @@ static bool isMinNeighborsValid(int minNeighbors)
bool CascadeClassifierParameters::LoadModelData()
{
const auto path = QString::fromStdString(_modelPath);
_loadedModelPath = _modelPath;
const auto path = QString::fromStdString(_loadedModelPath);
if (!QFileInfo(path).exists(path)) {
_detector.reset();
return false;
}
auto det = std::make_unique<CascadeClassifierDetector>();
if (!det->Load(_modelPath)) {
if (!det->Load(_loadedModelPath)) {
_detector.reset();
return false;
}
@@ -79,7 +80,7 @@ bool CascadeClassifierParameters::LoadModelData()
bool CascadeClassifierParameters::Save(obs_data_t *obj) const
{
auto data = obs_data_create();
obs_data_set_string(data, "modelPath", _modelPath.c_str());
_modelPath.Save(data, "modelPath");
scaleFactor.Save(data, "scaleFactor");
obs_data_set_int(data, "minNeighbors", minNeighbors);
minSize.Save(data, "minSize");
@@ -108,7 +109,7 @@ bool CascadeClassifierParameters::Load(obs_data_t *obj)
return true;
}
auto data = obs_data_get_obj(obj, "objectMatchData");
_modelPath = obs_data_get_string(data, "modelPath");
_modelPath.Load(data, "modelPath");
scaleFactor.Load(data, "scaleFactor");
// TODO: Remove this fallback in a future version
if (!obs_data_has_user_value(data, "version")) {
@@ -121,11 +122,12 @@ bool CascadeClassifierParameters::Load(obs_data_t *obj)
// which invalidates previously saved default model paths.
const std::string oldPrefix =
"../../data/obs-plugins/advanced-scene-switcher/res/cascadeClassifiers/";
if (_modelPath.substr(0, oldPrefix.size()) == oldPrefix) {
const std::string oldPath = _modelPath.UnresolvedValue();
if (oldPath.substr(0, oldPrefix.size()) == oldPrefix) {
_modelPath = std::string(obs_get_module_data_path(
obs_current_module())) +
"/res/cascadeClassifiers/" +
_modelPath.substr(oldPrefix.size());
oldPath.substr(oldPrefix.size());
}
#endif
}
@@ -150,7 +152,8 @@ bool CascadeClassifierParameters::SetModelPath(const std::string &path)
ObjectDetector *CascadeClassifierParameters::GetDetector()
{
if (!_detector || !_detector->IsLoaded()) {
if (!_detector || !_detector->IsLoaded() ||
std::string(_modelPath) != _loadedModelPath) {
if (!LoadModelData()) {
return nullptr;
}
@@ -316,7 +319,7 @@ bool OCRParameters::Save(obs_data_t *obj) const
tesseractBasePath.Save(data, "tesseractBasePath");
languageCode.Save(data, "language");
obs_data_set_bool(data, "useConfig", useConfig);
obs_data_set_string(data, "configFile", configFile.c_str());
configFile.Save(data, "configFile");
color.Save(data, "textColor");
colorThreshold.Save(data, "colorThreshold");
obs_data_set_int(data, "pageSegMode", static_cast<int>(pageSegMode));
@@ -358,7 +361,7 @@ bool OCRParameters::Load(obs_data_t *obj)
#endif
}
useConfig = obs_data_get_bool(data, "useConfig");
configFile = obs_data_get_string(data, "configFile");
configFile.Load(data, "configFile");
color.Load(data, "textColor");
if (obs_data_has_user_value(data, "version")) {
@@ -382,18 +385,31 @@ void OCRParameters::SetPageMode(tesseract::PageSegMode mode)
tesseract::TessBaseAPI *OCRParameters::GetOCR()
{
if (!initDone) {
if (!initDone || !SetupIsUpToDate()) {
Setup();
}
return initDone ? ocr.get() : nullptr;
}
static bool containsVariables(const std::string &value)
{
return std::string(StringVariable(value)) != value;
}
static bool modelFileExists(const std::string &basePath,
const std::string &languageCode)
{
const auto dataPath = QString::fromStdString(basePath) + "/" +
QString::fromStdString(languageCode) +
".traineddata";
return QFileInfo::exists(dataPath);
}
bool OCRParameters::SetLanguageCode(const std::string &value)
{
const auto dataPath = QString::fromStdString(tesseractBasePath) + "/" +
QString::fromStdString(value) + ".traineddata";
QFileInfo fileInfo(dataPath);
if (!fileInfo.exists(dataPath)) {
// Variable values can change later, so only fixed values are validated
if (!containsVariables(value) &&
!modelFileExists(tesseractBasePath, value)) {
return false;
}
languageCode = value;
@@ -401,18 +417,10 @@ bool OCRParameters::SetLanguageCode(const std::string &value)
return true;
}
std::string OCRParameters::GetLanguageCode() const
{
return languageCode;
}
bool OCRParameters::SetTesseractBasePath(const std::string &value)
{
const auto dataPath = QString::fromStdString(value) + "/" +
QString::fromStdString(languageCode) +
".traineddata";
QFileInfo fileInfo(dataPath);
if (!fileInfo.exists(dataPath)) {
if (!containsVariables(value) &&
!modelFileExists(value, languageCode)) {
return false;
}
tesseractBasePath = value;
@@ -420,11 +428,6 @@ bool OCRParameters::SetTesseractBasePath(const std::string &value)
return true;
}
std::string OCRParameters::GetTesseractBasePath() const
{
return tesseractBasePath;
}
void OCRParameters::EnableCustomConfig(bool enable)
{
useConfig = enable;
@@ -437,17 +440,27 @@ void OCRParameters::SetCustomConfigFile(const std::string &filename)
initDone = false;
}
bool OCRParameters::SetupIsUpToDate() const
{
return setupBasePath == std::string(tesseractBasePath) &&
setupLanguageCode == std::string(languageCode) &&
setupConfigFile == std::string(configFile);
}
void OCRParameters::Setup()
{
setupBasePath = tesseractBasePath;
setupLanguageCode = languageCode;
setupConfigFile = configFile;
ocr = std::make_unique<tesseract::TessBaseAPI>();
if (!ocr) {
initDone = false;
return;
}
const std::string dataPath = std::string(tesseractBasePath) + "/";
const std::string modelFile =
std::string(languageCode) + ".traineddata";
const std::string dataPath = setupBasePath + "/";
const std::string modelFile = setupLanguageCode + ".traineddata";
const auto modelFullPath = QString::fromStdString(dataPath) +
QString::fromStdString(modelFile);
QFileInfo modelFileInfo(modelFullPath);
@@ -459,7 +472,7 @@ void OCRParameters::Setup()
return;
}
auto configPath = QString::fromStdString(configFile);
auto configPath = QString::fromStdString(setupConfigFile);
QFileInfo configFileInfo(configPath);
bool configFileExists = configFileInfo.exists(configPath);
@@ -471,8 +484,8 @@ void OCRParameters::Setup()
setupWithConfig = false;
}
char *configs[] = {configFile.data()};
if (ocr->Init(dataPath.c_str(), languageCode.c_str(),
char *configs[] = {setupConfigFile.data()};
if (ocr->Init(dataPath.c_str(), setupLanguageCode.c_str(),
tesseract::OEM_DEFAULT,
setupWithConfig ? configs : nullptr,
setupWithConfig ? 1 : 0, nullptr, nullptr, false) != 0) {

View File

@@ -94,7 +94,7 @@ public:
}
bool SetModelPath(const std::string &path);
const std::string &GetModelPath() const { return _modelPath; }
const StringVariable &GetModelPath() const { return _modelPath; }
ObjectDetector *GetDetector();
NumberVariable<double> scaleFactor = defaultScaleFactor;
@@ -106,10 +106,11 @@ private:
bool LoadModelData();
std::unique_ptr<ObjectDetector> _detector;
std::string _modelPath =
StringVariable _modelPath =
obs_get_module_data_path(obs_current_module()) +
std::string(
"/res/cascadeClassifiers/haarcascade_frontalface_alt.xml");
std::string _loadedModelPath;
};
class OCRParameters {
@@ -125,13 +126,16 @@ public:
bool Initialized() const { return initDone; }
void SetPageMode(tesseract::PageSegMode);
bool SetLanguageCode(const std::string &);
std::string GetLanguageCode() const;
const StringVariable &GetLanguageCode() const { return languageCode; }
bool SetTesseractBasePath(const std::string &);
std::string GetTesseractBasePath() const;
const StringVariable &GetTesseractBasePath() const
{
return tesseractBasePath;
}
void EnableCustomConfig(bool enable);
bool CustomConfigIsEnabled() const { return useConfig; }
void SetCustomConfigFile(const std::string &);
std::string GetCustomConfigFile() const { return configFile; }
const StringVariable &GetCustomConfigFile() const { return configFile; }
tesseract::PageSegMode GetPageMode() const { return pageSegMode; }
tesseract::TessBaseAPI *GetOCR();
@@ -142,6 +146,7 @@ public:
private:
void Setup();
bool SetupIsUpToDate() const;
tesseract::PageSegMode pageSegMode = tesseract::PSM_SINGLE_BLOCK;
StringVariable tesseractBasePath =
@@ -149,9 +154,12 @@ private:
std::string("/res/ocr");
StringVariable languageCode = "eng";
bool useConfig = false;
std::string configFile = "config.txt";
StringVariable configFile = "config.txt";
std::unique_ptr<tesseract::TessBaseAPI> ocr;
bool initDone = false;
std::string setupBasePath;
std::string setupLanguageCode;
std::string setupConfigFile;
};
class ColorParameters {