Expose "Similarity Rating" as temp var when pattern matching

This commit is contained in:
WarmUpTill 2026-02-21 21:37:27 +01:00 committed by WarmUpTill
parent f35ef558ee
commit d6ea815b85
6 changed files with 58 additions and 39 deletions

View File

@ -2196,6 +2196,8 @@ AdvSceneSwitcher.tempVar.recording.durationSeconds.description="Recording durati
AdvSceneSwitcher.tempVar.recording.lastSavePath="Last save path"
AdvSceneSwitcher.tempVar.recording.lastSavePath.description="The file path of the last saved recording."
AdvSceneSwitcher.tempVar.video.similarity="Similarity Rating"
AdvSceneSwitcher.tempVar.video.similarity.description="Values range from 0 to 1, where 0 means dissimilar and 1 means highly similar."
AdvSceneSwitcher.tempVar.video.patternCount="Pattern count"
AdvSceneSwitcher.tempVar.video.patternCount.description="The number of times the given pattern has been found in a given video input frame."
AdvSceneSwitcher.tempVar.video.objectCount="Object count"

View File

@ -273,15 +273,18 @@ void MacroConditionVideo::SetCondition(VideoCondition condition)
bool MacroConditionVideo::ScreenshotContainsPattern()
{
cv::Mat result;
MatchPattern(_screenshotData.GetImage(), _patternImageData,
_patternMatchParameters.threshold, result, nullptr,
_patternMatchParameters.useAlphaAsMask,
_patternMatchParameters.matchMode);
double bestMatchValue =
MatchPattern(_screenshotData.GetImage(), _patternImageData,
_patternMatchParameters.threshold, result,
_patternMatchParameters.useAlphaAsMask,
_patternMatchParameters.matchMode);
if (result.total() == 0) {
SetTempVarValue("similarity", std::to_string(bestMatchValue));
SetTempVarValue("patternCount", "0");
return false;
}
const auto count = countNonZero(result);
SetTempVarValue("similarity", std::to_string(bestMatchValue));
SetTempVarValue("patternCount", std::to_string(count));
return count > 0;
}
@ -304,10 +307,12 @@ bool MacroConditionVideo::OutputChanged()
cv::Mat result;
_patternImageData = CreatePatternData(_matchImage);
MatchPattern(_screenshotData.GetImage(), _patternImageData,
_patternMatchParameters.threshold, result, nullptr,
_patternMatchParameters.useAlphaAsMask,
_patternMatchParameters.matchMode);
double bestMatchValue =
MatchPattern(_screenshotData.GetImage(), _patternImageData,
_patternMatchParameters.threshold, result,
_patternMatchParameters.useAlphaAsMask,
_patternMatchParameters.matchMode);
SetTempVarValue("similarity", std::to_string(bestMatchValue));
if (result.total() == 0) {
return false;
}
@ -411,7 +416,25 @@ void MacroConditionVideo::SetupTempVars()
{
MacroCondition::SetupTempVars();
switch (_condition) {
case VideoCondition::HAS_CHANGED:
case VideoCondition::HAS_NOT_CHANGED:
if (!_patternMatchParameters.useForChangedCheck) {
break;
}
AddTempvar(
"similarity",
obs_module_text(
"AdvSceneSwitcher.tempVar.video.similarity"),
obs_module_text(
"AdvSceneSwitcher.tempVar.video.similarity.description"));
break;
case VideoCondition::PATTERN:
AddTempvar(
"similarity",
obs_module_text(
"AdvSceneSwitcher.tempVar.video.similarity"),
obs_module_text(
"AdvSceneSwitcher.tempVar.video.similarity.description"));
AddTempvar(
"patternCount",
obs_module_text(
@ -451,8 +474,6 @@ void MacroConditionVideo::SetupTempVars()
break;
case VideoCondition::MATCH:
case VideoCondition::DIFFER:
case VideoCondition::HAS_NOT_CHANGED:
case VideoCondition::HAS_CHANGED:
case VideoCondition::NO_IMAGE:
default:
break;
@ -1477,6 +1498,7 @@ void MacroConditionVideoEdit::UsePatternForChangedCheckChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_patternMatchParameters.useForChangedCheck = value;
_entryData->SetupTempVars();
SetWidgetVisibility();
}

View File

@ -50,6 +50,7 @@ public:
void SetCondition(VideoCondition);
VideoCondition GetCondition() const { return _condition; }
void SetupTempVars();
VideoInput _video;
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
@ -89,8 +90,6 @@ private:
bool Compare();
bool CheckShouldBeSkipped();
void SetupTempVars();
VideoCondition _condition = VideoCondition::MATCH;
bool _getNextScreenshot = true;

View File

@ -48,20 +48,18 @@ static void preprocessPatternMatchResult(cv::Mat &mat, bool invert)
}
}
void MatchPattern(QImage &img, const PatternImageData &patternData,
double threshold, cv::Mat &result, double *pBestFitValue,
bool useAlphaAsMask, cv::TemplateMatchModes matchMode)
double MatchPattern(QImage &img, const PatternImageData &patternData,
double threshold, cv::Mat &result, bool useAlphaAsMask,
cv::TemplateMatchModes matchMode)
{
double bestFitValue = std::numeric_limits<double>::signaling_NaN();
result = cv::Mat(0, 0, CV_32F);
if (pBestFitValue) {
*pBestFitValue = std::numeric_limits<double>::signaling_NaN();
}
if (img.isNull() || patternData.rgbaPattern.empty()) {
return;
return bestFitValue;
}
if (img.height() < patternData.rgbaPattern.rows ||
img.width() < patternData.rgbaPattern.cols) {
return;
return bestFitValue;
}
auto input = QImageToMat(img);
@ -94,20 +92,18 @@ void MatchPattern(QImage &img, const PatternImageData &patternData,
// -> Invert TM_SQDIFF_NORMED in the preprocess step
preprocessPatternMatchResult(result, matchMode == cv::TM_SQDIFF_NORMED);
if (pBestFitValue) {
cv::minMaxLoc(result, nullptr, pBestFitValue);
}
cv::minMaxLoc(result, nullptr, &bestFitValue);
cv::threshold(result, result, threshold, 0.0, cv::THRESH_TOZERO);
return bestFitValue;
}
void MatchPattern(QImage &img, QImage &pattern, double threshold,
cv::Mat &result, double *pBestFitValue, bool useAlphaAsMask,
cv::TemplateMatchModes matchColor)
double MatchPattern(QImage &img, QImage &pattern, double threshold,
cv::Mat &result, bool useAlphaAsMask,
cv::TemplateMatchModes matchColor)
{
auto data = CreatePatternData(pattern);
MatchPattern(img, data, threshold, result, pBestFitValue,
useAlphaAsMask, matchColor);
return MatchPattern(img, data, threshold, result, useAlphaAsMask,
matchColor);
}
std::vector<cv::Rect> MatchObject(QImage &img, cv::CascadeClassifier &cascade,

View File

@ -62,12 +62,12 @@ struct PatternImageData {
};
PatternImageData CreatePatternData(const QImage &pattern);
void MatchPattern(QImage &img, const PatternImageData &patternData,
double threshold, cv::Mat &result, double *pBestFitValue,
bool useAlphaAsMask, cv::TemplateMatchModes matchMode);
void MatchPattern(QImage &img, QImage &pattern, double threshold,
cv::Mat &result, double *pBestFitValue, bool useAlphaAsMask,
cv::TemplateMatchModes matchMode);
double MatchPattern(QImage &img, const PatternImageData &patternData,
double threshold, cv::Mat &result, bool useAlphaAsMask,
cv::TemplateMatchModes matchMode);
double MatchPattern(QImage &img, QImage &pattern, double threshold,
cv::Mat &result, bool useAlphaAsMask,
cv::TemplateMatchModes matchMode);
std::vector<cv::Rect> MatchObject(QImage &img, cv::CascadeClassifier &cascade,
double scaleFactor, int minNeighbors,
const cv::Size &minSize,

View File

@ -329,10 +329,10 @@ void PreviewImage::MarkPatternMatch(
const PatternImageData &patternImageData)
{
cv::Mat result;
double matchValue = std::numeric_limits<double>::signaling_NaN();
MatchPattern(screenshot, patternImageData, patternMatchParams.threshold,
result, &matchValue, patternMatchParams.useAlphaAsMask,
patternMatchParams.matchMode);
double matchValue = MatchPattern(screenshot, patternImageData,
patternMatchParams.threshold, result,
patternMatchParams.useAlphaAsMask,
patternMatchParams.matchMode);
emit ValueUpdate(matchValue);
if (result.total() == 0 || countNonZero(result) == 0) {
emit StatusUpdate(obs_module_text(