diff --git a/Makefile b/Makefile index 961a5b0..036fb37 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ LOGF = ./thirdparty/Log/ LOGO = $(LOGF)Log.o INCLUDES = -I$(LOGF) $(addprefix -I, $(INCFS)) -LDFLAGS = -lX11 -lXext `pkg-config opencv4 --libs` +LDFLAGS = -lX11 -lXext `pkg-config opencv4 --libs` -lXInputSimulator SRCFILES = $(shell find $(SRCF) -name "*.cpp") OBJFILES = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(patsubst %.cpp, %.o, $(SRCFILES))) $(LOGO) diff --git a/include/matcher.h b/include/matcher.h new file mode 100644 index 0000000..71dde0f --- /dev/null +++ b/include/matcher.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +class Matcher { +private: + cv::Mat templ; + +public: + Matcher(const std::string& filename); + Matcher(const cv::Mat& templ); + ~Matcher(); + + struct Match { + bool doesMatch = false; + int x = 0, y = 0; + int width = 0; + int height = 0; + }; + + Match match(const cv::Mat& img); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bc98c23..cba1dea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,29 +2,11 @@ #include "Log.h" #include "screen.h" +#include "matcher.h" -std::string type2str(int type) { - std::string r; +#include - uchar depth = type & CV_MAT_DEPTH_MASK; - uchar chans = 1 + (type >> CV_CN_SHIFT); - - switch ( depth ) { - case CV_8U: r = "8U"; break; - case CV_8S: r = "8S"; break; - case CV_16U: r = "16U"; break; - case CV_16S: r = "16S"; break; - case CV_32S: r = "32S"; break; - case CV_32F: r = "32F"; break; - case CV_64F: r = "64F"; break; - default: r = "User"; break; - } - - r += "C"; - r += (chans+'0'); - - return r; -} +#include int main(int argc, const char** argv) { Log::init(); @@ -37,45 +19,38 @@ int main(int argc, const char** argv) { Log::info << "Hello, World!"; // load template - cv::Mat tem = cv::imread("imgs/Accept.png", cv::IMREAD_COLOR); - // cv::imshow("template", tem); - // cv::waitKey(0); + Matcher matcher("imgs/Accept.png"); ScreenShot screen; - cv::Mat img; - screen(img); - // cv::imshow("img", img); - // cv::waitKey(0); + XInputSimulator& sim = XInputSimulator::getInstance(); - Log::info << "img " << img.type(); + while(true) { + cv::Mat img; + screen(img); - cv::Mat out; - int result_cols = img.cols - tem.cols + 1; - int result_rows = img.rows - tem.rows + 1; - out.create(result_rows, result_cols, CV_32FC1); + Matcher::Match mat = matcher.match(img); - Log::info << "tem " << tem.type() << " " << type2str(tem.type()); - // img.convertTo(img, tem.type()); + Log::warn << "matched: " << mat.doesMatch; - cv::cvtColor(img, img, cv::COLOR_RGBA2RGB); - Log::info << "converted img: " << img.type() << " " << type2str(img.type()); + if(mat.doesMatch) { + cv::rectangle(img, cv::Point(mat.x, mat.y), cv::Point( mat.x + mat.width , mat.y + mat.height ), cv::Scalar(0, 0, 255, 0), 2); - cv::matchTemplate(img, tem, out, cv::TM_SQDIFF); - cv::normalize(out, out, 0, 1, cv::NORM_MINMAX, -1, cv::Mat()); + time_t t = time(0); + cv::imwrite("debugimages/" + std::to_string(t) + ".jpg", img); - double minVal; double maxVal; - cv::Point minLoc; cv::Point maxLoc; cv::Point matchLoc; - cv::minMaxLoc( out, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() ); + int x = mat.x + (mat.width/2); + int y = mat.y + (mat.height/2); + sim.mouseMoveTo(x, y); - matchLoc = minLoc; - cv::rectangle(img, matchLoc, cv::Point( matchLoc.x + tem.cols , matchLoc.y + tem.rows ), cv::Scalar(255, 0, 0, 0), 2); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + sim.mouseClick(XIS::LEFT_MOUSE_BUTTON); - cv::imshow("result", img); - cv::waitKey(0); + std::this_thread::sleep_for(std::chrono::seconds(10)); + } - time_t t = time(0); - cv::imwrite("debugimages/" + std::to_string(t) + ".png", img); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } Log::stop(); return 0; diff --git a/src/matcher.cpp b/src/matcher.cpp new file mode 100644 index 0000000..9b84dce --- /dev/null +++ b/src/matcher.cpp @@ -0,0 +1,39 @@ +#include "matcher.h" + +#include + +Matcher::Matcher(const std::string& filename) { + templ = cv::imread(filename, cv::IMREAD_COLOR); +} +Matcher::Matcher(const cv::Mat& templ) { + templ.copyTo(this->templ); +} +Matcher::~Matcher() {} + +Matcher::Match Matcher::match(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); + + // remove Alpha channel from input + cv::Mat converted; + cv::cvtColor(img, converted, cv::COLOR_RGBA2RGB); + + // match + cv::matchTemplate(converted, templ, out, cv::TM_SQDIFF); + + double minValbn; double maxValbn; + cv::minMaxLoc( out, &minValbn, &maxValbn, NULL, NULL, cv::Mat() ); + cv::normalize(out, out, 0, 1, cv::NORM_MINMAX, -1, cv::Mat()); + + double minVal; double maxVal; + cv::Point minLoc; cv::Point maxLoc; + cv::minMaxLoc( out, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() ); + + Log::info << "minValbn: " << minValbn << " maxValbn: " << maxValbn << " minVal: " << minVal << " maxVal: " << maxVal << " minLoc: " << minLoc.x << " " << minLoc.y << " maxLoc: " << maxLoc.x << " " << maxLoc.y; + + bool matched = minValbn < 2e7; + + return {matched, minLoc.x, minLoc.y, templ.cols, templ.rows}; +} \ No newline at end of file