lolautoaccept/src/matcher.cpp

103 lines
2.7 KiB
C++

#include "matcher.h"
#include <Log.h>
#include "util.h"
std::string Matcher::pathbase;
void Matcher::setPathBase(const std::string& pa) {
pathbase = pa;
}
Matcher::Matcher(const std::string& filename) {
templ = cv::imread(pathbase + filename, cv::IMREAD_UNCHANGED); // unchanged so alpha channel does not get dropped
maskFromTemplate();
}
Matcher::Matcher(const cv::Mat& templ) {
templ.copyTo(this->templ);
maskFromTemplate();
}
Matcher::~Matcher() {}
void Matcher::setOffset(int32_t x, int32_t y) {
posx = x;
posy = y;
}
bool Matcher::Match::operator==(const Match& other) const {
return doesMatch == other.doesMatch && x == other.x && y == other.y && width == other.width && height == other.height;
}
bool Matcher::Match::operator!=(const Match& other) const {
return !(*this == other);
}
Matcher::Match Matcher::match(const cv::Mat& img) {
// remove Alpha channel from input
cv::Mat converted;
cv::cvtColor(img, converted, cv::COLOR_RGBA2RGB);
if(posx < 0 || posy < 0) {
return matchAll(converted);
}
return matchPos(converted);
}
// https://stackoverflow.com/a/43133263/4399859
Matcher::Match Matcher::matchAll(const cv::Mat& img) {
// create out mat
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
cv::Mat out(result_rows, result_cols, CV_32FC1);
Log::info << "match size: " << result_cols << " " << result_cols;
// match
cv::matchTemplate(img, templ, out, cv::TM_CCORR_NORMED, mask);
double minVal; double maxVal;
cv::Point minLoc; cv::Point maxLoc;
cv::minMaxLoc( out, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
Log::debug << "pixelcount: " << (templ.cols * templ.rows) << " minVal: " << minVal << " maxVal: " << maxVal << " minLoc: " << minLoc.x << " " << minLoc.y << " maxLoc: " << maxLoc.x << " " << maxLoc.y;
bool matched = maxVal > 0.95;
return {matched, maxLoc.x, maxLoc.y, templ.cols, templ.rows};
}
Matcher::Match Matcher::matchPos(const cv::Mat& img) {
cv::Mat matchpart = img(cv::Range(posy, posy + templ.rows), cv::Range(posx, posx + templ.cols));
// create out mat (only one pxl)
cv::Mat out(1, 1, CV_32FC1);
// match
cv::matchTemplate(matchpart, templ, out, cv::TM_CCORR_NORMED, mask);
float val = out.at<float>({0, 0});
bool matched = val > 0.95;
Log::debug << "val: " << val;
return {matched, posx, posy, templ.cols, templ.rows};
}
void Matcher::maskFromTemplate() {
if(templ.channels() == 4) {
// split channels
std::vector<cv::Mat> split;
cv::split(templ, split);
// template without alpha channel
cv::merge(std::vector(split.begin(), split.end()-1), templ);
// 3*alpha channel
cv::Mat alphaChannel = split.at(3);
alphaChannel.convertTo(alphaChannel, CV_8U);
cv::merge(std::vector(3, alphaChannel), mask);
}
}