#include "matcher.h" #include #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({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 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); } }