Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a4ddfee71 | ||
|
|
3c0d91e320 | ||
|
|
a0f317b7c3 | ||
|
|
08b5d92f6d | ||
|
|
fb8b323335 | ||
|
|
afabb54c42 | ||
|
|
aa89efee15 | ||
|
|
0bc224f671 | ||
|
|
d0164a958d | ||
|
|
f165e0b2b2 | ||
|
|
a5f9e55fe2 | ||
|
|
7fc46c160c | ||
|
|
481135bcb2 | ||
|
|
a2c49d2feb | ||
|
|
02551f62ce | ||
|
|
07436c3c70 | ||
|
|
53c993cd67 | ||
|
|
d7b21ea307 | ||
|
|
d2962f10be | ||
|
|
39ffb8e50a | ||
|
|
d3d81253a4 | ||
|
|
febe7eacd7 | ||
|
|
240dee72d5 | ||
|
|
7e5875d213 | ||
|
|
5e36b493c1 | ||
|
|
7274f50684 | ||
|
|
d9182694a6 | ||
|
|
ad68e046f1 | ||
|
|
0d082d1635 | ||
|
|
989b96213f | ||
|
|
f2c3129fee | ||
|
|
9c20b5da49 | ||
|
|
b516c94512 | ||
|
|
c233c3ed38 | ||
|
|
d16b873ddf | ||
|
|
9f4b98dbac | ||
|
|
cb7f848d5e | ||
|
|
3d3e37687e | ||
|
|
d8829f869c | ||
|
|
0f7995f69a | ||
|
|
f6e69cc4ff | ||
|
|
767a667fbe | ||
|
|
94f0eced1c | ||
|
|
f000226a8d | ||
|
|
410d3c0885 | ||
|
|
3307838857 | ||
|
|
54a2127e45 | ||
|
|
2ed1d7302f | ||
|
|
35e5dcf460 | ||
|
|
36529d9760 | ||
|
|
2762ee9a28 | ||
|
|
3dc491f762 | ||
|
|
24e5f2eb61 | ||
|
|
c7a5b090eb | ||
|
|
e636fb1a77 | ||
|
|
d57a57960b | ||
|
|
42d92ef03d | ||
|
|
d3490ac2b2 | ||
|
|
4cdaaab27c | ||
|
|
75253107b6 | ||
|
|
517a9e09ed | ||
|
|
5741bc17f1 | ||
|
|
09fc9a4622 | ||
|
|
8293343467 | ||
|
|
dba4bf5dd4 | ||
|
|
ed1ec4c7f4 | ||
|
|
ef656e1c87 | ||
|
|
f17bb4d814 | ||
|
|
048dfd3f41 | ||
|
|
9efdc4d6f8 | ||
|
|
6ba9fc1f8d | ||
|
|
b46cc97c71 | ||
|
|
6e04a670a6 | ||
|
|
dcd9e5b8dc | ||
|
|
10c9fefe47 |
14
.github/ISSUE_TEMPLATE/-----bug-report-.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: 问题反馈(Bug report)
|
||||
about: 识别错误、操作异常、连接错误等
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
请附上助手软件目录下的`asst.log`日志文件,是可以直接拖拽进来的。
|
||||
|
||||
最好再能说明下使用的模拟器、并附上出错时的游戏和软件的截图(要是没截到就算啦_(:з」∠)_
|
||||
|
||||
Thanks♪(・ω・)ノ
|
||||
10
.github/ISSUE_TEMPLATE/-----feature-request-.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: 需求建议(Feature request)
|
||||
about: 新功能、建议等
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/---others-.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: 其他(Others)
|
||||
about: 其他议题
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
2
.gitignore
vendored
@@ -2,6 +2,7 @@
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
build
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
@@ -405,6 +406,7 @@ MigrationBackup/
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
**/.vscode/*
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
|
||||
BIN
3rdparty/bin/OcrLiteOnnx.dll
vendored
BIN
3rdparty/bin/libiomp5md.dll
vendored
Normal file
BIN
3rdparty/bin/mkldnn.dll
vendored
Normal file
BIN
3rdparty/bin/mklml.dll
vendored
Normal file
BIN
3rdparty/bin/paddle_inference.dll
vendored
Normal file
BIN
3rdparty/bin/ppocr.dll
vendored
Normal file
41
3rdparty/include/OcrLiteOnnx/AngleNet.h
vendored
@@ -1,41 +0,0 @@
|
||||
#ifndef __OCR_ANGLENET_H__
|
||||
#define __OCR_ANGLENET_H__
|
||||
|
||||
#include "OcrStruct.h"
|
||||
#include "onnxruntime_cxx_api.h"
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
class AngleNet {
|
||||
public:
|
||||
AngleNet();
|
||||
|
||||
~AngleNet();
|
||||
|
||||
void setNumThread(int numOfThread);
|
||||
|
||||
void initModel(const std::string &pathStr);
|
||||
|
||||
std::vector<Angle> getAngles(std::vector<cv::Mat> &partImgs, const char *path,
|
||||
const char *imgName, bool doAngle, bool mostAngle);
|
||||
|
||||
private:
|
||||
bool isOutputAngleImg = false;
|
||||
|
||||
Ort::Session *session;
|
||||
Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "AngleNet");
|
||||
Ort::SessionOptions sessionOptions = Ort::SessionOptions();
|
||||
int numThread = 0;
|
||||
|
||||
char *inputName;
|
||||
char *outputName;
|
||||
|
||||
const float meanValues[3] = {127.5, 127.5, 127.5};
|
||||
const float normValues[3] = {1.0 / 127.5, 1.0 / 127.5, 1.0 / 127.5};
|
||||
const int dstWidth = 192;
|
||||
const int dstHeight = 32;
|
||||
|
||||
Angle getAngle(cv::Mat &src);
|
||||
};
|
||||
|
||||
|
||||
#endif //__OCR_ANGLENET_H__
|
||||
43
3rdparty/include/OcrLiteOnnx/CrnnNet.h
vendored
@@ -1,43 +0,0 @@
|
||||
#ifndef __OCR_CRNNNET_H__
|
||||
#define __OCR_CRNNNET_H__
|
||||
|
||||
#include "OcrStruct.h"
|
||||
#include "onnxruntime_cxx_api.h"
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
class CrnnNet {
|
||||
public:
|
||||
|
||||
CrnnNet();
|
||||
|
||||
~CrnnNet();
|
||||
|
||||
void setNumThread(int numOfThread);
|
||||
|
||||
void initModel(const std::string &pathStr, const std::string &keysPath);
|
||||
|
||||
std::vector<TextLine> getTextLines(std::vector<cv::Mat> &partImg, const char *path, const char *imgName);
|
||||
|
||||
private:
|
||||
bool isOutputDebugImg = false;
|
||||
Ort::Session *session;
|
||||
Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "CrnnNet");
|
||||
Ort::SessionOptions sessionOptions = Ort::SessionOptions();
|
||||
int numThread = 0;
|
||||
|
||||
char *inputName;
|
||||
char *outputName;
|
||||
|
||||
const float meanValues[3] = {127.5, 127.5, 127.5};
|
||||
const float normValues[3] = {1.0 / 127.5, 1.0 / 127.5, 1.0 / 127.5};
|
||||
const int dstHeight = 32;
|
||||
|
||||
std::vector<std::string> keys;
|
||||
|
||||
TextLine scoreToTextLine(const std::vector<float> &outputData, int h, int w);
|
||||
|
||||
TextLine getTextLine(const cv::Mat &src);
|
||||
};
|
||||
|
||||
|
||||
#endif //__OCR_CRNNNET_H__
|
||||
34
3rdparty/include/OcrLiteOnnx/DbNet.h
vendored
@@ -1,34 +0,0 @@
|
||||
#ifndef __OCR_DBNET_H__
|
||||
#define __OCR_DBNET_H__
|
||||
|
||||
#include "OcrStruct.h"
|
||||
#include "onnxruntime_cxx_api.h"
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
class DbNet {
|
||||
public:
|
||||
DbNet();
|
||||
|
||||
~DbNet();
|
||||
|
||||
void setNumThread(int numOfThread);
|
||||
|
||||
void initModel(const std::string &pathStr);
|
||||
|
||||
std::vector<TextBox> getTextBoxes(cv::Mat &src, ScaleParam &s, float boxScoreThresh,
|
||||
float boxThresh, float unClipRatio);
|
||||
|
||||
private:
|
||||
Ort::Session *session;
|
||||
Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "DbNet");
|
||||
Ort::SessionOptions sessionOptions = Ort::SessionOptions();
|
||||
int numThread = 0;
|
||||
char *inputName;
|
||||
char *outputName;
|
||||
|
||||
const float meanValues[3] = {0.485 * 255, 0.456 * 255, 0.406 * 255};
|
||||
const float normValues[3] = {1.0 / 0.229 / 255.0, 1.0 / 0.224 / 255.0, 1.0 / 0.225 / 255.0};
|
||||
};
|
||||
|
||||
|
||||
#endif //__OCR_DBNET_H__
|
||||
56
3rdparty/include/OcrLiteOnnx/OcrLite.h
vendored
@@ -1,56 +0,0 @@
|
||||
#ifndef __OCR_LITE_H__
|
||||
#define __OCR_LITE_H__
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "onnxruntime_cxx_api.h"
|
||||
#include "OcrStruct.h"
|
||||
#include "DbNet.h"
|
||||
#include "AngleNet.h"
|
||||
#include "CrnnNet.h"
|
||||
|
||||
class OcrLite {
|
||||
public:
|
||||
OcrLite();
|
||||
|
||||
~OcrLite();
|
||||
|
||||
void setNumThread(int numOfThread);
|
||||
|
||||
void initLogger(bool isConsole, bool isPartImg, bool isResultImg);
|
||||
|
||||
void enableResultTxt(const char *path, const char *imgName);
|
||||
|
||||
void initModels(const std::string &detPath, const std::string &clsPath,
|
||||
const std::string &recPath, const std::string &keysPath);
|
||||
|
||||
void Logger(const char *format, ...);
|
||||
|
||||
OcrResult detect(const char *path, const char *imgName,
|
||||
int padding, int maxSideLen,
|
||||
float boxScoreThresh, float boxThresh, float unClipRatio, bool doAngle, bool mostAngle);
|
||||
|
||||
|
||||
OcrResult detect(const cv::Mat& mat,
|
||||
int padding, int maxSideLen,
|
||||
float boxScoreThresh, float boxThresh, float unClipRatio, bool doAngle, bool mostAngle);
|
||||
|
||||
private:
|
||||
bool isOutputConsole = false;
|
||||
bool isOutputPartImg = false;
|
||||
bool isOutputResultTxt = false;
|
||||
bool isOutputResultImg = false;
|
||||
FILE *resultTxt;
|
||||
DbNet dbNet;
|
||||
AngleNet angleNet;
|
||||
CrnnNet crnnNet;
|
||||
|
||||
std::vector<cv::Mat> getPartImages(cv::Mat &src, std::vector<TextBox> &textBoxes,
|
||||
const char *path, const char *imgName);
|
||||
|
||||
OcrResult detect(const char *path, const char *imgName,
|
||||
cv::Mat &src, cv::Rect &originRect, ScaleParam &scale,
|
||||
float boxScoreThresh = 0.6f, float boxThresh = 0.3f,
|
||||
float unClipRatio = 2.0f, bool doAngle = true, bool mostAngle = true);
|
||||
};
|
||||
|
||||
#endif //__OCR_LITE_H__
|
||||
39
3rdparty/include/OcrLiteOnnx/OcrLiteCaller.h
vendored
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "OcrLitePort.h"
|
||||
#include "OcrStruct.h"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
class Mat;
|
||||
}
|
||||
class OcrLite;
|
||||
|
||||
class OCRLITE_PORT OcrLiteCaller
|
||||
{
|
||||
public:
|
||||
OcrLiteCaller();
|
||||
~OcrLiteCaller();
|
||||
OcrLiteCaller(const OcrLite&) = delete;
|
||||
OcrLiteCaller(OcrLite&&) = delete;
|
||||
|
||||
void setNumThread(int numOfThread);
|
||||
bool initModels(const std::string& detPath, const std::string& clsPath,
|
||||
const std::string& recPath, const std::string& keysPath);
|
||||
|
||||
OcrResult detect(const cv::Mat& mat,
|
||||
int padding, int maxSideLen,
|
||||
float boxScoreThresh, float boxThresh, float unClipRatio, bool doAngle, bool mostAngle);
|
||||
|
||||
OcrResult detect(const std::string& dir, const std::string& file,
|
||||
int padding, int maxSideLen,
|
||||
float boxScoreThresh, float boxThresh, float unClipRatio, bool doAngle, bool mostAngle);
|
||||
|
||||
OcrLiteCaller& operator=(const OcrLiteCaller&) = delete;
|
||||
OcrLiteCaller& operator=(OcrLiteCaller&&) = delete;
|
||||
private:
|
||||
std::unique_ptr<OcrLite> m_ocrlite_ptr;
|
||||
};
|
||||
45
3rdparty/include/OcrLiteOnnx/OcrLitePort.h
vendored
@@ -1,45 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(__JNI__) && !defined(__EXEC__)
|
||||
|
||||
// The way how the function is called
|
||||
#if !defined(OCRLITE_CALL)
|
||||
#if defined(_WIN32)
|
||||
#define OCRLITE_CALL __stdcall
|
||||
#else
|
||||
#define OCRLITE_CALL
|
||||
#endif /* _WIN32 */
|
||||
#endif /* OCRLITE_CALL */
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#define OCRLITE_EXPORT __declspec(dllexport)
|
||||
#define OCRLITE_IMPORT __declspec(dllimport)
|
||||
#define OCRLITE_LOCAL
|
||||
#else // ! defined _WIN32 || defined __CYGWIN__
|
||||
#if __GNUC__ >= 4
|
||||
#define OCRLITE_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define OCRLITE_IMPORT __attribute__ ((visibility ("default")))
|
||||
#define OCRLITE_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#else // ! __GNUC__ >= 4
|
||||
#define OCRLITE_EXPORT
|
||||
#define OCRLITE_IMPORT
|
||||
#endif // End __GNUC__ >= 4
|
||||
#endif // End defined _WIN32 || defined __CYGWIN__
|
||||
|
||||
#ifdef __CLIB__
|
||||
#define OCRLITE_PORT OCRLITE_EXPORT
|
||||
#else
|
||||
#define OCRLITE_PORT OCRLITE_IMPORT
|
||||
#endif // OCRLITE_PORT
|
||||
|
||||
#define OCR_API OCRLITE_PORT OCRLITE_CALL
|
||||
|
||||
#define OCR_LOCAL OCRLITE_LOCAL OCRLITE_CALL
|
||||
|
||||
#else // __JNI__ || __EXEC__
|
||||
|
||||
#define OCRLITE_PORT
|
||||
#define OCR_API
|
||||
#define OCR_LOCAL
|
||||
|
||||
#endif // __JNI__ || __EXEC__
|
||||
35
3rdparty/include/OcrLiteOnnx/OcrResultUtils.h
vendored
@@ -1,35 +0,0 @@
|
||||
#ifdef __JNI__
|
||||
#ifndef __OCR_RESULT_UTILS_H__
|
||||
#define __OCR_RESULT_UTILS_H__
|
||||
#include <jni.h>
|
||||
#include "OcrStruct.h"
|
||||
|
||||
class OcrResultUtils {
|
||||
public:
|
||||
OcrResultUtils(JNIEnv *env, OcrResult &ocrResult);
|
||||
|
||||
~OcrResultUtils();
|
||||
|
||||
jobject getJObject();
|
||||
|
||||
private:
|
||||
JNIEnv *jniEnv;
|
||||
jobject jOcrResult;
|
||||
|
||||
jclass newJListClass();
|
||||
|
||||
jmethodID getListConstructor(jclass clazz);
|
||||
|
||||
jobject getTextBlock(TextBlock &textBlock);
|
||||
|
||||
jobject getTextBlocks(std::vector<TextBlock> &textBlocks);
|
||||
|
||||
jobject newJPoint(cv::Point &point);
|
||||
|
||||
jobject newJBoxPoint(std::vector<cv::Point> &boxPoint);
|
||||
|
||||
jfloatArray newJScoreArray(std::vector<float> &scores);
|
||||
|
||||
};
|
||||
#endif //__OCR_RESULT_UTILS_H__
|
||||
#endif
|
||||
55
3rdparty/include/OcrLiteOnnx/OcrStruct.h
vendored
@@ -1,55 +0,0 @@
|
||||
#ifndef __OCR_STRUCT_H__
|
||||
#define __OCR_STRUCT_H__
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include <vector>
|
||||
|
||||
#include "OcrLitePort.h"
|
||||
|
||||
struct ScaleParam {
|
||||
int srcWidth;
|
||||
int srcHeight;
|
||||
int dstWidth;
|
||||
int dstHeight;
|
||||
float ratioWidth;
|
||||
float ratioHeight;
|
||||
};
|
||||
|
||||
struct TextBox {
|
||||
std::vector<cv::Point> boxPoint;
|
||||
float score;
|
||||
};
|
||||
|
||||
struct Angle {
|
||||
int index;
|
||||
float score;
|
||||
double time;
|
||||
};
|
||||
|
||||
struct TextLine {
|
||||
std::string text;
|
||||
std::vector<float> charScores;
|
||||
double time;
|
||||
};
|
||||
|
||||
struct OCRLITE_PORT TextBlock {
|
||||
std::vector<cv::Point> boxPoint;
|
||||
float boxScore;
|
||||
int angleIndex;
|
||||
float angleScore;
|
||||
double angleTime;
|
||||
std::string text;
|
||||
std::vector<float> charScores;
|
||||
double crnnTime;
|
||||
double blockTime;
|
||||
};
|
||||
|
||||
struct OCRLITE_PORT OcrResult {
|
||||
double dbNetTime;
|
||||
std::vector<TextBlock> textBlocks;
|
||||
cv::Mat boxImg;
|
||||
double detectTime;
|
||||
std::string strRes;
|
||||
};
|
||||
|
||||
#endif //__OCR_STRUCT_H__
|
||||
103
3rdparty/include/OcrLiteOnnx/OcrUtils.h
vendored
@@ -1,103 +0,0 @@
|
||||
#ifndef __OCR_UTILS_H__
|
||||
#define __OCR_UTILS_H__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include "OcrStruct.h"
|
||||
#include "onnxruntime_cxx_api.h"
|
||||
#include <numeric>
|
||||
#include <sys/stat.h>
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
static std::unique_ptr<T> makeUnique(Ts &&... params) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static double getMean(std::vector<T> &input) {
|
||||
auto sum = accumulate(input.begin(), input.end(), 0.0);
|
||||
return sum / input.size();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static double getStdev(std::vector<T> &input, double mean) {
|
||||
if (input.size() <= 1) return 0;
|
||||
double accum = 0.0;
|
||||
for_each(input.begin(), input.end(), [&](const double d) {
|
||||
accum += (d - mean) * (d - mean);
|
||||
});
|
||||
double stdev = sqrt(accum / (input.size() - 1));
|
||||
return stdev;
|
||||
}
|
||||
|
||||
double getCurrentTime();
|
||||
|
||||
inline bool isFileExists(const std::string &name) {
|
||||
struct stat buffer;
|
||||
return (stat(name.c_str(), &buffer) == 0);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define my_strtol wcstol
|
||||
#define my_strrchr wcsrchr
|
||||
#define my_strcasecmp _wcsicmp
|
||||
#define my_strdup _strdup
|
||||
#else
|
||||
#define my_strtol strtol
|
||||
#define my_strrchr strrchr
|
||||
#define my_strcasecmp strcasecmp
|
||||
#define my_strdup strdup
|
||||
#endif
|
||||
|
||||
std::wstring strToWstr(std::string str);
|
||||
|
||||
ScaleParam getScaleParam(cv::Mat &src, const float scale);
|
||||
|
||||
ScaleParam getScaleParam(cv::Mat &src, const int targetSize);
|
||||
|
||||
std::vector<cv::Point2f> getBox(const cv::RotatedRect &rect);
|
||||
|
||||
int getThickness(cv::Mat &boxImg);
|
||||
|
||||
void drawTextBox(cv::Mat &boxImg, cv::RotatedRect &rect, int thickness);
|
||||
|
||||
void drawTextBox(cv::Mat &boxImg, const std::vector<cv::Point> &box, int thickness);
|
||||
|
||||
void drawTextBoxes(cv::Mat &boxImg, std::vector<TextBox> &textBoxes, int thickness);
|
||||
|
||||
cv::Mat matRotateClockWise180(cv::Mat src);
|
||||
|
||||
cv::Mat matRotateClockWise90(cv::Mat src);
|
||||
|
||||
cv::Mat getRotateCropImage(const cv::Mat &src, std::vector<cv::Point> box);
|
||||
|
||||
cv::Mat adjustTargetImg(cv::Mat &src, int dstWidth, int dstHeight);
|
||||
|
||||
std::vector<cv::Point> getMinBoxes(const std::vector<cv::Point> &inVec, float &minSideLen, float &allEdgeSize);
|
||||
|
||||
float boxScoreFast(const cv::Mat &inMat, const std::vector<cv::Point> &inBox);
|
||||
|
||||
std::vector<cv::Point> unClip(const std::vector<cv::Point> &inBox, float perimeter, float unClipRatio);
|
||||
|
||||
std::vector<float> substractMeanNormalize(cv::Mat &src, const float *meanVals, const float *normVals);
|
||||
|
||||
std::vector<int> getAngleIndexes(std::vector<Angle> &angles);
|
||||
|
||||
std::vector<char *> getInputNames(Ort::Session *session);
|
||||
|
||||
std::vector<char *> getOutputNames(Ort::Session *session);
|
||||
|
||||
void getInputName(Ort::Session *session, char *&inputName);
|
||||
|
||||
void getOutputName(Ort::Session *session, char *&outputName);
|
||||
|
||||
void saveImg(cv::Mat &img, const char *imgPath);
|
||||
|
||||
std::string getSrcImgFilePath(const char *path, const char *imgName);
|
||||
|
||||
std::string getResultTxtFilePath(const char *path, const char *imgName);
|
||||
|
||||
std::string getResultImgFilePath(const char *path, const char *imgName);
|
||||
|
||||
std::string getDebugImgFilePath(const char *path, const char *imgName, int i, const char *tag);
|
||||
|
||||
#endif //__OCR_UTILS_H__
|
||||
406
3rdparty/include/OcrLiteOnnx/clipper.hpp
vendored
@@ -1,406 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 6.4.2 *
|
||||
* Date : 27 February 2017 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2017 *
|
||||
* *
|
||||
* License: *
|
||||
* Use, modification & distribution is subject to Boost Software License Ver 1. *
|
||||
* http://www.boost.org/LICENSE_1_0.txt *
|
||||
* *
|
||||
* Attributions: *
|
||||
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
|
||||
* "A generic solution to polygon clipping" *
|
||||
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
|
||||
* http://portal.acm.org/citation.cfm?id=129906 *
|
||||
* *
|
||||
* Computer graphics and geometric modeling: implementation and algorithms *
|
||||
* By Max K. Agoston *
|
||||
* Springer; 1 edition (January 4, 2005) *
|
||||
* http://books.google.com/books?q=vatti+clipping+agoston *
|
||||
* *
|
||||
* See also: *
|
||||
* "Polygon Offsetting by Computing Winding Numbers" *
|
||||
* Paper no. DETC2005-85513 pp. 565-575 *
|
||||
* ASME 2005 International Design Engineering Technical Conferences *
|
||||
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
|
||||
* September 24-28, 2005 , Long Beach, California, USA *
|
||||
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef clipper_hpp
|
||||
#define clipper_hpp
|
||||
|
||||
#define CLIPPER_VERSION "6.4.2"
|
||||
|
||||
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
|
||||
//improve performance but coordinate values are limited to the range +/- 46340
|
||||
//#define use_int32
|
||||
|
||||
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
|
||||
//#define use_xyz
|
||||
|
||||
//use_lines: Enables line clipping. Adds a very minor cost to performance.
|
||||
#define use_lines
|
||||
|
||||
//use_deprecated: Enables temporary support for the obsolete functions
|
||||
//#define use_deprecated
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ostream>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
|
||||
namespace ClipperLib {
|
||||
|
||||
enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
|
||||
enum PolyType { ptSubject, ptClip };
|
||||
//By far the most widely used winding rules for polygon filling are
|
||||
//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
|
||||
//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
|
||||
//see http://glprogramming.com/red/chapter11.html
|
||||
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
||||
|
||||
#ifdef use_int32
|
||||
typedef int cInt;
|
||||
static cInt const loRange = 0x7FFF;
|
||||
static cInt const hiRange = 0x7FFF;
|
||||
#else
|
||||
typedef signed long long cInt;
|
||||
static cInt const loRange = 0x3FFFFFFF;
|
||||
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
||||
typedef signed long long long64; //used by Int128 class
|
||||
typedef unsigned long long ulong64;
|
||||
|
||||
#endif
|
||||
|
||||
struct IntPoint {
|
||||
cInt X;
|
||||
cInt Y;
|
||||
#ifdef use_xyz
|
||||
cInt Z;
|
||||
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
|
||||
#else
|
||||
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
|
||||
#endif
|
||||
|
||||
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
|
||||
{
|
||||
return a.X == b.X && a.Y == b.Y;
|
||||
}
|
||||
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
|
||||
{
|
||||
return a.X != b.X || a.Y != b.Y;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef std::vector< IntPoint > Path;
|
||||
typedef std::vector< Path > Paths;
|
||||
|
||||
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
|
||||
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const IntPoint &p);
|
||||
std::ostream& operator <<(std::ostream &s, const Path &p);
|
||||
std::ostream& operator <<(std::ostream &s, const Paths &p);
|
||||
|
||||
struct DoublePoint
|
||||
{
|
||||
double X;
|
||||
double Y;
|
||||
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
|
||||
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef use_xyz
|
||||
typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
|
||||
#endif
|
||||
|
||||
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
|
||||
enum JoinType {jtSquare, jtRound, jtMiter};
|
||||
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
|
||||
|
||||
class PolyNode;
|
||||
typedef std::vector< PolyNode* > PolyNodes;
|
||||
|
||||
class PolyNode
|
||||
{
|
||||
public:
|
||||
PolyNode();
|
||||
virtual ~PolyNode(){};
|
||||
Path Contour;
|
||||
PolyNodes Childs;
|
||||
PolyNode* Parent;
|
||||
PolyNode* GetNext() const;
|
||||
bool IsHole() const;
|
||||
bool IsOpen() const;
|
||||
int ChildCount() const;
|
||||
private:
|
||||
//PolyNode& operator =(PolyNode& other);
|
||||
unsigned Index; //node index in Parent.Childs
|
||||
bool m_IsOpen;
|
||||
JoinType m_jointype;
|
||||
EndType m_endtype;
|
||||
PolyNode* GetNextSiblingUp() const;
|
||||
void AddChild(PolyNode& child);
|
||||
friend class Clipper; //to access Index
|
||||
friend class ClipperOffset;
|
||||
};
|
||||
|
||||
class PolyTree: public PolyNode
|
||||
{
|
||||
public:
|
||||
~PolyTree(){ Clear(); };
|
||||
PolyNode* GetFirst() const;
|
||||
void Clear();
|
||||
int Total() const;
|
||||
private:
|
||||
//PolyTree& operator =(PolyTree& other);
|
||||
PolyNodes AllNodes;
|
||||
friend class Clipper; //to access AllNodes
|
||||
};
|
||||
|
||||
bool Orientation(const Path &poly);
|
||||
double Area(const Path &poly);
|
||||
int PointInPolygon(const IntPoint &pt, const Path &path);
|
||||
|
||||
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
|
||||
|
||||
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
||||
void CleanPolygon(Path& poly, double distance = 1.415);
|
||||
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
|
||||
void CleanPolygons(Paths& polys, double distance = 1.415);
|
||||
|
||||
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
|
||||
void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
|
||||
void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
|
||||
|
||||
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
|
||||
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
|
||||
void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
|
||||
|
||||
void ReversePath(Path& p);
|
||||
void ReversePaths(Paths& p);
|
||||
|
||||
struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
|
||||
|
||||
//enums that are used internally ...
|
||||
enum EdgeSide { esLeft = 1, esRight = 2};
|
||||
|
||||
//forward declarations (for stuff used internally) ...
|
||||
struct TEdge;
|
||||
struct IntersectNode;
|
||||
struct LocalMinimum;
|
||||
struct OutPt;
|
||||
struct OutRec;
|
||||
struct Join;
|
||||
|
||||
typedef std::vector < OutRec* > PolyOutList;
|
||||
typedef std::vector < TEdge* > EdgeList;
|
||||
typedef std::vector < Join* > JoinList;
|
||||
typedef std::vector < IntersectNode* > IntersectList;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//ClipperBase is the ancestor to the Clipper class. It should not be
|
||||
//instantiated directly. This class simply abstracts the conversion of sets of
|
||||
//polygon coordinates into edge objects that are stored in a LocalMinima list.
|
||||
class ClipperBase
|
||||
{
|
||||
public:
|
||||
ClipperBase();
|
||||
virtual ~ClipperBase();
|
||||
virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
|
||||
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
|
||||
virtual void Clear();
|
||||
IntRect GetBounds();
|
||||
bool PreserveCollinear() {return m_PreserveCollinear;};
|
||||
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
|
||||
protected:
|
||||
void DisposeLocalMinimaList();
|
||||
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
|
||||
virtual void Reset();
|
||||
TEdge* ProcessBound(TEdge* E, bool IsClockwise);
|
||||
void InsertScanbeam(const cInt Y);
|
||||
bool PopScanbeam(cInt &Y);
|
||||
bool LocalMinimaPending();
|
||||
bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin);
|
||||
OutRec* CreateOutRec();
|
||||
void DisposeAllOutRecs();
|
||||
void DisposeOutRec(PolyOutList::size_type index);
|
||||
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
|
||||
void DeleteFromAEL(TEdge *e);
|
||||
void UpdateEdgeIntoAEL(TEdge *&e);
|
||||
|
||||
typedef std::vector<LocalMinimum> MinimaList;
|
||||
MinimaList::iterator m_CurrentLM;
|
||||
MinimaList m_MinimaList;
|
||||
|
||||
bool m_UseFullRange;
|
||||
EdgeList m_edges;
|
||||
bool m_PreserveCollinear;
|
||||
bool m_HasOpenPaths;
|
||||
PolyOutList m_PolyOuts;
|
||||
TEdge *m_ActiveEdges;
|
||||
|
||||
typedef std::priority_queue<cInt> ScanbeamList;
|
||||
ScanbeamList m_Scanbeam;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class Clipper : public virtual ClipperBase
|
||||
{
|
||||
public:
|
||||
Clipper(int initOptions = 0);
|
||||
bool Execute(ClipType clipType,
|
||||
Paths &solution,
|
||||
PolyFillType fillType = pftEvenOdd);
|
||||
bool Execute(ClipType clipType,
|
||||
Paths &solution,
|
||||
PolyFillType subjFillType,
|
||||
PolyFillType clipFillType);
|
||||
bool Execute(ClipType clipType,
|
||||
PolyTree &polytree,
|
||||
PolyFillType fillType = pftEvenOdd);
|
||||
bool Execute(ClipType clipType,
|
||||
PolyTree &polytree,
|
||||
PolyFillType subjFillType,
|
||||
PolyFillType clipFillType);
|
||||
bool ReverseSolution() { return m_ReverseOutput; };
|
||||
void ReverseSolution(bool value) {m_ReverseOutput = value;};
|
||||
bool StrictlySimple() {return m_StrictSimple;};
|
||||
void StrictlySimple(bool value) {m_StrictSimple = value;};
|
||||
//set the callback function for z value filling on intersections (otherwise Z is 0)
|
||||
#ifdef use_xyz
|
||||
void ZFillFunction(ZFillCallback zFillFunc);
|
||||
#endif
|
||||
protected:
|
||||
virtual bool ExecuteInternal();
|
||||
private:
|
||||
JoinList m_Joins;
|
||||
JoinList m_GhostJoins;
|
||||
IntersectList m_IntersectList;
|
||||
ClipType m_ClipType;
|
||||
typedef std::list<cInt> MaximaList;
|
||||
MaximaList m_Maxima;
|
||||
TEdge *m_SortedEdges;
|
||||
bool m_ExecuteLocked;
|
||||
PolyFillType m_ClipFillType;
|
||||
PolyFillType m_SubjFillType;
|
||||
bool m_ReverseOutput;
|
||||
bool m_UsingPolyTree;
|
||||
bool m_StrictSimple;
|
||||
#ifdef use_xyz
|
||||
ZFillCallback m_ZFill; //custom callback
|
||||
#endif
|
||||
void SetWindingCount(TEdge& edge);
|
||||
bool IsEvenOddFillType(const TEdge& edge) const;
|
||||
bool IsEvenOddAltFillType(const TEdge& edge) const;
|
||||
void InsertLocalMinimaIntoAEL(const cInt botY);
|
||||
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
|
||||
void AddEdgeToSEL(TEdge *edge);
|
||||
bool PopEdgeFromSEL(TEdge *&edge);
|
||||
void CopyAELToSEL();
|
||||
void DeleteFromSEL(TEdge *e);
|
||||
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
|
||||
bool IsContributing(const TEdge& edge) const;
|
||||
bool IsTopHorz(const cInt XPos);
|
||||
void DoMaxima(TEdge *e);
|
||||
void ProcessHorizontals();
|
||||
void ProcessHorizontal(TEdge *horzEdge);
|
||||
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutRec* GetOutRec(int idx);
|
||||
void AppendPolygon(TEdge *e1, TEdge *e2);
|
||||
void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
|
||||
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
|
||||
OutPt* GetLastOutPt(TEdge *e);
|
||||
bool ProcessIntersections(const cInt topY);
|
||||
void BuildIntersectList(const cInt topY);
|
||||
void ProcessIntersectList();
|
||||
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
||||
void BuildResult(Paths& polys);
|
||||
void BuildResult2(PolyTree& polytree);
|
||||
void SetHoleState(TEdge *e, OutRec *outrec);
|
||||
void DisposeIntersectNodes();
|
||||
bool FixupIntersectionOrder();
|
||||
void FixupOutPolygon(OutRec &outrec);
|
||||
void FixupOutPolyline(OutRec &outrec);
|
||||
bool IsHole(TEdge *e);
|
||||
bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
|
||||
void FixHoleLinkage(OutRec &outrec);
|
||||
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
|
||||
void ClearJoins();
|
||||
void ClearGhostJoins();
|
||||
void AddGhostJoin(OutPt *op, const IntPoint offPt);
|
||||
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
||||
void JoinCommonEdges();
|
||||
void DoSimplePolygons();
|
||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
||||
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
#ifdef use_xyz
|
||||
void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
|
||||
#endif
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ClipperOffset
|
||||
{
|
||||
public:
|
||||
ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
|
||||
~ClipperOffset();
|
||||
void AddPath(const Path& path, JoinType joinType, EndType endType);
|
||||
void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
|
||||
void Execute(Paths& solution, double delta);
|
||||
void Execute(PolyTree& solution, double delta);
|
||||
void Clear();
|
||||
double MiterLimit;
|
||||
double ArcTolerance;
|
||||
private:
|
||||
Paths m_destPolys;
|
||||
Path m_srcPoly;
|
||||
Path m_destPoly;
|
||||
std::vector<DoublePoint> m_normals;
|
||||
double m_delta, m_sinA, m_sin, m_cos;
|
||||
double m_miterLim, m_StepsPerRad;
|
||||
IntPoint m_lowest;
|
||||
PolyNode m_polyNodes;
|
||||
|
||||
void FixOrientations();
|
||||
void DoOffset(double delta);
|
||||
void OffsetPoint(int j, int& k, JoinType jointype);
|
||||
void DoSquare(int j, int k);
|
||||
void DoMiter(int j, int k, double r);
|
||||
void DoRound(int j, int k);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class clipperException : public std::exception
|
||||
{
|
||||
public:
|
||||
clipperException(const char* description): m_descr(description) {}
|
||||
virtual ~clipperException() throw() {}
|
||||
virtual const char* what() const throw() {return m_descr.c_str();}
|
||||
private:
|
||||
std::string m_descr;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} //ClipperLib namespace
|
||||
|
||||
#endif //clipper_hpp
|
||||
|
||||
|
||||
44
3rdparty/include/OcrLiteOnnx/getopt.h
vendored
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* getopt - POSIX like getopt for Windows console Application
|
||||
*
|
||||
* win-c - Windows Console Library
|
||||
* Copyright (c) 2015 Koji Takami
|
||||
* Released under the MIT license
|
||||
* https://github.com/takamin/win-c/blob/master/LICENSE
|
||||
*/
|
||||
#ifndef _GETOPT_H_
|
||||
#define _GETOPT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
int getopt(int argc, char *const argv[],
|
||||
const char *optstring);
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
struct option {
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
int getopt_long(int argc, char *const argv[],
|
||||
const char *optstring,
|
||||
const struct option *longopts, int *longindex);
|
||||
/****************************************************************************
|
||||
int getopt_long_only(int argc, char* const argv[],
|
||||
const char* optstring,
|
||||
const struct option* longopts, int* longindex);
|
||||
****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GETOPT_H_
|
||||
54
3rdparty/include/OcrLiteOnnx/main.h
vendored
@@ -1,54 +0,0 @@
|
||||
#ifndef __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{"models", required_argument, NULL, 'd'},
|
||||
{"det", required_argument, NULL, '1'},
|
||||
{"cls", required_argument, NULL, '2'},
|
||||
{"rec", required_argument, NULL, '3'},
|
||||
{"keys", required_argument, NULL, '4'},
|
||||
{"image", required_argument, NULL, 'i'},
|
||||
{"numThread", required_argument, NULL, 't'},
|
||||
{"padding", required_argument, NULL, 'p'},
|
||||
{"maxSideLen", required_argument, NULL, 's'},
|
||||
{"boxScoreThresh", required_argument, NULL, 'b'},
|
||||
{"boxThresh", required_argument, NULL, 'o'},
|
||||
{"unClipRatio", required_argument, NULL, 'u'},
|
||||
{"doAngle", required_argument, NULL, 'a'},
|
||||
{"mostAngle", required_argument, NULL, 'A'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"loopCount", required_argument, NULL, 'l'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
const char *usageMsg = "(-d --models) (-1 --det) (-2 --cls) (-3 --rec) (-4 --keys) (-i --image)\n"\
|
||||
"[-t --numThread] [-p --padding] [-s --maxSideLen]\n" \
|
||||
"[-b --boxScoreThresh] [-o --boxThresh] [-u --unClipRatio]\n" \
|
||||
"[-a --noAngle] [-A --mostAngle]\n\n";
|
||||
|
||||
const char *requiredMsg = "-d --models: models directory.\n" \
|
||||
"-1 --det: model file name of det.\n" \
|
||||
"-2 --cls: model file name of cls.\n" \
|
||||
"-3 --rec: model file name of rec.\n" \
|
||||
"-4 --keys: keys file name.\n" \
|
||||
"-i --image: path of target image.\n\n";
|
||||
|
||||
const char *optionalMsg = "-t --numThread: value of numThread(int), default: 4\n" \
|
||||
"-p --padding: value of padding(int), default: 50\n" \
|
||||
"-s --maxSideLen: Long side of picture for resize(int), default: 1024\n" \
|
||||
"-b --boxScoreThresh: value of boxScoreThresh(float), default: 0.6\n" \
|
||||
"-o --boxThresh: value of boxThresh(float), default: 0.3\n" \
|
||||
"-u --unClipRatio: value of unClipRatio(float), default: 2.0\n" \
|
||||
"-a --doAngle: Enable(1)/Disable(0) Angle Net, default: Enable\n" \
|
||||
"-A --mostAngle: Enable(1)/Disable(0) Most Possible AngleIndex, default: Enable\n\n";
|
||||
|
||||
const char *otherMsg = "-v --version: show version\n" \
|
||||
"-h --help: print this help\n\n";
|
||||
|
||||
const char *example1Msg = "Example1: %s --models models --det det.onnx --cls cls.onnx --rec rec.onnx --keys keys.txt --image 1.jpg\n";
|
||||
const char *example2Msg = "Example2: %s -d models -1 det.onnx -2 cls.onnx -3 rec.onnx -4 keys.txt -i 1.jpg -t 4 -p 50 -s 0 -b 0.6 -o 0.3 -u 2.0 -a 1 -A 1\n";
|
||||
|
||||
#endif //__MAIN_H__
|
||||
6
3rdparty/include/OcrLiteOnnx/version.h
vendored
@@ -1,6 +0,0 @@
|
||||
#ifndef __OCR_VERSION_H__
|
||||
#define __OCR_VERSION_H__
|
||||
|
||||
#define VERSION "1.5.1.20210128"
|
||||
|
||||
#endif //__OCR_VERSION_H__
|
||||
37
3rdparty/include/PaddleOCR/exports.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
// The way how the function is called
|
||||
#if !defined(OCR_CALL)
|
||||
#if defined(_WIN32)
|
||||
#define OCR_CALL __stdcall
|
||||
#else
|
||||
#define OCR_CALL
|
||||
#endif /* _WIN32 */
|
||||
#endif /* OCR_CALL */
|
||||
|
||||
// The function exported symbols
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#define OCR_IMPORT __declspec(dllimport)
|
||||
#define OCR_EXPORT __declspec(dllexport)
|
||||
#define OCR_LOCAL
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define OCR_IMPORT __attribute__ ((visibility ("default")))
|
||||
#define OCR_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define OCR_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define OCR_IMPORT
|
||||
#define OCR_EXPORT
|
||||
#define OCR_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef OCR_EXPORTS // defined if we are building the DLL (instead of using it)
|
||||
#define OCRAPI_PORT OCR_EXPORT
|
||||
#else
|
||||
#define OCRAPI_PORT OCR_IMPORT
|
||||
#endif // OCR_EXPORTS
|
||||
|
||||
#define OCRAPI OCRAPI_PORT OCR_CALL
|
||||
|
||||
#define OCRLOCAL OCR_LOCAL OCR_CALL
|
||||
39
3rdparty/include/PaddleOCR/paddle_ocr.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
struct paddle_ocr_t;
|
||||
typedef int OCR_ERROR;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
#define OCR_SUCCESS 0
|
||||
#define OCR_FAILURE 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
OCRAPI_PORT paddle_ocr_t* OCR_CALL PaddleOcrCreate(
|
||||
const char* det_model_dir, const char* rec_model_dir,
|
||||
const char* char_list_file, const char* cls_model_dir);
|
||||
|
||||
void OCRAPI PaddleOcrDestroy(paddle_ocr_t* ocr_ptr);
|
||||
|
||||
OCR_ERROR OCRAPI PaddleOcrDet(
|
||||
paddle_ocr_t* ocr_ptr, const uint8_t* encode_buf, size_t encode_buf_size,
|
||||
int* out_boxes, size_t* out_boxes_size,
|
||||
double* out_times, size_t* out_times_size);
|
||||
|
||||
OCR_ERROR OCRAPI PaddleOcrRec(
|
||||
paddle_ocr_t* ocr_ptr, const uint8_t* encode_buf, size_t encode_buf_size,
|
||||
char** out_strs, float* out_scores, size_t* out_size,
|
||||
double* out_times, size_t* out_times_size);
|
||||
|
||||
OCR_ERROR OCRAPI PaddleOcrSystem(
|
||||
paddle_ocr_t* ocr_ptr, const uint8_t* encode_buf, size_t encode_buf_size, bool with_cls,
|
||||
int* out_boxes, char** out_strs, float* out_scores, size_t* out_size,
|
||||
double* out_times, size_t* out_times_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
310
3rdparty/include/cpp-base64/base64.hpp
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
base64.cpp and base64.h
|
||||
|
||||
base64 encoding and decoding with C++.
|
||||
More information at
|
||||
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
|
||||
|
||||
Version: 2.rc.08 (release candidate)
|
||||
|
||||
Copyright (C) 2004-2017, 2020, 2021 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
|
||||
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
|
||||
|
||||
#include <string>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#include <string_view>
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
std::string base64_encode (std::string const& s, bool url = false);
|
||||
std::string base64_encode_pem (std::string const& s);
|
||||
std::string base64_encode_mime(std::string const& s);
|
||||
|
||||
std::string base64_decode(std::string const& s, bool remove_linebreaks = false);
|
||||
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
//
|
||||
// Interface with std::string_view rather than const std::string&
|
||||
// Requires C++17
|
||||
// Provided by Yannic Bonenberger (https://github.com/Yannic)
|
||||
//
|
||||
std::string base64_encode (std::string_view s, bool url = false);
|
||||
std::string base64_encode_pem (std::string_view s);
|
||||
std::string base64_encode_mime(std::string_view s);
|
||||
|
||||
std::string base64_decode(std::string_view s, bool remove_linebreaks = false);
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
//
|
||||
// Depending on the url parameter in base64_chars, one of
|
||||
// two sets of base64 characters needs to be chosen.
|
||||
// They differ in their last two characters.
|
||||
//
|
||||
static const char* base64_chars[2] = {
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"+/",
|
||||
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"-_"};
|
||||
|
||||
static unsigned int pos_of_char(const unsigned char chr) {
|
||||
//
|
||||
// Return the position of chr within base64_encode()
|
||||
//
|
||||
|
||||
if (chr >= 'A' && chr <= 'Z') return chr - 'A';
|
||||
else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1;
|
||||
else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
|
||||
else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
|
||||
else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_'
|
||||
else
|
||||
//
|
||||
// 2020-10-23: Throw std::exception rather than const char*
|
||||
//(Pablo Martin-Gomez, https://github.com/Bouska)
|
||||
//
|
||||
throw std::runtime_error("Input is not valid base64-encoded data.");
|
||||
}
|
||||
|
||||
static std::string insert_linebreaks(std::string str, size_t distance) {
|
||||
//
|
||||
// Provided by https://github.com/JomaCorpFX, adapted by me.
|
||||
//
|
||||
if (!str.length()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
size_t pos = distance;
|
||||
|
||||
while (pos < str.size()) {
|
||||
str.insert(pos, "\n");
|
||||
pos += distance + 1;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename String, unsigned int line_length>
|
||||
static std::string encode_with_line_breaks(String s) {
|
||||
return insert_linebreaks(base64_encode(s, false), line_length);
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
static std::string encode_pem(String s) {
|
||||
return encode_with_line_breaks<String, 64>(s);
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
static std::string encode_mime(String s) {
|
||||
return encode_with_line_breaks<String, 76>(s);
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
static std::string encode(String s, bool url) {
|
||||
return base64_encode(reinterpret_cast<const unsigned char*>(s.data()), s.length(), url);
|
||||
}
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) {
|
||||
|
||||
size_t len_encoded = (in_len +2) / 3 * 4;
|
||||
|
||||
unsigned char trailing_char = url ? '.' : '=';
|
||||
|
||||
//
|
||||
// Choose set of base64 characters. They differ
|
||||
// for the last two positions, depending on the url
|
||||
// parameter.
|
||||
// A bool (as is the parameter url) is guaranteed
|
||||
// to evaluate to either 0 or 1 in C++ therefore,
|
||||
// the correct character set is chosen by subscripting
|
||||
// base64_chars with url.
|
||||
//
|
||||
const char* base64_chars_ = base64_chars[url];
|
||||
|
||||
std::string ret;
|
||||
ret.reserve(len_encoded);
|
||||
|
||||
unsigned int pos = 0;
|
||||
|
||||
while (pos < in_len) {
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);
|
||||
|
||||
if (pos+1 < in_len) {
|
||||
ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);
|
||||
|
||||
if (pos+2 < in_len) {
|
||||
ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
|
||||
ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]);
|
||||
}
|
||||
else {
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
|
||||
ret.push_back(trailing_char);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
|
||||
ret.push_back(trailing_char);
|
||||
ret.push_back(trailing_char);
|
||||
}
|
||||
|
||||
pos += 3;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
static std::string decode(String encoded_string, bool remove_linebreaks) {
|
||||
//
|
||||
// decode(…) is templated so that it can be used with String = const std::string&
|
||||
// or std::string_view (requires at least C++17)
|
||||
//
|
||||
|
||||
if (encoded_string.empty()) return std::string();
|
||||
|
||||
if (remove_linebreaks) {
|
||||
|
||||
std::string copy(encoded_string);
|
||||
|
||||
copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());
|
||||
|
||||
return base64_decode(copy, false);
|
||||
}
|
||||
|
||||
size_t length_of_string = encoded_string.length();
|
||||
size_t pos = 0;
|
||||
|
||||
//
|
||||
// The approximate length (bytes) of the decoded string might be one or
|
||||
// two bytes smaller, depending on the amount of trailing equal signs
|
||||
// in the encoded string. This approximation is needed to reserve
|
||||
// enough space in the string to be returned.
|
||||
//
|
||||
size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
|
||||
std::string ret;
|
||||
ret.reserve(approx_length_of_decoded_string);
|
||||
|
||||
while (pos < length_of_string) {
|
||||
//
|
||||
// Iterate over encoded input string in chunks. The size of all
|
||||
// chunks except the last one is 4 bytes.
|
||||
//
|
||||
// The last chunk might be padded with equal signs or dots
|
||||
// in order to make it 4 bytes in size as well, but this
|
||||
// is not required as per RFC 2045.
|
||||
//
|
||||
// All chunks except the last one produce three output bytes.
|
||||
//
|
||||
// The last chunk produces at least one and up to three bytes.
|
||||
//
|
||||
|
||||
size_t pos_of_char_1 = pos_of_char(encoded_string[pos+1] );
|
||||
|
||||
//
|
||||
// Emit the first output byte that is produced in each chunk:
|
||||
//
|
||||
ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char(encoded_string[pos+0]) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4)));
|
||||
|
||||
if ( ( pos + 2 < length_of_string ) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045)
|
||||
encoded_string[pos+2] != '=' &&
|
||||
encoded_string[pos+2] != '.' // accept URL-safe base 64 strings, too, so check for '.' also.
|
||||
)
|
||||
{
|
||||
//
|
||||
// Emit a chunk's second byte (which might not be produced in the last chunk).
|
||||
//
|
||||
unsigned int pos_of_char_2 = pos_of_char(encoded_string[pos+2] );
|
||||
ret.push_back(static_cast<std::string::value_type>( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2)));
|
||||
|
||||
if ( ( pos + 3 < length_of_string ) &&
|
||||
encoded_string[pos+3] != '=' &&
|
||||
encoded_string[pos+3] != '.'
|
||||
)
|
||||
{
|
||||
//
|
||||
// Emit a chunk's third byte (which might not be produced in the last chunk).
|
||||
//
|
||||
ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string[pos+3]) ));
|
||||
}
|
||||
}
|
||||
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string const& s, bool remove_linebreaks) {
|
||||
return decode(s, remove_linebreaks);
|
||||
}
|
||||
|
||||
std::string base64_encode(std::string const& s, bool url) {
|
||||
return encode(s, url);
|
||||
}
|
||||
|
||||
std::string base64_encode_pem (std::string const& s) {
|
||||
return encode_pem(s);
|
||||
}
|
||||
|
||||
std::string base64_encode_mime(std::string const& s) {
|
||||
return encode_mime(s);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
//
|
||||
// Interface with std::string_view rather than const std::string&
|
||||
// Requires C++17
|
||||
// Provided by Yannic Bonenberger (https://github.com/Yannic)
|
||||
//
|
||||
|
||||
std::string base64_encode(std::string_view s, bool url) {
|
||||
return encode(s, url);
|
||||
}
|
||||
|
||||
std::string base64_encode_pem(std::string_view s) {
|
||||
return encode_pem(s);
|
||||
}
|
||||
|
||||
std::string base64_encode_mime(std::string_view s) {
|
||||
return encode_mime(s);
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string_view s, bool remove_linebreaks) {
|
||||
return decode(s, remove_linebreaks);
|
||||
}
|
||||
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */
|
||||
BIN
3rdparty/lib/OcrLiteOnnx.lib
vendored
BIN
3rdparty/lib/ppocr.lib
vendored
Normal file
BIN
3rdparty/resource/OcrLiteOnnx/models/angle_net.onnx
vendored
BIN
3rdparty/resource/OcrLiteOnnx/models/dbnet.onnx
vendored
BIN
3rdparty/resource/PaddleOCR/det/inference.pdiparams
vendored
Normal file
BIN
3rdparty/resource/PaddleOCR/det/inference.pdmodel
vendored
Normal file
1
3rdparty/resource/PaddleOCR/det/version.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ch_ppocr_mobile_v2.0_det_prune_infer
|
||||
BIN
3rdparty/resource/PaddleOCR/rec/inference.pdiparams
vendored
Normal file
BIN
3rdparty/resource/PaddleOCR/rec/inference.pdmodel
vendored
Normal file
1
3rdparty/resource/PaddleOCR/rec/version.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ch_ppocr_mobile_v2.0_rec_slim_infer
|
||||
87382
3rdparty/resource/penguin-stats-recognize/json/stages.json
vendored
24
CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(MeoAssistantArknights)
|
||||
|
||||
include_directories(include 3rdparty/include)
|
||||
aux_source_directory(src/MeoAssistant SRC)
|
||||
add_definitions(-DASST_DLL_EXPORTS)
|
||||
|
||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/MP>")
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/MP>")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_library(MeoAssistant SHARED ${SRC})
|
||||
|
||||
find_library(Opencv_LIB NAMES opencv_world453 PATHS 3rdparty/lib)
|
||||
find_library(PaddleOCR_LIB NAMES ppocr PATHS 3rdparty/lib)
|
||||
find_library(Penguin_LIB NAMES penguin-stats-recognize PATHS 3rdparty/lib)
|
||||
find_library(MeoJson_LIB NAMES libmeojson PATHS 3rdparty/lib)
|
||||
|
||||
target_link_libraries(MeoAssistant ${Opencv_LIB} ${PaddleOCR_LIB} ${Penguin_LIB} ${MeoJson_LIB})
|
||||
@@ -1,69 +1,71 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31912.275
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeoAssistance", "src\MeoAssistance\MeoAssistance.vcxproj", "{362D1E30-F5AE-4279-9985-65C27B3BA300}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{6C4B8D52-51D1-45F8-AAEC-808035443FD6}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCaller", "tools\TestCaller\TestCaller.vcxproj", "{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeoAsstGui", "src\MeoAsstGui\MeoAsstGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TransparentImageCvt", "tools\TransparentImageCvt\TransparentImageCvt.vcxproj", "{093A3174-A27E-4D23-B64E-16F9448AD5AC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
RelWithDebInfo|x64 = RelWithDebInfo|x64
|
||||
RelWithDebInfo|x86 = RelWithDebInfo|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.ActiveCfg = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.Build.0 = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x86.ActiveCfg = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x86.Build.0 = Release|Win32
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4F2C0E4B-4FE9-47C6-A878-6BD2FAD8B9B2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31912.275
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{6C4B8D52-51D1-45F8-AAEC-808035443FD6}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCaller", "tools\TestCaller\TestCaller.vcxproj", "{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeoAsstGui", "src\MeoAsstGui\MeoAsstGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TransparentImageCvt", "tools\TransparentImageCvt\TransparentImageCvt.vcxproj", "{093A3174-A27E-4D23-B64E-16F9448AD5AC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeoAssistant", "src\MeoAssistant\MeoAssistant.vcxproj", "{362D1E30-F5AE-4279-9985-65C27B3BA300}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
RelWithDebInfo|x64 = RelWithDebInfo|x64
|
||||
RelWithDebInfo|x86 = RelWithDebInfo|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.ActiveCfg = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.Build.0 = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x86.ActiveCfg = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x86.Build.0 = Release|Win32
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x86.Build.0 = Release|Win32
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.Build.0 = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4F2C0E4B-4FE9-47C6-A878-6BD2FAD8B9B2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
216
README.md
@@ -1,5 +1,8 @@
|
||||
# MeoAssistance
|
||||
<div align="center">
|
||||
|
||||
# MeoAssistantArknights
|
||||
|
||||
<br>
|
||||
<div>
|
||||
<img alt="C++" src="https://img.shields.io/badge/c++-17-%2300599C?logo=cplusplus">
|
||||
<img alt="VS" src="https://img.shields.io/badge/VisualStudio-19-%235C2D91?logo=visualstudio">
|
||||
@@ -8,18 +11,26 @@
|
||||
<img alt="platform" src="https://img.shields.io/badge/platform-Windows%2064bit-%230078D6?logo=windows">
|
||||
</div>
|
||||
<div>
|
||||
<img alt="license" src="https://img.shields.io/github/license/MistEO/MeoAssistance-Arknights">
|
||||
<img alt="commit" src="https://img.shields.io/github/commit-activity/m/MistEO/MeoAssistance-Arknights?color=%23ff69b4">
|
||||
<img alt="stars" src="https://img.shields.io/github/stars/MistEO/MeoAssistance-Arknights?style=social">
|
||||
<img alt="license" src="https://img.shields.io/github/license/MistEO/MeoAssistantArknights">
|
||||
<img alt="commit" src="https://img.shields.io/github/commit-activity/m/MistEO/MeoAssistantArknights?color=%23ff69b4">
|
||||
<img alt="stars" src="https://img.shields.io/github/stars/MistEO/MeoAssistantArknights?style=social">
|
||||
</div>
|
||||
<br>
|
||||
|
||||
A game assistance for Arknights
|
||||
A Game Assistant for Arknights
|
||||
|
||||
一款明日方舟的游戏助手,自动刷理智、智能基建换班、公招识别等,一键完成所有日常,全自动长草!!!
|
||||
一款明日方舟的游戏小助手,一键完成所有日常,全自动长草!!!
|
||||
|
||||
纯图像识别,非内存挂,全图形化界面,兼容模拟器和安卓设备,开罐即食,绝赞开发中!✿✿ヽ(°▽°)ノ✿
|
||||
<br>
|
||||
纯图像识别,非内存挂!全图形化界面,开罐即食!
|
||||
|
||||
并提供 [Python接口](src/Python/interface.py) 供自行DIY~ 绝赞更新中!✿✿ヽ(°▽°)ノ✿
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## 功能介绍
|
||||
|
||||
废话不多说,看图!
|
||||
|
||||

|
||||

|
||||
@@ -27,119 +38,85 @@ A game assistance for Arknights
|
||||
|
||||
## 下载地址
|
||||
|
||||
[稳定版](https://github.com/MistEO/MeoAssistance/releases/latest)
|
||||
[测试版](https://github.com/MistEO/MeoAssistance/releases)
|
||||
[稳定版](https://github.com/MistEO/MeoAssistantArknights/releases/latest)
|
||||
[测试版](https://github.com/MistEO/MeoAssistantArknights/releases)
|
||||
|
||||
## 功能介绍
|
||||
## 模拟器支持
|
||||
|
||||
- **全自动基建换班(新功能!)**
|
||||
- 自动识别干员技能,自动计算设施内最优解并换班!
|
||||
- 支持如`巫恋组`、`温蒂组`等等所有单设施内组合
|
||||
- 自动识别干员心情并入驻宿舍
|
||||
- 可设置自动使用无人机给制造站/贸易站加速
|
||||
- 可识别赤金、经验书、搓玉,分别使用不同的干员组合
|
||||
- `迷迭香`等跨设施体系正在开发中!
|
||||
- 自动刷理智
|
||||
- 支持刷完自动上传[企鹅物流数据统计](https://penguin-stats.cn/)
|
||||
- 支持企鹅物流自定义ID
|
||||
- 界面支持统计掉落数量
|
||||
- 可设置是否吃完理智药及数量
|
||||
- 可设置是否吃石头及数量
|
||||
- 可设置刷的次数(用来刷剿灭啥的)
|
||||
- 可设置刷完自动关机
|
||||
- 支持剿灭模式
|
||||
- 支持打完升级了的情况
|
||||
- 支持代理失败的情况,会自动放弃本次行动
|
||||
- 支持刷完自动截图
|
||||
- 支持掉线后重连,继续刷上次的图
|
||||
- 支持凌晨4点更新后重连,继续刷上次的图
|
||||
- 公开招募识别
|
||||
- 自动识别当前招募页所有Tags
|
||||
- 自动计算可能出的干员组合并显示
|
||||
- 自动帮你点击最优解Tags
|
||||
- 自动帮你点击时间9小时
|
||||
- 出5、6星干员弹窗提示
|
||||
- 最新版本已支持2.5新增的`阿`等干员
|
||||
- 自动访问好友
|
||||
- 访问完了还会贴心的帮你点进信用商店~
|
||||
- 可设置访问完自动买信用商店的材料
|
||||
- 其他优势
|
||||
- 所有点击操作,都是点击按钮内随机位置,并模拟泊松分布(按钮偏中间位置点的概率大,越往旁边点到的概率越小)
|
||||
- 刷理智及访问好友的点击操作,支持设置随机延时,没有封号风险~
|
||||
- 底层算法纯C++开发,并设计了多重的缓存技术,最大限度降低CPU和内存占用
|
||||
- 模拟器窗口可以被遮挡、可以最小化、甚至可以老板键隐藏!即使全屏看视频、玩游戏,也完全不影响软件运行
|
||||
- 软件支持自动更新✿✿ヽ(°▽°)ノ✿
|
||||
- 支持多款主流模拟器
|
||||
- 兼容安卓手机(USB调试、无线调试)
|
||||
- 兼容非16:9分辨率:包括宽屏、方屏,也兼容在游戏设置中的异形屏适配(基建换班功能除外,正在适配中)。但仍推荐使用16:9分辨率
|
||||
- 自适应分辨率及屏幕缩放
|
||||
- 未来更多功能见[Todo](#Todo)
|
||||
|
||||
### 模拟器支持
|
||||
|
||||
#### 蓝叠模拟器
|
||||
### 蓝叠模拟器
|
||||
|
||||
完美支持。需要在模拟器`设置`-`引擎设置`中打开`允许ADB连接`
|
||||
|
||||
#### 蓝叠模拟器国际版
|
||||
### 蓝叠模拟器国际版
|
||||
|
||||
完美支持。需要在模拟器`设定`-`进阶`中打开`Android调试桥`
|
||||
|
||||
#### 蓝叠模拟器Hyper-V版本
|
||||
|
||||
支持。
|
||||
|
||||
1. 需要在模拟器`设定`-`进阶`中打开`Android调试桥`
|
||||
2. 需要在软件`设置`-`连接设置`中添加蓝叠安装目录下`bluestacks.conf`文件的完整路径
|
||||
|
||||
#### 夜神模拟器
|
||||
### 夜神模拟器
|
||||
|
||||
完美支持
|
||||
|
||||
#### MuMu模拟器
|
||||
### MuMu模拟器
|
||||
|
||||
完美支持
|
||||
|
||||
#### 雷电模拟器
|
||||
### 雷电模拟器
|
||||
|
||||
勉强支持,雷电总有莫名其妙的问题,可以试试看,不保证能用(
|
||||
勉强支持。雷电总有莫名其妙的问题,可以试试看,不保证能用(
|
||||
|
||||
#### 逍遥模拟器
|
||||
### 逍遥模拟器
|
||||
|
||||
支持
|
||||
|
||||
#### 腾讯手游助手
|
||||
### 腾讯手游助手
|
||||
|
||||
不支持,新版本的腾讯好像也是自研引擎了,没开放ADB端口。但是测试是能响应Win32 Api的,有需求再做
|
||||
不支持。新版本的腾讯好像也是自研引擎了,没开放ADB端口;但是测试是能响应Win32 Api的,有需求再做
|
||||
|
||||
#### MuMu手游助手(星云引擎)
|
||||
### MuMu手游助手(星云引擎)
|
||||
|
||||
不支持,星云引擎这个版本不支持adb控制,甚至不响应Win32 Api鼠标消息,无解_(:з」∠)_
|
||||
不支持。星云引擎这个版本不支持adb控制,甚至不响应Win32 Api鼠标消息,无解_(:з」∠)_
|
||||
|
||||
#### 其他模拟器
|
||||
### Win11 WSA
|
||||
|
||||
若有其他需要,欢迎给我提[ISSUE](https://github.com/MistEO/MeoAssistance/issues),会根据情况尽量适配~
|
||||
不支持,WSA 目前没有实现 AOSP screencap 需要的接口,无法进行截图。等微软支持后会尝试适配
|
||||
|
||||
#### 安卓手机/平板
|
||||
### 蓝叠模拟器Hyper-V版本
|
||||
|
||||
部分功能支持,正在开发中……
|
||||
需要下载[谷歌官方ADB](https://dl.google.com/android/repository/platform-tools-latest-windows.zip),将`platform-tools`文件夹解压到`MeoAsstGui.exe`的同级目录
|
||||
支持
|
||||
|
||||
1. 在模拟器`设定`-`进阶`中打开`Android调试桥`
|
||||
2. 下载 [ADB](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将`platform-tools`文件夹解压到`MeoAsstGui.exe`的同级目录
|
||||
3. 在软件`设置`-`连接设置`中填写蓝叠安装目录下`bluestacks.conf`文件的完整路径
|
||||
|
||||
### 自定义连接
|
||||
|
||||
- 下载 [ADB](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将`platform-tools`文件夹解压到`MeoAsstGui.exe`的同级目录
|
||||
- 进入软件`设置`-`连接设置`,填写自定义地址(需要填写IP+端口,例如`127.0.0.1:5555`)
|
||||
- **注意 :** 若是使用手机,在非`16:9`分辨率下,部分功能不稳定(但也凑合能用),尤其是基建,几乎是不可用状态,正在进一步适配中。推荐使用`16:9`分辨率,经过的测试验证最多,也最稳定。
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 基本说明
|
||||
|
||||
1. 根据上面模拟器支持情况,进行对应的`ADB`相关操作
|
||||
1. 根据上面模拟器支持情况,进行对应的操作
|
||||
2. 解压压缩包,到**没有中文或特殊符号**的文件夹路径
|
||||
3. 第一次运行软件,**请使用管理员权限**打开`MeoAsstGui.exe`。运行过一次后,后续不再需要管理员权限(之后的版本会尝试完全去掉管理员权限)
|
||||
3. 第一次运行软件,**请使用管理员权限**打开`MeoAsstGui.exe`。运行过一次后,后续不再需要管理员权限
|
||||
4. 开始运行后,所有设置均不可再修改
|
||||
5. 运行期间,模拟器窗口可以最小化,全屏玩游戏、看视频等,完全不影响
|
||||
|
||||
目前非16:9分辨率下,刷理智、访问好友、公招识别已初步可用,基建功能暂不可用,后期将逐步优化。但仍推荐使用16:9分辨率,经过的测试验证最多,也最稳定。
|
||||
### 刷理智
|
||||
|
||||
### Tips
|
||||
|
||||
若明日方舟处于**蓝色开始按钮**界面,则会刷当前关卡。否则会前往上一次作战的关卡!(自动选关功能正在开发中
|
||||
- 若游戏处于**蓝色开始按钮**界面,则会刷当前关卡。否则会前往上次作战的关卡!
|
||||
- 主界面上的`吃理智`、`吃石头`、`指定次数`三个选项为短路开关,即三个选项中的任一条件达到,均会视为任务完成,停止刷理智。
|
||||
- 举例1:设置`吃理智药`:`999`、`吃石头`:`10`、`指定次数`:`1`。则在刷完**一次**后,由于满足了`指定次数`:`1`的条件,视为任务完成,停止刷理智。
|
||||
- 举例2:不勾选`吃理智药`、不勾选`吃石头`,设置`指定次数`:`100`。则在当前可用理智全部刷完后(可能只刷了几次),由于满足了`不吃理智药`、`不吃石头`的条件,视为任务完成,停止刷理智。
|
||||
- 其他优势
|
||||
- 支持刷完自动上传 [企鹅物流数据统计](https://penguin-stats.cn/)
|
||||
- 支持企鹅物流自定义ID
|
||||
- 支持统计掉落数量
|
||||
- 支持剿灭模式
|
||||
- 支持打完升级了的情况
|
||||
- 支持代理失败的情况,会自动放弃本次行动
|
||||
- 支持掉线后重连,继续刷上次的图
|
||||
- 支持凌晨4点更新后重连,继续刷上次的图
|
||||
|
||||
### 基建换班
|
||||
|
||||
@@ -149,37 +126,54 @@ A game assistance for Arknights
|
||||
|
||||
#### 宿舍入驻心情阈值
|
||||
|
||||
计算心情进度条的百分比;心情小于该阈值的干员,不会再去上班,直接进驻宿舍
|
||||
识别心情进度条的百分比;心情小于该阈值的干员,不会再去上班,直接进驻宿舍
|
||||
|
||||
#### 特殊说明
|
||||
|
||||
- 基建换班目前均为单设施最优解,但非跨设施的全局最优解,例如`迷迭香`这类多个设施间联动的体系,都是不支持的
|
||||
- 基建换班目前均为单设施最优解,但非跨设施的全局最优解。例如:`巫恋 龙舌兰`、`红云 稀音`等这类单设施内的组合,都是可以正常识别并使用的;`迷迭香`、`红松骑士团`这类多个设施间联动的体系,目前都是不支持的
|
||||
- 会客室仅缺一个线索时,会选择对应流派的干员;否则会选择通用干员
|
||||
- 会客室暂不支持送出线索,当线索满时可能会处理异常。建议自动换班完成后自己再去看下会客室的情况
|
||||
- 控制中枢策略太过复杂,目前只考虑`阿米娅`、`诗怀雅`、`凯尔希`、`彩虹小队`及其他心情+0.05的干员,后续逐步优化
|
||||
|
||||
### 信用商店随缘买
|
||||
|
||||
从左到右依次买,但不会买`碳`和`家具零件`。有需要的同学可自行修改`resource\tasks.json`中`CreditShop-NotToBuy`.`text`字段,自定义不买的物品。后续版本会尝试开放界面选项
|
||||
|
||||
### 公开招募识别
|
||||
|
||||
**请注意:公招识别和自动公招是两个独立的功能!**
|
||||
- 公招识别和自动公招是两个独立的功能!
|
||||
- 公招识别需要手动打开有公招Tag选择的界面再使用
|
||||
|
||||
1. 明日方舟打开公开招募,有Tag选择的界面
|
||||
2. 软件勾选你需要的选项,点击"开始识别"
|
||||
3. 请检查识别结果是否正确,自行判断是否确定开始招募
|
||||
### 其他乱七八糟的说明
|
||||
|
||||
### 连接自定义模拟器端口,或安卓手机/平板
|
||||
- 公招出5、6星会有弹窗提示
|
||||
- 主界面上要执行的任务,是可以拖动改变顺序的。同样设置中基建换班的顺序,也是可以拖动改变的
|
||||
- 活动关卡掉落识别到的`未知材料`,一般就是活动商店的票据
|
||||
- 新的活动关卡刚上线的时候可能无法正常识别,一般一两天内软件会自动OTA更新资源,更新后即可正常识别
|
||||
- 所有点击操作,都是点击按钮内随机位置,并模拟泊松分布(按钮偏中间位置点的概率大,越往旁边点到的概率越小)
|
||||
- `resource\config.json`中有一些自定义选项,可以尝试根据自己的需要进行修改
|
||||
- 底层算法纯C++开发,并设计了多重的缓存技术,最大限度降低CPU和内存占用
|
||||
- 软件支持自动更新✿✿ヽ(°▽°)ノ✿ 推荐非杠精的同学使用测试版,一般来说更新快且bug少(什么MIUI (╯‵□′)╯︵┻━┻
|
||||
|
||||
1. 下载[ADB程序](https://dl.google.com/android/repository/platform-tools-latest-windows.zip),将`platform-tools`文件夹解压到`MeoAsstGui.exe`的同级目录
|
||||
2. 使用USB有线连接安卓手机和电脑
|
||||
3. 请在手机`设置`-`开发者选项`中打开`USB调试`、`USB调试(安全设置)`两个选项。具体操作方式不同品牌手机各不相同,请自行百度查询
|
||||
4. 请手动修改`resource\config.json`文件中:
|
||||
1. `options`.`connectType`字段值为`1`
|
||||
2. `emulator`.`Custom`.`adb`.`addresses`字段填写为要连接的地址,请注意这是个数组,会以此尝试所有的(若不填写,或`addresses`中所有的都没连上,则会使用`adb devices`自动查找)
|
||||
## 常见问题
|
||||
|
||||
目前非16:9分辨率下,刷理智、访问好友、公招识别已初步可用,基建功能暂不可用,后期将逐步优化。但仍推荐使用16:9分辨率,经过的测试验证最多,也最稳定。
|
||||
### 软件一打开就闪退
|
||||
|
||||
- 目前初步怀疑是运行库问题。可以尝试把 [Visual C++ Redistributable](https://docs.microsoft.com/sl-SI/cpp/windows/latest-supported-vc-redist?view=msvc-160)、[.NET Framework 4.8](https://dotnet.microsoft.com/download/dotnet-framework/net48) 都安装一下看看有没有效果
|
||||
- 若您有一定的开发能力,也可使用 [Python接口](src/Python/interface.py) 自行调用
|
||||
|
||||
### 连接错误/捕获模拟器窗口错误
|
||||
|
||||
- 方法1: 使用 [自定义连接](#自定义连接) 的方式连接模拟器
|
||||
- 方法2: 换模拟器,推荐 [蓝叠国际版](https://www.bluestacks.com/download.html)
|
||||
- 方法3: _根本解决方法_ 编辑`resource/config.json`,修改(最好是新增)模拟器窗口句柄名,并修改对应的adb设置。若您修改后可以提PR给我,我会感激不尽的_(:з」∠)_
|
||||
|
||||
###
|
||||
|
||||
## Todo
|
||||
|
||||
- [x] 任务队列功能
|
||||
- [ ] 常用关卡选关
|
||||
- [x] 常用关卡选关
|
||||
- [x] 自动收任务功能
|
||||
- [x] 基建智能换班功能
|
||||
- [x] 图形化界面
|
||||
@@ -196,7 +190,7 @@ A game assistance for Arknights
|
||||
- [x] `激进换班模式`
|
||||
- [ ] 自定义换班(手动修改配置文件)
|
||||
- [ ] 宿舍换班支持加速心情的干员识别
|
||||
- [ ] 贸易站无人机支持设置给经验书还是赤金
|
||||
- [x] 贸易站无人机支持设置给经验书还是赤金
|
||||
- [ ] 使用GPU进行识别的版本
|
||||
- [x] 企鹅物流汇报,自定义ID
|
||||
- [ ] 指定刷某种材料xx个
|
||||
@@ -206,7 +200,7 @@ A game assistance for Arknights
|
||||
- [x] 后台自动更新
|
||||
- [x] 忽略当前版本更新
|
||||
- [ ] 提供log接口,以及界面log
|
||||
- [ ] 更换OCR库,提高公开招募识别率
|
||||
- [x] 更换OCR库,提高公开招募识别率
|
||||
- [x] 终极目标!全自动长草机!!!
|
||||
|
||||
## 致谢
|
||||
@@ -214,13 +208,16 @@ A game assistance for Arknights
|
||||
### 开源库
|
||||
|
||||
- 图像识别库:[opencv](https://github.com/opencv/opencv.git)
|
||||
- 文字识别库:[chineseocr_lite](https://github.com/DayBreak-u/chineseocr_lite.git)
|
||||
- ~~文字识别库:[chineseocr_lite](https://github.com/DayBreak-u/chineseocr_lite.git)~~
|
||||
- 文字识别库:[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)
|
||||
- 关卡掉落识别:[企鹅物流识别](https://github.com/KumoSiunaus/penguin-stats-recognize-v3)
|
||||
- C++ JSON库:[meojson](https://github.com/MistEO/meojson.git)
|
||||
- C++ 运算符解析器:[calculator](https://github.com/kimwalisch/calculator)
|
||||
- C++ base64编解码:[cpp-base64](https://github.com/ReneNyffenegger/cpp-base64)
|
||||
- WPF MVVW框架:[Stylet](https://github.com/canton7/Stylet)
|
||||
- WPF控件库:[HandyControl](https://github.com/HandyOrg/HandyControl)
|
||||
- C# JSON库: [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
- 下载器:[aria2](https://github.com/aria2/aria2)
|
||||
|
||||
### 数据源
|
||||
|
||||
@@ -233,13 +230,16 @@ A game assistance for Arknights
|
||||
- 非常感谢 [tcyh035](https://github.com/tcyh035) 帮忙设计重构图形界面
|
||||
- 非常感谢 [GengGode](https://github.com/GengGode) 和 [DbgDebug](https://github.com/DbgDebug) 提供图像算法思路并协助验证
|
||||
- 非常感谢 [LoveLoliii](https://github.com/LoveLoliii) 提供公开招募算法及数据、部分功能逻辑思路
|
||||
- 感谢[AAH](https://github.com/ninthDevilHAUNSTER/ArknightsAutoHelper)的大佬们协助提供部分图像、操作思路
|
||||
- 感谢 [内卷地狱](https://jq.qq.com/?_wv=1027&k=ypbzXcA2) 的大佬们提供的各种协助支持
|
||||
- 感谢 [LmeSzinc](https://github.com/LmeSzinc) 提供的界面样式参考,~~虽然我抄了个四不像orz~~
|
||||
- 感谢参与软件测试、提bug的小伙伴们~
|
||||
- ~~感谢[B站直播间](https://live.bilibili.com/2808861)的小伙伴们陪我弹幕吹水~~
|
||||
- ~~感谢 [B站直播间](https://live.bilibili.com/2808861) 的小伙伴们陪我弹幕吹水~~
|
||||
|
||||
## 广告
|
||||
|
||||
[B站直播间](https://live.bilibili.com/2808861):每晚直播敲代码,近期很长一段时间应该都是在写本助手软件
|
||||
[QQ群](https://jq.qq.com/?_wv=1027&k=ypbzXcA2):欢迎加入~
|
||||
[QQ群:内卷地狱](https://jq.qq.com/?_wv=1027&k=ypbzXcA2):欢迎加入~
|
||||
|
||||
另:作者前端苦手,寻大佬帮忙一起写界面,继续现在的WPF也行,用electron或者别的重写也行,球球了QAQ
|
||||
如果觉得软件对你有帮助,帮忙点个Star吧!~(网页最上方右上角的小星星),这就是对我最大的支持了!
|
||||
|
||||
PS:作者前端苦手,现在的界面(WPF)基本是现学现卖的,写得很烂,希望有大佬能帮忙提点PR修改修改,感激不尽_(:з」∠)_
|
||||
|
||||
@@ -7,7 +7,7 @@ clone_depth: 1
|
||||
before_build:
|
||||
- ps: nuget restore
|
||||
build:
|
||||
project: MeoAssistance.sln
|
||||
project: MeoAssistantArknights.sln
|
||||
parallel: true
|
||||
verbosity: minimal
|
||||
notifications:
|
||||
|
||||
BIN
images/gui.png
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 48 KiB |
@@ -2,37 +2,42 @@
|
||||
|
||||
#include "AsstPort.h"
|
||||
|
||||
namespace asst {
|
||||
class Assistant;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef void (MEO_CALL* AsstCallback)(int msg, const char* detail_json, void* custom_arg);
|
||||
typedef void (ASST_CALL* AsstCallback)(int msg, const char* detail_json, void* custom_arg);
|
||||
|
||||
MEOAPI_PORT void* MEO_CALL AsstCreate();
|
||||
MEOAPI_PORT void* MEO_CALL AsstCreateEx(AsstCallback callback, void* custom_arg);
|
||||
void MEOAPI AsstDestory(void* p_asst);
|
||||
ASSTAPI_PORT asst::Assistant* ASST_CALL AsstCreate(const char* dirname);
|
||||
ASSTAPI_PORT asst::Assistant* ASST_CALL AsstCreateEx(const char* dirname, AsstCallback callback, void* custom_arg);
|
||||
void ASSTAPI AsstDestroy(asst::Assistant* p_asst);
|
||||
|
||||
bool MEOAPI AsstCatchDefault(void* p_asst);
|
||||
bool MEOAPI AsstCatchEmulator(void* p_asst);
|
||||
bool MEOAPI AsstCatchCustom(void* p_asst, const char* address);
|
||||
bool MEOAPI AsstCatchFake(void* p_asst);
|
||||
bool ASSTAPI AsstCatchDefault(asst::Assistant* p_asst);
|
||||
bool ASSTAPI AsstCatchEmulator(asst::Assistant* p_asst);
|
||||
bool ASSTAPI AsstCatchCustom(asst::Assistant* p_asst, const char* address);
|
||||
bool ASSTAPI AsstCatchFake(asst::Assistant* p_asst);
|
||||
|
||||
bool MEOAPI AsstAppendFight(void* p_asst, int max_mecidine, int max_stone, int max_times);
|
||||
bool MEOAPI AsstAppendAward(void* p_asst);
|
||||
bool MEOAPI AsstAppendVisit(void* p_asst);
|
||||
bool MEOAPI AsstAppendMall(void* p_asst, bool with_shopping);
|
||||
//bool MEOAPI AsstAppendProcessTask(void* p_asst, const char* task);
|
||||
bool MEOAPI AsstAppendInfrast(void* p_asst, int work_mode, const char** order, int order_size, const char* uses_of_drones, double dorm_threshold);
|
||||
bool MEOAPI AsstAppendRecruit(void* p_asst, int max_times, const int required_level[], int required_len, const int confirm_level[], int confirm_len, bool need_refresh);
|
||||
bool MEOAPI AsstAppendDebug(void* p_asst);
|
||||
bool ASSTAPI AsstAppendStartUp(asst::Assistant* p_asst);
|
||||
bool ASSTAPI AsstAppendFight(asst::Assistant* p_asst, const char* stage, int max_mecidine, int max_stone, int max_times);
|
||||
bool ASSTAPI AsstAppendAward(asst::Assistant* p_asst);
|
||||
bool ASSTAPI AsstAppendVisit(asst::Assistant* p_asst);
|
||||
bool ASSTAPI AsstAppendMall(asst::Assistant* p_asst, bool with_shopping);
|
||||
//bool ASSTAPI AsstAppendProcessTask(asst::Assistant* p_asst, const char* task);
|
||||
bool ASSTAPI AsstAppendInfrast(asst::Assistant* p_asst, int work_mode, const char** order, int order_size, const char* uses_of_drones, double dorm_threshold);
|
||||
bool ASSTAPI AsstAppendRecruit(asst::Assistant* p_asst, int max_times, const int select_level[], int select_len, const int confirm_level[], int confirm_len, bool need_refresh);
|
||||
bool ASSTAPI AsstAppendDebug(asst::Assistant* p_asst);
|
||||
|
||||
bool MEOAPI AsstStartRecruitCalc(void* p_asst, const int required_level[], int required_len, bool set_time);
|
||||
bool MEOAPI AsstStart(void* p_asst);
|
||||
bool MEOAPI AsstStop(void* p_asst);
|
||||
bool ASSTAPI AsstStartRecruitCalc(asst::Assistant* p_asst, const int select_level[], int required_len, bool set_time);
|
||||
bool ASSTAPI AsstStart(asst::Assistant* p_asst);
|
||||
bool ASSTAPI AsstStop(asst::Assistant* p_asst);
|
||||
|
||||
bool MEOAPI AsstSetPenguinId(void* p_asst, const char* id);
|
||||
//bool MEOAPI AsstSetParam(void* p_asst, const char* type, const char* param, const char* value);
|
||||
bool ASSTAPI AsstSetPenguinId(asst::Assistant* p_asst, const char* id);
|
||||
//bool ASSTAPI AsstSetParam(asst::Assistant* p_asst, const char* type, const char* param, const char* value);
|
||||
|
||||
MEOAPI_PORT const char* MEO_CALL AsstGetVersion();
|
||||
ASSTAPI_PORT const char* ASST_CALL AsstGetVersion();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,37 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
// The way how the function is called
|
||||
#if !defined(MEO_CALL)
|
||||
#if !defined(ASST_CALL)
|
||||
#if defined(_WIN32)
|
||||
#define MEO_CALL __stdcall
|
||||
#define ASST_CALL __stdcall
|
||||
#else
|
||||
#define MEO_CALL
|
||||
#define ASST_CALL
|
||||
#endif /* _WIN32 */
|
||||
#endif /* MEO_CALL */
|
||||
#endif /* ASST_CALL */
|
||||
|
||||
// The function exported symbols
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#define MEO_DLL_IMPORT __declspec(dllimport)
|
||||
#define MEO_DLL_EXPORT __declspec(dllexport)
|
||||
#define MEO_DLL_LOCAL
|
||||
#define ASST_DLL_IMPORT __declspec(dllimport)
|
||||
#define ASST_DLL_EXPORT __declspec(dllexport)
|
||||
#define ASST_DLL_LOCAL
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define MEO_DLL_IMPORT __attribute__ ((visibility ("default")))
|
||||
#define MEO_DLL_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define MEO_DLL_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#define ASST_DLL_IMPORT __attribute__ ((visibility ("default")))
|
||||
#define ASST_DLL_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define ASST_DLL_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define MEO_DLL_IMPORT
|
||||
#define MEO_DLL_EXPORT
|
||||
#define MEO_DLL_LOCAL
|
||||
#define ASST_DLL_IMPORT
|
||||
#define ASST_DLL_EXPORT
|
||||
#define ASST_DLL_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MEO_DLL_EXPORTS // defined if we are building the DLL (instead of using it)
|
||||
#define MEOAPI_PORT MEO_DLL_EXPORT
|
||||
#ifdef ASST_DLL_EXPORTS // defined if we are building the DLL (instead of using it)
|
||||
#define ASSTAPI_PORT ASST_DLL_EXPORT
|
||||
#else
|
||||
#define MEOAPI_PORT MEO_DLL_IMPORT
|
||||
#endif // MEO_DLL_EXPORTS
|
||||
#define ASSTAPI_PORT ASST_DLL_IMPORT
|
||||
#endif // ASST_DLL_EXPORTS
|
||||
|
||||
#define MEOAPI MEOAPI_PORT MEO_CALL
|
||||
#define ASSTAPI ASSTAPI_PORT ASST_CALL
|
||||
|
||||
#define MEOLOCAL MEO_DLL_LOCAL MEO_CALL
|
||||
#define ASSTLOCAL ASST_DLL_LOCAL ASST_CALL
|
||||
@@ -5,23 +5,21 @@
|
||||
"connectType_Doc": "连接类型:0-连接电脑上的模拟器;1-连接自定义端口,请手动修改'emulator.Custom'中的相关字段。默认0",
|
||||
"taskDelay": 2000,
|
||||
"taskDelay_Doc": "识别的延迟:越快识别频率越快,但会增加CPU消耗。单位毫秒,默认2000",
|
||||
"printWindow": false,
|
||||
"printWindow_Doc": "截图功能:开启后每次结算界面会截图到screenshot目录下。true-开启,false-关闭,默认false",
|
||||
"penguinReport": true,
|
||||
"penguinReport_Doc": "企鹅数据汇报:每次到结算界面,是否汇报掉落数据至企鹅数据 https://penguin-stats.cn/。true-开启,false-关闭,默认true",
|
||||
"penguinReportCmdLine": "curl -H \"Content-Type: application/json\" -d \"[body]\" \"https://penguin-stats.cn/PenguinStats/api/v2/report\" [extra]",
|
||||
"penguinReportCmdLine_Doc": "企鹅数据汇报的命令,想打印详细信息可以尝试添加 -v -i",
|
||||
"controlDelayRange": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"controlDelayRange_Doc": "点击随机延时:每次点击操作会进行随机延时,降低封号风险(好像也没听说过谁被封号的)。格式为 [ 最小延时, 最大延时 ],单位为毫秒。例如想设置3~5秒延时,即修改为[ 3000, 5000 ],默认0~0",
|
||||
"ocrThreadNumber": 4,
|
||||
"ocrThreadNumber_Doc": "文字识别库OcrLite的线程数量,理论上开的高点识别会快点,但是会更卡。默认4",
|
||||
"adbExtraSwipeDist": 50,
|
||||
"adbExtraSwipeDist_Doc": "额外的滑动距离:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来",
|
||||
"adbExtraSwipeDuration": 1000,
|
||||
"adbExtraSwipeDuration_Doc": "额外的滑动持续时间:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来。若小于0,则关闭额外滑动功能"
|
||||
"adbExtraSwipeDuration_Doc": "额外的滑动持续时间:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来。若小于0,则关闭额外滑动功能",
|
||||
"penguinReport": {
|
||||
"Doc": "企鹅数据汇报:每次到结算界面,汇报掉落数据至企鹅数据 https://penguin-stats.cn/。true-开启,false-关闭,默认true",
|
||||
"enable": true,
|
||||
"cmdFormat": "curl -H \"Content-Type: application/json\" -d \"[body]\" \"https://penguin-stats.cn/PenguinStats/api/v2/report\" [extra]",
|
||||
"cmdFormat_Doc": "命令格式,想打印详细信息可以尝试添加 -v -i"
|
||||
}
|
||||
},
|
||||
"emulator_Doc": "下面的和模拟器窗口捕获逻辑有关,不需要修改",
|
||||
"emulator": {
|
||||
@@ -40,7 +38,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayFormat": "cur=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p"
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
},
|
||||
"BlueStacksInternational": {
|
||||
@@ -58,7 +57,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayFormat": "cur=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p"
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
},
|
||||
"MuMuEmulator": {
|
||||
@@ -76,7 +76,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayFormat": "cur=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p"
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
},
|
||||
"LDPlayer": {
|
||||
@@ -94,7 +95,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayFormat": "cur=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] shell screencap -p"
|
||||
"screencap": "[Adb] -s [Address] shell screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
},
|
||||
"Nox": {
|
||||
@@ -112,7 +114,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayFormat": "cur=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p"
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
},
|
||||
"XYAZ": {
|
||||
@@ -130,7 +133,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init=",
|
||||
"displayFormat": " init=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] shell screencap -p"
|
||||
"screencap": "[Adb] -s [Address] shell screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
},
|
||||
"Custom": {
|
||||
@@ -150,7 +154,8 @@
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayFormat": "cur=%dx%d",
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p"
|
||||
"screencap": "[Adb] -s [Address] exec-out screencap -p",
|
||||
"release": "[Adb] kill-server"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,6 +482,15 @@
|
||||
"all": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "火神-1",
|
||||
"skills": [
|
||||
"Bskill_man_spd&limit&cost1"
|
||||
],
|
||||
"efficient": {
|
||||
"all": 27
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "米格鲁、卡缇",
|
||||
"skills": [
|
||||
|
||||
@@ -1,10 +1,168 @@
|
||||
{
|
||||
"SanityBegin": {
|
||||
"StartUp": {
|
||||
"algorithm": "justreturn",
|
||||
"action": "doNothing",
|
||||
"next": [
|
||||
"GameStart",
|
||||
"StartToWakeUp",
|
||||
"Terminal",
|
||||
"CloseAnno",
|
||||
"TodaysSupplies",
|
||||
"ReturnToTerminal",
|
||||
"OfflineConfirm"
|
||||
]
|
||||
},
|
||||
"LS-5": {
|
||||
"algorithm": "justreturn",
|
||||
"action": "doNothing",
|
||||
"next": [
|
||||
"StageResourceToLS5",
|
||||
"StageLS",
|
||||
"StageLS5"
|
||||
]
|
||||
},
|
||||
"StageResourceToLS5": {
|
||||
"template": "StageResource.png",
|
||||
"roi": [
|
||||
790,
|
||||
640,
|
||||
60,
|
||||
60
|
||||
],
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"SwipeToStageLS"
|
||||
]
|
||||
},
|
||||
"SwipeToStageLS": {
|
||||
"algorithm": "justReturn",
|
||||
"action": "swipeToTheLeft",
|
||||
"next": [
|
||||
"StageLS"
|
||||
]
|
||||
},
|
||||
"StageLS": {
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"StageLS5"
|
||||
]
|
||||
},
|
||||
"StageLS5": {
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
850,
|
||||
140,
|
||||
250,
|
||||
80
|
||||
]
|
||||
},
|
||||
"AP-5": {
|
||||
"algorithm": "justreturn",
|
||||
"action": "doNothing",
|
||||
"next": [
|
||||
"StageResourceToAP5",
|
||||
"StageAP",
|
||||
"StageAP5"
|
||||
]
|
||||
},
|
||||
"StageResourceToAP5": {
|
||||
"template": "StageResource.png",
|
||||
"roi": [
|
||||
790,
|
||||
640,
|
||||
60,
|
||||
60
|
||||
],
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"SwipeToStageAP"
|
||||
]
|
||||
},
|
||||
"SwipeToStageAP": {
|
||||
"algorithm": "justReturn",
|
||||
"action": "swipeToTheLeft",
|
||||
"next": [
|
||||
"StageAP"
|
||||
]
|
||||
},
|
||||
"StageAP": {
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"StageAP5"
|
||||
]
|
||||
},
|
||||
"StageAP5": {
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
850,
|
||||
140,
|
||||
250,
|
||||
80
|
||||
]
|
||||
},
|
||||
"CE-5": {
|
||||
"algorithm": "justreturn",
|
||||
"action": "doNothing",
|
||||
"next": [
|
||||
"StageResourceToCE5",
|
||||
"StageCE",
|
||||
"StageCE5"
|
||||
]
|
||||
},
|
||||
"StageResourceToCE5": {
|
||||
"template": "StageResource.png",
|
||||
"roi": [
|
||||
790,
|
||||
640,
|
||||
60,
|
||||
60
|
||||
],
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"SwipeToStageCE"
|
||||
]
|
||||
},
|
||||
"SwipeToStageCE": {
|
||||
"algorithm": "justReturn",
|
||||
"action": "swipeToTheLeft",
|
||||
"next": [
|
||||
"StageCE"
|
||||
]
|
||||
},
|
||||
"StageCE": {
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"StageCE5"
|
||||
]
|
||||
},
|
||||
"StageCE5": {
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
850,
|
||||
140,
|
||||
250,
|
||||
80
|
||||
]
|
||||
},
|
||||
"Annihilation": {
|
||||
"doc": "剿灭作战,一般本周的满了也不会有人再刷的,所以只识别右上角ToDoList里的剿灭就可以了",
|
||||
"template": "StageAnnihilation.png",
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
900,
|
||||
70,
|
||||
380,
|
||||
400
|
||||
],
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
]
|
||||
},
|
||||
"StageBegin": {
|
||||
"algorithm": "justreturn",
|
||||
"action": "doNothing",
|
||||
"next": [
|
||||
"UsePrts",
|
||||
"StartButton1",
|
||||
"ReturnToTerminal",
|
||||
"PRTS",
|
||||
"EndOfAction",
|
||||
@@ -16,6 +174,15 @@
|
||||
"GameStart"
|
||||
]
|
||||
},
|
||||
"FightBegin": {
|
||||
"algorithm": "justreturn",
|
||||
"action": "doNothing",
|
||||
"next": [
|
||||
"UsePrts",
|
||||
"StartButton1",
|
||||
"LastBattle"
|
||||
]
|
||||
},
|
||||
"GameStart": {
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
@@ -24,7 +191,6 @@
|
||||
200,
|
||||
120
|
||||
],
|
||||
"cache": false,
|
||||
"rearDelay": 5000,
|
||||
"maskRange": [
|
||||
1,
|
||||
@@ -113,14 +279,14 @@
|
||||
"PRTS": {
|
||||
"algorithm": "OcrDetect",
|
||||
"text": [
|
||||
"剩余可放置角色",
|
||||
"接管作战"
|
||||
"剩余可放置角色"
|
||||
],
|
||||
"roi": [
|
||||
0,
|
||||
530,
|
||||
1280,
|
||||
190
|
||||
900,
|
||||
500,
|
||||
380,
|
||||
150
|
||||
|
||||
],
|
||||
"action": "doNothing",
|
||||
"rearDelay": 5000,
|
||||
@@ -200,10 +366,11 @@
|
||||
},
|
||||
"UseMedicine": {
|
||||
"action": "doNothing",
|
||||
"templThreshold": 0.7,
|
||||
"roi": [
|
||||
580,
|
||||
50,
|
||||
700,
|
||||
400,
|
||||
100
|
||||
],
|
||||
"next": [
|
||||
@@ -212,7 +379,6 @@
|
||||
},
|
||||
"MedicineConfirm": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"maxTimes": 0,
|
||||
"roi": [
|
||||
1000,
|
||||
@@ -245,7 +411,6 @@
|
||||
"StoneConfirm": {
|
||||
"template": "MedicineConfirm.png",
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"maxTimes": 0,
|
||||
"roi": [
|
||||
1000,
|
||||
@@ -277,7 +442,6 @@
|
||||
]
|
||||
},
|
||||
"PrtsErrorConfirm": {
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
120,
|
||||
@@ -292,7 +456,6 @@
|
||||
},
|
||||
"AbandonAction": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"reduceOtherTimes": [
|
||||
"StartButton1",
|
||||
"StartButton2"
|
||||
@@ -312,7 +475,6 @@
|
||||
"OfflineConfirmAfterBattle": {
|
||||
"template": "PopupConfirm.png",
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
630,
|
||||
400,
|
||||
@@ -328,7 +490,6 @@
|
||||
},
|
||||
"OfflineConfirm": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
400,
|
||||
@@ -387,7 +548,8 @@
|
||||
"LastBattle",
|
||||
"Terminal",
|
||||
"CloseAnno",
|
||||
"TodaysSupplies"
|
||||
"TodaysSupplies",
|
||||
"Stop"
|
||||
]
|
||||
},
|
||||
"TodaysSupplies": {
|
||||
@@ -416,8 +578,8 @@
|
||||
"LastBattle": {
|
||||
"algorithm": "OcrDetect",
|
||||
"text": [
|
||||
"上一次作战",
|
||||
"前往上一次"
|
||||
"前往",
|
||||
"作战"
|
||||
],
|
||||
"roi": [
|
||||
900,
|
||||
@@ -427,6 +589,7 @@
|
||||
],
|
||||
"action": "clickSelf",
|
||||
"next": [
|
||||
"UsePrts",
|
||||
"StartButton1"
|
||||
]
|
||||
},
|
||||
@@ -473,7 +636,6 @@
|
||||
},
|
||||
"Recruit": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
900,
|
||||
450,
|
||||
@@ -507,7 +669,6 @@
|
||||
},
|
||||
"RecruitSkip": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"rearDelay": 3000,
|
||||
"roi": [
|
||||
1100,
|
||||
@@ -538,7 +699,6 @@
|
||||
"StartRecruit": {
|
||||
"algorithm": "OcrDetect",
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"rearDelay": 1000,
|
||||
"text": [
|
||||
"开始招"
|
||||
@@ -591,7 +751,6 @@
|
||||
]
|
||||
},
|
||||
"ReceiveAward": {
|
||||
"cache": false,
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
950,
|
||||
@@ -793,7 +952,6 @@
|
||||
},
|
||||
"VisitNext": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"rearDelay": 2000,
|
||||
"roi": [
|
||||
1080,
|
||||
@@ -879,6 +1037,7 @@
|
||||
640,
|
||||
360
|
||||
],
|
||||
"rearDelay": 1000,
|
||||
"next": [
|
||||
"CreditStoreOcr",
|
||||
"Mall"
|
||||
@@ -1008,7 +1167,6 @@
|
||||
},
|
||||
"HomeFlag": {
|
||||
"template": "Terminal.png",
|
||||
"cache": false,
|
||||
"action": "stop",
|
||||
"roi": [
|
||||
880,
|
||||
@@ -1019,7 +1177,6 @@
|
||||
},
|
||||
"CreditShop-Commoditys": {
|
||||
"template": "CreditPoint.png",
|
||||
"cache": false,
|
||||
"rectMove": [
|
||||
-60,
|
||||
-180,
|
||||
@@ -1028,7 +1185,6 @@
|
||||
]
|
||||
},
|
||||
"CreditShop-SoldOut": {
|
||||
"cache": false,
|
||||
"template": "SoldOut.png"
|
||||
},
|
||||
"CreditShop-BuyIt": {
|
||||
@@ -1039,7 +1195,6 @@
|
||||
250,
|
||||
150
|
||||
],
|
||||
"cache": false,
|
||||
"preDelay": 1000,
|
||||
"rearDelay": 1000
|
||||
},
|
||||
@@ -1077,7 +1232,6 @@
|
||||
"RecruitTime": {
|
||||
"template": "RecruitTimeReduce.png",
|
||||
"templThreshold": 0.89,
|
||||
"cache": false,
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
350,
|
||||
@@ -1096,53 +1250,24 @@
|
||||
"algorithm": "OcrDetect",
|
||||
"text": [],
|
||||
"roi": [
|
||||
200,
|
||||
200,
|
||||
800,
|
||||
500
|
||||
375,
|
||||
360,
|
||||
480,
|
||||
120
|
||||
],
|
||||
"ocrReplace": [
|
||||
[
|
||||
"沮击",
|
||||
"狙击"
|
||||
"千员",
|
||||
"干员"
|
||||
],
|
||||
[
|
||||
"犯击",
|
||||
"狙击"
|
||||
],
|
||||
[
|
||||
"泪击",
|
||||
"狙击"
|
||||
],
|
||||
[
|
||||
"都出",
|
||||
"输出"
|
||||
],
|
||||
[
|
||||
"都乐",
|
||||
"输出"
|
||||
],
|
||||
[
|
||||
"抓出",
|
||||
"输出"
|
||||
],
|
||||
[
|
||||
"都任",
|
||||
"输出"
|
||||
],
|
||||
[
|
||||
"新于",
|
||||
"新手"
|
||||
],
|
||||
[
|
||||
"防拍",
|
||||
"防护"
|
||||
".+击干员",
|
||||
"狙击干员"
|
||||
]
|
||||
]
|
||||
},
|
||||
"RecruitRefresh": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
850,
|
||||
340,
|
||||
@@ -1155,7 +1280,6 @@
|
||||
},
|
||||
"RecruitNoRefresh": {
|
||||
"action": "doNothing",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
850,
|
||||
340,
|
||||
@@ -1166,18 +1290,38 @@
|
||||
"RecruitRefreshConfirm": {
|
||||
"template": "PopupConfirm.png",
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"rearDelay": 3000,
|
||||
"roi": [
|
||||
630,
|
||||
400,
|
||||
650,
|
||||
160
|
||||
],
|
||||
"next": [
|
||||
"RecruitLoading",
|
||||
"Stop"
|
||||
]
|
||||
},
|
||||
"RecruitLoading": {
|
||||
"algorithm": "OcrDetect",
|
||||
"action": "doNothing",
|
||||
"text": [
|
||||
"正在提交",
|
||||
"反馈至神经"
|
||||
],
|
||||
"roi": [
|
||||
700,
|
||||
600,
|
||||
300,
|
||||
120
|
||||
],
|
||||
"next": [
|
||||
"RecruitLoading",
|
||||
"Stop"
|
||||
]
|
||||
},
|
||||
"RecruitConfirm": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
860,
|
||||
540,
|
||||
@@ -1247,7 +1391,6 @@
|
||||
},
|
||||
"EnterInfrast": {
|
||||
"rearDelay": 3000,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
900,
|
||||
540,
|
||||
@@ -1325,7 +1468,6 @@
|
||||
},
|
||||
"DroneAssistMfg": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
1180,
|
||||
500,
|
||||
@@ -1341,7 +1483,6 @@
|
||||
},
|
||||
"DroneAssistTrade": {
|
||||
"action": "clickSelf",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
250,
|
||||
430,
|
||||
@@ -1381,13 +1522,12 @@
|
||||
]
|
||||
},
|
||||
"DeliverableOrder": {
|
||||
"cache": false,
|
||||
"action": "clickSelf",
|
||||
"roi": [
|
||||
250,
|
||||
130,
|
||||
300,
|
||||
230,
|
||||
420
|
||||
250
|
||||
],
|
||||
"next": [
|
||||
"DeliverableOrder",
|
||||
@@ -1398,8 +1538,7 @@
|
||||
"DroneAssist-Trade-Stop": {
|
||||
"Doc": "如果找到了“无人机加速”按钮,却没有找到订单交付:说明上一次无人机没有把一个订单加速完成,也说明没有更多的无人机了,所以直接stop",
|
||||
"template": "DroneAssistTrade.png",
|
||||
"action": "stop",
|
||||
"cache": false
|
||||
"action": "stop"
|
||||
},
|
||||
"InfrastSkillsUpper": {
|
||||
"algorithm": "justReturn",
|
||||
@@ -1449,7 +1588,6 @@
|
||||
100,
|
||||
255
|
||||
],
|
||||
"cache": false,
|
||||
"templThreshold": 0.8
|
||||
},
|
||||
"InfrastSmileyOnWork": {
|
||||
@@ -1458,7 +1596,6 @@
|
||||
100,
|
||||
255
|
||||
],
|
||||
"cache": false,
|
||||
"templThreshold": 0.8
|
||||
},
|
||||
"InfrastSmileyOnDistract": {
|
||||
@@ -1467,15 +1604,13 @@
|
||||
100,
|
||||
255
|
||||
],
|
||||
"cache": false,
|
||||
"templThreshold": 0.8
|
||||
},
|
||||
"InfrastSkills": {
|
||||
"template": "empty.png",
|
||||
"templThreshold": 0.9,
|
||||
"histThreshold": 95,
|
||||
"histThreshold_Doc": "该任务里的Hist阈值,是特化了拿来做灰度图平均值的,懒得重新写个字段了",
|
||||
"cache": false,
|
||||
"specialThreshold": 95,
|
||||
"specialThreshold_Doc": "用于做灰度图平均值",
|
||||
"rectMove_Doc": "基于笑脸的位置移动",
|
||||
"rectMove": [
|
||||
-8,
|
||||
@@ -1538,9 +1673,8 @@
|
||||
"InfrastOperMoodProgressBar": {
|
||||
"template": "empty.png",
|
||||
"templThreshold": 160,
|
||||
"histThreshold": 20,
|
||||
"Doc": "这里的templThreshold,作为进度条最小灰度阈值使用;histThreshold作为进度条相邻点最大变化阈值使用。懒得重新弄个字段了",
|
||||
"cache": false,
|
||||
"specialThreshold": 20,
|
||||
"Doc": "这里的templThreshold,作为进度条最小灰度阈值使用;specialThreshold作为进度条相邻点最大变化阈值使用。懒得重新弄个字段了",
|
||||
"rectMove_Doc": "基于笑脸的位置移动",
|
||||
"rectMove": [
|
||||
21,
|
||||
@@ -1551,7 +1685,6 @@
|
||||
},
|
||||
"InfrastMfg": {
|
||||
"template": "Manufacturing.png",
|
||||
"cache": false,
|
||||
"templThreshold": 0.9,
|
||||
"maskRange": [
|
||||
1,
|
||||
@@ -1567,7 +1700,6 @@
|
||||
"InfrastMfgMini": {
|
||||
"template": "ManufacturingMini.png",
|
||||
"templThreshold": 0.9,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
240,
|
||||
@@ -1582,7 +1714,6 @@
|
||||
"InfrastTrade": {
|
||||
"template": "Trade.png",
|
||||
"templThreshold": 0.9,
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1597,7 +1728,6 @@
|
||||
"InfrastTradeMini": {
|
||||
"template": "TradeMini.png",
|
||||
"templThreshold": 0.9,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
240,
|
||||
@@ -1611,7 +1741,6 @@
|
||||
},
|
||||
"InfrastPower": {
|
||||
"template": "Power.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1626,7 +1755,6 @@
|
||||
},
|
||||
"InfrastPowerMini": {
|
||||
"template": "PowerMini.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
240,
|
||||
@@ -1641,7 +1769,6 @@
|
||||
},
|
||||
"InfrastDorm": {
|
||||
"template": "Dorm.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1656,7 +1783,6 @@
|
||||
},
|
||||
"InfrastDormMini": {
|
||||
"template": "DormMini.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1671,7 +1797,6 @@
|
||||
},
|
||||
"InfrastOffice": {
|
||||
"template": "Office.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1686,7 +1811,6 @@
|
||||
},
|
||||
"InfrastOfficeMini": {
|
||||
"template": "OfficeMini.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1701,7 +1825,6 @@
|
||||
},
|
||||
"InfrastReception": {
|
||||
"template": "Reception.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1716,7 +1839,6 @@
|
||||
},
|
||||
"InfrastReceptionMini": {
|
||||
"template": "ReceptionMini.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1731,7 +1853,6 @@
|
||||
},
|
||||
"InfrastControl": {
|
||||
"template": "ControlCenter.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1746,7 +1867,6 @@
|
||||
},
|
||||
"InfrastControlMini": {
|
||||
"template": "ControlCenterMini.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
@@ -1761,7 +1881,6 @@
|
||||
},
|
||||
"InfrastStationedInfo": {
|
||||
"algorithm": "OcrDetect",
|
||||
"cache": false,
|
||||
"text": [
|
||||
"进驻信息"
|
||||
],
|
||||
@@ -1775,7 +1894,6 @@
|
||||
},
|
||||
"InfrastEnterOperList": {
|
||||
"algorithm": "OcrDetect",
|
||||
"cache": false,
|
||||
"text": [
|
||||
"心情",
|
||||
"休息中",
|
||||
@@ -1812,7 +1930,6 @@
|
||||
"rearDelay": 500,
|
||||
"Doc": "这个任务复用了,上半部分用来检测确认按钮点击成功没;下部部分用来点击",
|
||||
"algorithm": "ocrDetect",
|
||||
"cache": false,
|
||||
"text": [
|
||||
"正在提交",
|
||||
"反馈至神经"
|
||||
@@ -1852,7 +1969,6 @@
|
||||
},
|
||||
"InfrastFacilityListTabMfg": {
|
||||
"template": "FacilityListTabMfg.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
0,
|
||||
@@ -1867,7 +1983,6 @@
|
||||
},
|
||||
"InfrastFacilityListTabTrade": {
|
||||
"template": "FacilityListTabTrade.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
0,
|
||||
@@ -1882,7 +1997,6 @@
|
||||
},
|
||||
"InfrastOperLockedMfg": {
|
||||
"template": "OperLockedMfg.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
200,
|
||||
500,
|
||||
@@ -1892,7 +2006,6 @@
|
||||
},
|
||||
"InfrastOperLockedTrade": {
|
||||
"template": "OperLockedTrade.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
200,
|
||||
500,
|
||||
@@ -1902,7 +2015,6 @@
|
||||
},
|
||||
"InfrastFlagCombatRecord": {
|
||||
"template": "InfrastMfgDogFoodFlag.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
1000,
|
||||
0,
|
||||
@@ -1912,7 +2024,6 @@
|
||||
},
|
||||
"InfrastFlagPureGold": {
|
||||
"template": "InfrastMfgPureGoldFlag.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
1000,
|
||||
0,
|
||||
@@ -1922,7 +2033,6 @@
|
||||
},
|
||||
"InfrastFlagOriginStone": {
|
||||
"template": "InfrastMfgOriginStoneFlag.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
1000,
|
||||
0,
|
||||
@@ -1932,7 +2042,6 @@
|
||||
},
|
||||
"InfrastFlagChip": {
|
||||
"template": "InfrastMfgChipFlag.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
1000,
|
||||
0,
|
||||
@@ -1942,7 +2051,6 @@
|
||||
},
|
||||
"InfrastFlagMoney": {
|
||||
"template": "InfrastTradeMoneyFlag.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
900,
|
||||
500,
|
||||
@@ -1952,7 +2060,6 @@
|
||||
},
|
||||
"InfrastFlagSyntheticJade": {
|
||||
"template": "InfrastTradeSyntheticJadeFlag.png",
|
||||
"cache": false,
|
||||
"roi": [
|
||||
900,
|
||||
500,
|
||||
@@ -1963,7 +2070,6 @@
|
||||
"InfrastAddOperatorMfgGentle": {
|
||||
"template": "AddOperatorMfgGentle.png",
|
||||
"templThreshold": 0.8,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
200,
|
||||
500,
|
||||
@@ -1975,7 +2081,6 @@
|
||||
"InfrastAddOperatorMfgAggressive": {
|
||||
"template": "AddOperatorMfgAggressive.png",
|
||||
"templThreshold": 0.8,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
200,
|
||||
500,
|
||||
@@ -1993,7 +2098,6 @@
|
||||
"InfrastAddOperatorTradeGentle": {
|
||||
"template": "AddOperatorTradeGentle.png",
|
||||
"templThreshold": 0.8,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
200,
|
||||
500,
|
||||
@@ -2005,7 +2109,6 @@
|
||||
"InfrastAddOperatorTradeAggressive": {
|
||||
"template": "AddOperatorTradeAggressive.png",
|
||||
"templThreshold": 0.8,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
200,
|
||||
500,
|
||||
@@ -2023,7 +2126,6 @@
|
||||
"InfrastAddOperatorReceptionGentle": {
|
||||
"template": "AddOperatorReceptionGentle.png",
|
||||
"templThreshold": 0.8,
|
||||
"cache": false,
|
||||
"roi": [
|
||||
0,
|
||||
0,
|
||||
@@ -2045,7 +2147,6 @@
|
||||
},
|
||||
"InfrastOperSelected": {
|
||||
"template": "empty.png",
|
||||
"cache": false,
|
||||
"templThreshold": 8000,
|
||||
"templThreshold_Doc": "这个任务中作为符合range的像素点数量阈值",
|
||||
"maskRange": [
|
||||
@@ -2061,7 +2162,6 @@
|
||||
},
|
||||
"InfrastOperOnShift": {
|
||||
"template": "OnShift.png",
|
||||
"cache": false,
|
||||
"templThreshold": 0.8,
|
||||
"rectMove": [
|
||||
0,
|
||||
@@ -2156,7 +2256,6 @@
|
||||
},
|
||||
"InfrastClue": {
|
||||
"template": "Clue.png",
|
||||
"cache": false,
|
||||
"maskRange": [
|
||||
1,
|
||||
255
|
||||
|
||||
BIN
resource/template/StageAP.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
resource/template/StageAP5.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resource/template/StageAnnihilation.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
resource/template/StageCE.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
resource/template/StageCE5.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
resource/template/StageLS.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
resource/template/StageLS5.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
resource/template/StageResource.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 8.8 KiB |
@@ -1 +0,0 @@
|
||||
#include "AbstractResource.h"
|
||||
@@ -1,252 +0,0 @@
|
||||
#include "AsstCaller.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <json_value.h>
|
||||
|
||||
#include "Assistance.h"
|
||||
#include "AsstDef.h"
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Version.h"
|
||||
|
||||
#if 0
|
||||
#if _MSC_VER
|
||||
// Win32平台下Dll的入口
|
||||
BOOL APIENTRY DllMain(HANDLE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hModule);
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#elif VA_GNUC
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
AsstCallback _callback = nullptr;
|
||||
|
||||
void CallbackTrans(asst::AsstMsg msg, const json::value& json, void* custom_arg)
|
||||
{
|
||||
_callback(static_cast<int>(msg), asst::utils::utf8_to_gbk(json.to_string()).c_str(), custom_arg);
|
||||
}
|
||||
|
||||
void* AsstCreate()
|
||||
{
|
||||
try {
|
||||
return new asst::Assistance();
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* AsstCreateEx(AsstCallback callback, void* custom_arg)
|
||||
{
|
||||
try {
|
||||
// 创建多实例回调会有问题,有空再慢慢整
|
||||
_callback = callback;
|
||||
return new asst::Assistance(CallbackTrans, custom_arg);
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AsstDestory(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete p_asst;
|
||||
p_asst = nullptr;
|
||||
}
|
||||
|
||||
bool AsstCatchDefault(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->catch_default();
|
||||
}
|
||||
|
||||
bool AsstCatchEmulator(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->catch_emulator();
|
||||
}
|
||||
|
||||
bool AsstCatchCustom(void* p_asst, const char* address)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->catch_custom(address);
|
||||
}
|
||||
|
||||
bool AsstCatchFake(void* p_asst)
|
||||
{
|
||||
#ifdef LOG_TRACE
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->catch_fake();
|
||||
#else
|
||||
return false;
|
||||
#endif // LOG_TRACE
|
||||
}
|
||||
|
||||
bool AsstAppendFight(void* p_asst, int max_mecidine, int max_stone, int max_times)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
asst::Assistance* ptr = (asst::Assistance*)p_asst;
|
||||
|
||||
return ptr->append_fight(max_mecidine, max_stone, max_times);
|
||||
}
|
||||
|
||||
bool AsstAppendAward(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->append_award();
|
||||
}
|
||||
|
||||
bool AsstAppendVisit(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->append_visit();
|
||||
}
|
||||
|
||||
bool AsstAppendMall(void* p_asst, bool with_shopping)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->append_mall(with_shopping);
|
||||
}
|
||||
|
||||
//bool AsstAppendProcessTask(void* p_asst, const char* task)
|
||||
//{
|
||||
// if (p_asst == nullptr) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return ((asst::Assistance*)p_asst)->append_process_task(task);
|
||||
//}
|
||||
|
||||
bool AsstStartRecruitCalc(void* p_asst, const int required_level[], int required_len, bool set_time)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<int> level_vector;
|
||||
level_vector.assign(required_level, required_level + required_len);
|
||||
return ((asst::Assistance*)p_asst)->start_recruit_calc(level_vector, set_time);
|
||||
}
|
||||
|
||||
bool AsstAppendInfrast(void* p_asst, int work_mode, const char** order, int order_size, const char* uses_of_drones, double dorm_threshold)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> order_vector;
|
||||
order_vector.assign(order, order + order_size);
|
||||
|
||||
return ((asst::Assistance*)p_asst)->
|
||||
append_infrast(
|
||||
static_cast<asst::infrast::WorkMode>(work_mode),
|
||||
order_vector,
|
||||
uses_of_drones,
|
||||
dorm_threshold);
|
||||
}
|
||||
|
||||
bool AsstAppendRecruit(void* p_asst, int max_times, const int required_level[], int required_len, const int confirm_level[], int confirm_len, bool need_refresh)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<int> required_vector;
|
||||
required_vector.assign(required_level, required_level + required_len);
|
||||
std::vector<int> confirm_vector;
|
||||
confirm_vector.assign(confirm_level, confirm_level + confirm_len);
|
||||
|
||||
return ((asst::Assistance*)p_asst)->append_recruit(max_times, required_vector, confirm_vector, need_refresh);
|
||||
}
|
||||
|
||||
bool AsstStart(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->start();
|
||||
}
|
||||
|
||||
bool AsstStop(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistance*)p_asst)->stop();
|
||||
}
|
||||
|
||||
bool MEOAPI AsstSetPenguinId(void* p_asst, const char* id)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto ptr = (asst::Assistance*)p_asst;
|
||||
ptr->set_penguin_id(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool AsstSetParam(void* p_asst, const char* type, const char* param, const char* value)
|
||||
//{
|
||||
// if (p_asst == nullptr) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return ((asst::Assistance*)p_asst)->set_param(type, param, value);
|
||||
//}
|
||||
|
||||
const char* AsstGetVersion()
|
||||
{
|
||||
return asst::Version;
|
||||
}
|
||||
|
||||
bool AsstAppendDebug(void* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
#if LOG_TRACE
|
||||
return ((asst::Assistance*)p_asst)->append_debug();
|
||||
#else
|
||||
return false;
|
||||
#endif // LOG_TRACE
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
#include "MatchImageAnalyzer.h"
|
||||
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "Resource.h"
|
||||
|
||||
asst::MatchImageAnalyzer::MatchImageAnalyzer(const cv::Mat& image, const Rect& roi, std::string templ_name, double templ_thres, double hist_thres)
|
||||
: AbstractImageAnalyzer(image, roi),
|
||||
m_templ_name(std::move(templ_name)),
|
||||
m_templ_thres(templ_thres),
|
||||
m_hist_thres(hist_thres)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
bool asst::MatchImageAnalyzer::analyze()
|
||||
{
|
||||
if (m_use_cache) {
|
||||
auto&& [hist, roi] = resource.templ().get_hist(m_templ_name);
|
||||
if (!hist.empty()) {
|
||||
return comp_hist(hist, roi);
|
||||
}
|
||||
}
|
||||
const cv::Mat& templ = resource.templ().get_templ(m_templ_name);
|
||||
if (templ.empty()) {
|
||||
log.error("templ is empty!");
|
||||
return false;
|
||||
}
|
||||
if (match_templ(templ)) {
|
||||
if (m_use_cache) {
|
||||
resource.templ().emplace_hist(m_templ_name, to_hist(templ), utils::make_rect<cv::Rect>(m_result.rect));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
cv::Mat asst::MatchImageAnalyzer::to_hist(const cv::Mat& src)
|
||||
{
|
||||
constexpr int histSize[] = { 50, 60 };
|
||||
constexpr float h_ranges[] = { 0, 180 };
|
||||
constexpr float s_ranges[] = { 0, 256 };
|
||||
const float* ranges[] = { h_ranges, s_ranges };
|
||||
constexpr int channels[] = { 0, 1 };
|
||||
|
||||
cv::MatND hist;
|
||||
|
||||
cv::calcHist(&src, 1, channels, cv::Mat(), hist, 2, histSize, ranges);
|
||||
cv::normalize(hist, hist, 0, 1, cv::NORM_MINMAX);
|
||||
|
||||
return hist;
|
||||
}
|
||||
|
||||
bool asst::MatchImageAnalyzer::match_templ(const cv::Mat& templ)
|
||||
{
|
||||
cv::Mat matched;
|
||||
|
||||
cv::Mat image_roi = m_image(utils::make_rect<cv::Rect>(m_roi));
|
||||
if (templ.cols > image_roi.cols || templ.rows > image_roi.rows) {
|
||||
log.error("templ size is too large", m_templ_name,
|
||||
"image_roi size:", image_roi.cols, image_roi.rows,
|
||||
"templ size:", templ.cols, templ.rows);
|
||||
return false;
|
||||
}
|
||||
if (m_mask_range.first == m_mask_range.second) {
|
||||
cv::matchTemplate(image_roi, templ, matched, cv::TM_CCOEFF_NORMED);
|
||||
}
|
||||
else {
|
||||
cv::Mat mask;
|
||||
cv::cvtColor(templ, mask, cv::COLOR_BGR2GRAY);
|
||||
cv::inRange(mask, m_mask_range.first, m_mask_range.second, mask);
|
||||
cv::matchTemplate(image_roi, templ, matched, cv::TM_CCOEFF_NORMED, mask);
|
||||
}
|
||||
double min_val = 0.0, max_val = 0.0;
|
||||
cv::Point min_loc, max_loc;
|
||||
cv::minMaxLoc(matched, &min_val, &max_val, &min_loc, &max_loc);
|
||||
|
||||
Rect rect(max_loc.x + m_roi.x, max_loc.y + m_roi.y, templ.cols, templ.rows);
|
||||
if (max_val > m_templ_thres * 0.7) { // 得分太低的肯定不对,没必要打印
|
||||
log.trace("match_templ |", m_templ_name, "score:", max_val, "rect:", rect.to_string());
|
||||
}
|
||||
|
||||
if (max_val >= m_templ_thres) {
|
||||
m_result = { AlgorithmType::MatchTemplate, max_val, rect };
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool asst::MatchImageAnalyzer::comp_hist(const cv::Mat& hist, const cv::Rect roi)
|
||||
{
|
||||
cv::Mat image_roi = m_image(utils::make_rect<cv::Rect>(roi));
|
||||
double score = 1.0 - cv::compareHist(to_hist(image_roi), hist, cv::HISTCMP_BHATTACHARYYA);
|
||||
|
||||
if (score > 0.7) { // 得分太低的肯定不对,没必要打印
|
||||
log.trace("comp_hist |", m_templ_name, "score:", score);
|
||||
}
|
||||
|
||||
if (score >= m_hist_thres) {
|
||||
Rect rect(roi.x, roi.y, hist.cols, hist.rows);
|
||||
m_result = { AlgorithmType::CompareHist, score, rect };
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#include "OcrPack.h"
|
||||
|
||||
#include <OcrLiteOnnx/OcrLiteCaller.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Logger.hpp"
|
||||
|
||||
asst::OcrPack::OcrPack()
|
||||
: m_ocr_ptr(std::make_unique<OcrLiteCaller>())
|
||||
{}
|
||||
|
||||
asst::OcrPack::~OcrPack() = default;
|
||||
|
||||
bool asst::OcrPack::load(const std::string & dir)
|
||||
{
|
||||
constexpr static const char* DetName = "\\models\\dbnet.onnx";
|
||||
constexpr static const char* ClsName = "\\models\\angle_net.onnx";
|
||||
constexpr static const char* RecName = "\\models\\crnn_lite_lstm.onnx";
|
||||
constexpr static const char* KeysName = "\\models\\keys.txt";
|
||||
|
||||
const std::string dst_filename = dir + DetName;
|
||||
const std::string cls_filename = dir + ClsName;
|
||||
const std::string rec_filename = dir + RecName;
|
||||
const std::string keys_filename = dir + KeysName;
|
||||
|
||||
return m_ocr_ptr->initModels(dst_filename, cls_filename, rec_filename, keys_filename);
|
||||
}
|
||||
|
||||
void asst::OcrPack::set_param(int /*gpu_index*/, int thread_number)
|
||||
{
|
||||
// gpu_index是ncnn的参数,onnx架构的没有,预留参数接口
|
||||
m_ocr_ptr->setNumThread(thread_number);
|
||||
}
|
||||
|
||||
std::vector<asst::TextRect> asst::OcrPack::recognize(const cv::Mat & image, const asst::TextRectProc & pred)
|
||||
{
|
||||
constexpr int padding = 50;
|
||||
constexpr int maxSideLen = 0;
|
||||
constexpr float boxScoreThresh = 0.2f;
|
||||
constexpr float boxThresh = 0.3f;
|
||||
constexpr float unClipRatio = 2.0f;
|
||||
constexpr bool doAngle = false;
|
||||
constexpr bool mostAngle = false;
|
||||
|
||||
OcrResult ocr_results = m_ocr_ptr->detect(image,
|
||||
padding, maxSideLen,
|
||||
boxScoreThresh, boxThresh,
|
||||
unClipRatio, doAngle, mostAngle);
|
||||
|
||||
std::vector<TextRect> result;
|
||||
std::string log_str_raw;
|
||||
std::string log_str_proc;
|
||||
for (TextBlock& text_block : ocr_results.textBlocks) {
|
||||
if (text_block.boxPoint.size() != 4) {
|
||||
continue;
|
||||
}
|
||||
// the rect like ↓
|
||||
// 0 - 1
|
||||
// 3 - 2
|
||||
int x = text_block.boxPoint.at(0).x;
|
||||
int y = text_block.boxPoint.at(0).y;
|
||||
int width = text_block.boxPoint.at(1).x - x;
|
||||
int height = text_block.boxPoint.at(3).y - y;
|
||||
|
||||
TextRect tr{ std::move(text_block.text), Rect(x, y, width, height) };
|
||||
log_str_raw += (std::string)tr + ", ";
|
||||
if (!pred || pred(tr)) {
|
||||
log_str_proc += tr.to_string() + ", ";
|
||||
result.emplace_back(std::move(tr));
|
||||
}
|
||||
}
|
||||
log.trace("OcrPack::recognize | raw : ", log_str_raw);
|
||||
log.trace("OcrPack::recognize | proc : ", log_str_proc);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<asst::TextRect> asst::OcrPack::recognize(const cv::Mat & image, const asst::Rect & roi, const asst::TextRectProc & pred)
|
||||
{
|
||||
auto rect_cor = [&roi, &pred](TextRect& tr) -> bool {
|
||||
tr.rect.x += roi.x;
|
||||
tr.rect.y += roi.y;
|
||||
return pred(tr);
|
||||
};
|
||||
return recognize(image(utils::make_rect<cv::Rect>(roi)), rect_cor);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
#include "PenguinUploader.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <json.h>
|
||||
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "Resource.h"
|
||||
#include "Version.h"
|
||||
|
||||
bool asst::PenguinUploader::upload(const std::string& rec_res)
|
||||
{
|
||||
std::string body = cvt_json(rec_res);
|
||||
return request_penguin(body);
|
||||
}
|
||||
|
||||
std::string asst::PenguinUploader::cvt_json(const std::string& rec_res)
|
||||
{
|
||||
auto parse_ret = json::parse(rec_res);
|
||||
if (!parse_ret) {
|
||||
return std::string();
|
||||
}
|
||||
json::value rec = std::move(parse_ret.value());
|
||||
|
||||
// Doc: https://developer.penguin-stats.io/public-api/api-v2-instruction/report-api
|
||||
json::value body;
|
||||
auto& opt = resource.cfg().get_options();
|
||||
body["server"] = opt.penguin_report_server;
|
||||
body["stageId"] = rec["stage"]["stageId"];
|
||||
// To fix: https://github.com/MistEO/MeoAssistance-Arknights/issues/40
|
||||
body["drops"] = json::array();
|
||||
for (auto&& drop : rec["drops"].as_array()) {
|
||||
if (!drop["itemId"].as_string().empty()) {
|
||||
body["drops"].as_array().emplace_back(drop);
|
||||
}
|
||||
}
|
||||
body["source"] = "MeoAssistance";
|
||||
body["version"] = Version;
|
||||
|
||||
return body.to_string();
|
||||
}
|
||||
|
||||
bool asst::PenguinUploader::request_penguin(const std::string& body)
|
||||
{
|
||||
auto& opt = resource.cfg().get_options();
|
||||
std::string body_escape = utils::string_replace_all(body, "\"", "\\\"");
|
||||
std::string cmd_line = utils::string_replace_all(opt.penguin_report_cmd_line, "[body]", body_escape);
|
||||
cmd_line = utils::string_replace_all(cmd_line, "[extra]", opt.penguin_report_extra_param);
|
||||
|
||||
log.trace("request_penguin |", cmd_line);
|
||||
|
||||
SECURITY_ATTRIBUTES pipe_sec_attr = { 0 };
|
||||
pipe_sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
pipe_sec_attr.lpSecurityDescriptor = nullptr;
|
||||
pipe_sec_attr.bInheritHandle = TRUE;
|
||||
HANDLE pipe_read = nullptr;
|
||||
HANDLE pipe_child_write = nullptr;
|
||||
CreatePipe(&pipe_read, &pipe_child_write, &pipe_sec_attr, 4096);
|
||||
|
||||
STARTUPINFOA si = { 0 };
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
si.hStdOutput = pipe_child_write;
|
||||
si.hStdError = pipe_child_write;
|
||||
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
BOOL p_ret = CreateProcessA(NULL, const_cast<LPSTR>(cmd_line.c_str()), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
|
||||
if (p_ret) {
|
||||
std::string pipe_str;
|
||||
DWORD read_num = 0;
|
||||
DWORD std_num = 0;
|
||||
do {
|
||||
while (::PeekNamedPipe(pipe_read, NULL, 0, NULL, &read_num, NULL) && read_num > 0) {
|
||||
char* pipe_buffer = new char[read_num];
|
||||
BOOL read_ret = ::ReadFile(pipe_read, pipe_buffer, read_num, &std_num, NULL);
|
||||
if (read_ret) {
|
||||
pipe_str.append(pipe_buffer, pipe_buffer + std_num);
|
||||
}
|
||||
if (pipe_buffer != nullptr) {
|
||||
delete[] pipe_buffer;
|
||||
pipe_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
} while (::WaitForSingleObject(pi.hProcess, 0) == WAIT_TIMEOUT);
|
||||
|
||||
DWORD exit_ret = -1;
|
||||
::GetExitCodeProcess(pi.hProcess, &exit_ret);
|
||||
log.trace("curl say:", pipe_str);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
::CloseHandle(pipe_read);
|
||||
::CloseHandle(pipe_child_write);
|
||||
return true;
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#include "ProcessTaskImageAnalyzer.h"
|
||||
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "MatchImageAnalyzer.h"
|
||||
#include "OcrImageAnalyzer.h"
|
||||
#include "Resource.h"
|
||||
|
||||
asst::ProcessTaskImageAnalyzer::ProcessTaskImageAnalyzer(const cv::Mat& image, std::vector<std::string> tasks_name)
|
||||
: AbstractImageAnalyzer(image),
|
||||
m_tasks_name(std::move(tasks_name))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
asst::ProcessTaskImageAnalyzer::~ProcessTaskImageAnalyzer() = default;
|
||||
|
||||
bool asst::ProcessTaskImageAnalyzer::match_analyze(std::shared_ptr<TaskInfo> task_ptr)
|
||||
{
|
||||
if (!m_match_analyzer) {
|
||||
m_match_analyzer = std::make_unique<MatchImageAnalyzer>(m_image);
|
||||
}
|
||||
const auto match_task_ptr = std::dynamic_pointer_cast<MatchTaskInfo>(task_ptr);
|
||||
m_match_analyzer->set_task_info(*match_task_ptr);
|
||||
m_match_analyzer->correct_roi();
|
||||
|
||||
if (m_match_analyzer->analyze()) {
|
||||
m_result = match_task_ptr;
|
||||
m_result_rect = m_match_analyzer->get_result().rect;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool asst::ProcessTaskImageAnalyzer::ocr_analyze(std::shared_ptr<TaskInfo> task_ptr)
|
||||
{
|
||||
std::shared_ptr<OcrTaskInfo> ocr_task_ptr = std::dynamic_pointer_cast<OcrTaskInfo>(task_ptr);
|
||||
|
||||
// 先尝试从缓存的结果里找
|
||||
for (const TextRect& tr : m_ocr_cache) {
|
||||
TextRect temp = tr;
|
||||
for (const auto& [old_str, new_str] : ocr_task_ptr->replace_map) {
|
||||
temp.text = utils::string_replace_all(temp.text, old_str, new_str);
|
||||
}
|
||||
for (const auto& text : ocr_task_ptr->text) {
|
||||
bool flag = false;
|
||||
if (ocr_task_ptr->need_full_match) {
|
||||
if (temp.text == text) {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
else if (temp.text.find(text) != std::string::npos) {
|
||||
flag = true;
|
||||
}
|
||||
// 即使找到了,也得在ROI里才行,不然过滤掉
|
||||
if (flag && ocr_task_ptr->roi.include(tr.rect)) {
|
||||
m_result = ocr_task_ptr;
|
||||
m_result_rect = tr.rect;
|
||||
log.trace("ProcessTaskImageAnalyzer::ocr_analyze | found in cache", tr.to_string());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_ocr_analyzer) {
|
||||
m_ocr_analyzer = std::make_unique<OcrImageAnalyzer>(m_image);
|
||||
}
|
||||
m_ocr_analyzer->set_required(ocr_task_ptr->text);
|
||||
m_ocr_analyzer->set_replace(ocr_task_ptr->replace_map);
|
||||
|
||||
// 识别区域文字,并加入缓存
|
||||
auto analyze_roi = [&](const Rect& roi, bool is_appeared = false) -> bool {
|
||||
m_ocr_analyzer->set_roi(roi);
|
||||
m_ocr_analyzer->correct_roi();
|
||||
bool ret = m_ocr_analyzer->analyze();
|
||||
|
||||
const auto& ocr_result = m_ocr_analyzer->get_result();
|
||||
m_ocr_cache.insert(m_ocr_cache.end(), ocr_result.begin(), ocr_result.end());
|
||||
if (ret) {
|
||||
auto& res = ocr_result.front();
|
||||
m_result = ocr_task_ptr;
|
||||
m_result_rect = res.rect;
|
||||
if (!is_appeared) {
|
||||
ocr_task_ptr->region_of_appeared.emplace(res.rect);
|
||||
}
|
||||
log.trace("ProcessTaskImageAnalyzer::ocr_analyze | found", res.to_string(), "roi :", roi.to_string());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// 在曾经识别到过的历史区域里识别
|
||||
for (const Rect& region : ocr_task_ptr->region_of_appeared) {
|
||||
static auto& max_width = WindowWidthDefault;
|
||||
static auto& max_height = WindowHeightDefault;
|
||||
bool ret = analyze_roi(region.center_zoom(2.0, max_width, max_height), true);
|
||||
if (ret) {
|
||||
log.trace("ProcessTaskImageAnalyzer::ocr_analyze | found in appeared");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 都没有的话,再完整的识别整个ROI
|
||||
return analyze_roi(ocr_task_ptr->roi);
|
||||
}
|
||||
|
||||
void asst::ProcessTaskImageAnalyzer::reset() noexcept
|
||||
{
|
||||
m_ocr_cache.clear();
|
||||
m_ocr_analyzer = nullptr;
|
||||
m_match_analyzer = nullptr;
|
||||
}
|
||||
|
||||
bool asst::ProcessTaskImageAnalyzer::analyze()
|
||||
{
|
||||
m_result = nullptr;
|
||||
m_result_rect = Rect();
|
||||
|
||||
for (const std::string& task_name : m_tasks_name) {
|
||||
auto task_ptr = task.get(task_name);
|
||||
|
||||
switch (task_ptr->algorithm) {
|
||||
case AlgorithmType::JustReturn:
|
||||
m_result = task_ptr;
|
||||
return true;
|
||||
case AlgorithmType::MatchTemplate:
|
||||
if (match_analyze(task_ptr)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case AlgorithmType::OcrDetect:
|
||||
if (ocr_analyze(task_ptr)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void asst::ProcessTaskImageAnalyzer::set_image(const cv::Mat & image)
|
||||
{
|
||||
AbstractImageAnalyzer::set_image(image);
|
||||
reset();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace asst
|
||||
{
|
||||
constexpr static const char* Version = "v2.2";
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "AbstractConfiger.h"
|
||||
|
||||
#include <json.h>
|
||||
#include <meojson/json.h>
|
||||
|
||||
#include "AsstUtils.hpp"
|
||||
|
||||
@@ -43,7 +43,7 @@ void asst::AbstractImageAnalyzer::set_roi(const Rect& roi) noexcept
|
||||
|
||||
void asst::AbstractImageAnalyzer::correct_roi() noexcept
|
||||
{
|
||||
m_roi = ctrler.shaped_correct(m_roi);
|
||||
m_roi = Ctrler.shaped_correct(m_roi);
|
||||
}
|
||||
|
||||
asst::Rect asst::AbstractImageAnalyzer::empty_rect_to_full(const Rect& rect, const cv::Mat& image) noexcept
|
||||
1
src/MeoAssistant/AbstractResource.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "AbstractResource.h"
|
||||
@@ -29,7 +29,7 @@ bool asst::AbstractTask::run()
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
int delay = resource.cfg().get_options().task_delay;
|
||||
int delay = Resrc.cfg().get_options().task_delay;
|
||||
sleep(delay);
|
||||
|
||||
if (!on_run_fails()) {
|
||||
@@ -47,7 +47,7 @@ bool AbstractTask::sleep(unsigned millisecond)
|
||||
if (millisecond == 0) {
|
||||
return true;
|
||||
}
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
long long duration = 0;
|
||||
|
||||
json::value callback_json;
|
||||
@@ -56,7 +56,7 @@ bool AbstractTask::sleep(unsigned millisecond)
|
||||
|
||||
while (!need_exit() && duration < millisecond) {
|
||||
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now() - start)
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count();
|
||||
std::this_thread::yield();
|
||||
}
|
||||
@@ -94,6 +94,6 @@ void asst::AbstractTask::click_return_button()
|
||||
|
||||
Rect ReturnButtonRect = return_task_ptr->specific_rect;
|
||||
|
||||
ctrler.click(ReturnButtonRect);
|
||||
Ctrler.click(ReturnButtonRect);
|
||||
sleep(return_task_ptr->rear_delay);
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace asst
|
||||
void set_retry_times(int times) noexcept { m_retry_times = times; }
|
||||
void set_task_chain(std::string name) noexcept { m_task_chain = std::move(name); }
|
||||
const std::string& get_task_chain() const noexcept { return m_task_chain; }
|
||||
|
||||
|
||||
constexpr static int RetryTimesDefault = 20;
|
||||
protected:
|
||||
virtual bool _run() = 0;
|
||||
145
src/MeoAssistant/AipOcr.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#include "AipOcr.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <meojson/json.h>
|
||||
#include <cpp-base64/base64.hpp>
|
||||
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "Resource.h"
|
||||
|
||||
bool asst::AipOcr::request_access_token(const std::string& client_id, const std::string& client_secret)
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
m_access_token.clear();
|
||||
|
||||
std::string_view cmd_fmt =
|
||||
R"(curl -s -k "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s")";
|
||||
|
||||
constexpr int cmd_len = 256;
|
||||
char cmd[cmd_len] = { 0 };
|
||||
sprintf_s(cmd, cmd_len, cmd_fmt.data(), client_id.c_str(), client_secret.c_str());
|
||||
|
||||
Log.trace("call cmd:", cmd);
|
||||
|
||||
std::string response = utils::callcmd(cmd);
|
||||
|
||||
Log.trace("response:", response);
|
||||
|
||||
auto parse_res = json::parse(response);
|
||||
if (!parse_res) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
auto json = parse_res.value();
|
||||
m_access_token = json.at("access_token").as_string();
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asst::AipOcr::request_ocr_general(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred)
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
if (m_access_token.empty()) {
|
||||
auto& cfg = Resrc.cfg().get_options().aip_ocr;
|
||||
request_access_token(cfg.client_id, cfg.client_secret);
|
||||
}
|
||||
|
||||
std::string_view cmd_fmt =
|
||||
R"(curl -s -k "https://aip.baidubce.com/rest/2.0/ocr/v1/general?access_token=%s" --data "image=%s" -H "Content-Type:application/x-www-form-urlencoded")";
|
||||
|
||||
return request_ocr_and_parse(cmd_fmt, image, out_result, pred);
|
||||
}
|
||||
|
||||
bool asst::AipOcr::request_ocr_accurate(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred)
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
if (m_access_token.empty()) {
|
||||
auto& cfg = Resrc.cfg().get_options().aip_ocr;
|
||||
request_access_token(cfg.client_id, cfg.client_secret);
|
||||
}
|
||||
|
||||
std::string_view cmd_fmt =
|
||||
R"(curl -s -k "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=%s" --data "image=%s" -H "Content-Type:application/x-www-form-urlencoded")";
|
||||
|
||||
return request_ocr_and_parse(cmd_fmt, image, out_result, pred);
|
||||
}
|
||||
|
||||
bool asst::AipOcr::request_ocr_and_parse(std::string_view cmd_fmt, const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred)
|
||||
{
|
||||
if (m_access_token.empty()) {
|
||||
return false;
|
||||
}
|
||||
// CreateProcess 最大只能接受 32767 chars,一张图片随便就超过了
|
||||
// 这个功能暂时没法用,得集成下 libcurl 或者别的
|
||||
std::vector<uchar> buf;
|
||||
cv::imencode(".png", image, buf);
|
||||
auto* enc_msg = reinterpret_cast<unsigned char*>(buf.data());
|
||||
std::string encoded = base64_encode(enc_msg, buf.size());
|
||||
|
||||
size_t cmd_len = encoded.size() + cmd_fmt.size() + m_access_token.size();
|
||||
char* cmd = new char[cmd_len];
|
||||
memset(cmd, 0, cmd_len);
|
||||
sprintf_s(cmd, cmd_len, cmd_fmt.data(), m_access_token.c_str(), encoded.c_str());
|
||||
|
||||
Log.trace("call cmd:", cmd);
|
||||
std::string response = utils::callcmd(cmd);
|
||||
delete[] cmd;
|
||||
Log.trace("response:", response);
|
||||
|
||||
auto parse_res = json::parse(response);
|
||||
if (!parse_res) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
auto json = parse_res.value();
|
||||
return parse_response(json, out_result, pred);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool asst::AipOcr::parse_response(const json::value& json, std::vector<TextRect>& out_result, const TextRectProc& pred)
|
||||
{
|
||||
if (!json.exist("words_result")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<TextRect> result;
|
||||
std::string log_str_raw;
|
||||
std::string log_str_proc;
|
||||
for (const auto& word : json.at("words_result").as_array()) {
|
||||
std::string text = word.at("words").as_string();
|
||||
|
||||
auto& loc = word.at("location").as_object();
|
||||
int left = loc.at("left").as_integer();
|
||||
int right = loc.at("right").as_integer();
|
||||
int top = loc.at("top").as_integer();
|
||||
int bottom = loc.at("bottom").as_integer();
|
||||
|
||||
Rect rect(left, top, right - left, bottom - top);
|
||||
|
||||
TextRect tr{ text, rect, 0 };
|
||||
|
||||
log_str_raw += tr.to_string() + ", ";
|
||||
if (!pred || pred(tr)) {
|
||||
log_str_proc += tr.to_string() + ", ";
|
||||
result.emplace_back(std::move(tr));
|
||||
}
|
||||
}
|
||||
|
||||
Log.trace("AipOcr::parse_response | raw : ", log_str_raw);
|
||||
Log.trace("AipOcr::parse_response | proc : ", log_str_proc);
|
||||
|
||||
out_result = result;
|
||||
return true;
|
||||
}
|
||||
43
src/MeoAssistant/AipOcr.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "AsstDef.h"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
class Mat;
|
||||
}
|
||||
namespace json
|
||||
{
|
||||
class value;
|
||||
}
|
||||
|
||||
namespace asst
|
||||
{
|
||||
class AipOcr
|
||||
{
|
||||
public:
|
||||
~AipOcr() = default;
|
||||
|
||||
static AipOcr& get_instance()
|
||||
{
|
||||
static AipOcr unique_instance;
|
||||
return unique_instance;
|
||||
}
|
||||
|
||||
bool request_access_token(const std::string& client_id, const std::string& client_secret);
|
||||
bool request_ocr_general(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
|
||||
bool request_ocr_accurate(const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
|
||||
|
||||
private:
|
||||
AipOcr() = default;
|
||||
AipOcr(const AipOcr&) = default;
|
||||
AipOcr(AipOcr&&) noexcept = default;
|
||||
|
||||
bool request_ocr_and_parse(std::string_view cmd_fmt, const cv::Mat& image, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
|
||||
bool parse_response(const json::value& json, std::vector<TextRect>& out_result, const TextRectProc& pred = nullptr);
|
||||
|
||||
std::string m_access_token;
|
||||
};
|
||||
}
|
||||
@@ -23,11 +23,11 @@ namespace asst
|
||||
class Controller;
|
||||
class Identify;
|
||||
|
||||
class Assistance
|
||||
class Assistant
|
||||
{
|
||||
public:
|
||||
Assistance(AsstCallback callback = nullptr, void* callback_arg = nullptr);
|
||||
~Assistance();
|
||||
Assistant(std::string dirname, AsstCallback callback = nullptr, void* callback_arg = nullptr);
|
||||
~Assistant();
|
||||
|
||||
// 根据配置文件,决定捕获模拟器、USB 还是远程设备
|
||||
bool catch_default();
|
||||
@@ -38,8 +38,10 @@ namespace asst
|
||||
// 不实际进行捕获,调试用接口
|
||||
bool catch_fake();
|
||||
|
||||
// 添加开始游戏的任务(进入到主界面)
|
||||
bool append_start_up(bool only_append = true);
|
||||
// 添加刷理智任务
|
||||
bool append_fight(int mecidine = 0, int stone = 0, int times = INT_MAX, bool only_append = true);
|
||||
bool append_fight(const std::string& stage, int mecidine = 0, int stone = 0, int times = INT_MAX, bool only_append = true);
|
||||
// 添加领取日常任务奖励任务
|
||||
bool append_award(bool only_append = true);
|
||||
// 添加访问好友任务
|
||||
@@ -52,9 +54,9 @@ namespace asst
|
||||
|
||||
// 添加自动公招任务
|
||||
// 参数max_times: 最多进行几次公招
|
||||
// 参数required_level: 需要的选择Tags的等级
|
||||
// 参数select_level: 需要的选择Tags的等级
|
||||
// 参数confirm_level: 需要点击确认按钮的等级
|
||||
bool append_recruit(unsigned max_times, const std::vector<int>& required_level, const std::vector<int>& confirm_level, bool need_refresh);
|
||||
bool append_recruit(unsigned max_times, const std::vector<int>& select_level, const std::vector<int>& confirm_level, bool need_refresh);
|
||||
|
||||
#ifdef LOG_TRACE
|
||||
// 调试用
|
||||
@@ -62,7 +64,7 @@ namespace asst
|
||||
#endif
|
||||
|
||||
// 开始公开招募计算
|
||||
bool start_recruit_calc(const std::vector<int>& required_level, bool set_time);
|
||||
bool start_recruit_calc(const std::vector<int>& select_level, bool set_time);
|
||||
|
||||
// 开始执行任务队列
|
||||
bool start(bool block = true);
|
||||
@@ -76,6 +78,7 @@ namespace asst
|
||||
|
||||
static constexpr int ProcessTaskRetryTimesDefault = 20;
|
||||
static constexpr int OpenRecruitTaskRetryTimesDefault = 10;
|
||||
static constexpr int AutoRecruitTaskRetryTimesDefault = 5;
|
||||
|
||||
private:
|
||||
void working_proc();
|
||||
@@ -88,6 +91,7 @@ namespace asst
|
||||
json::value organize_stage_drop(const json::value& rec); // 整理关卡掉落的材料信息
|
||||
|
||||
bool m_inited = false;
|
||||
std::string m_dirname;
|
||||
|
||||
bool m_thread_exit = false;
|
||||
std::queue<std::shared_ptr<AbstractTask>> m_tasks_queue;
|
||||
259
src/MeoAssistant/AsstCaller.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#include "AsstCaller.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <meojson/json_value.h>
|
||||
|
||||
#include "Assistant.h"
|
||||
#include "AsstDef.h"
|
||||
#include "AsstUtils.hpp"
|
||||
#include "Version.h"
|
||||
|
||||
#if 0
|
||||
#if _MSC_VER
|
||||
// Win32平台下Dll的入口
|
||||
BOOL APIENTRY DllMain(HINSTANCE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hModule);
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#elif VA_GNUC
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
AsstCallback _callback = nullptr;
|
||||
|
||||
void CallbackTrans(asst::AsstMsg msg, const json::value& json, void* custom_arg)
|
||||
{
|
||||
_callback(static_cast<int>(msg), asst::utils::utf8_to_gbk(json.to_string()).c_str(), custom_arg);
|
||||
}
|
||||
|
||||
asst::Assistant* AsstCreate(const char* dirname)
|
||||
{
|
||||
try {
|
||||
return new asst::Assistant(dirname);
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
asst::Assistant* AsstCreateEx(const char* dirname, AsstCallback callback, void* custom_arg)
|
||||
{
|
||||
try {
|
||||
// 创建多实例回调会有问题,有空再慢慢整
|
||||
_callback = callback;
|
||||
return new asst::Assistant(dirname, CallbackTrans, custom_arg);
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AsstDestroy(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete p_asst;
|
||||
p_asst = nullptr;
|
||||
}
|
||||
|
||||
bool AsstCatchDefault(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistant*)p_asst)->catch_default();
|
||||
}
|
||||
|
||||
bool AsstCatchEmulator(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistant*)p_asst)->catch_emulator();
|
||||
}
|
||||
|
||||
bool AsstCatchCustom(asst::Assistant* p_asst, const char* address)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((asst::Assistant*)p_asst)->catch_custom(address);
|
||||
}
|
||||
|
||||
bool AsstCatchFake(asst::Assistant* p_asst)
|
||||
{
|
||||
#ifdef LOG_TRACE
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->catch_fake();
|
||||
#else
|
||||
return false;
|
||||
#endif // LOG_TRACE
|
||||
}
|
||||
|
||||
bool ASSTAPI AsstAppendStartUp(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->append_start_up();
|
||||
}
|
||||
|
||||
bool AsstAppendFight(asst::Assistant* p_asst, const char* stage, int max_mecidine, int max_stone, int max_times)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->append_fight(stage, max_mecidine, max_stone, max_times);
|
||||
}
|
||||
|
||||
bool AsstAppendAward(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->append_award();
|
||||
}
|
||||
|
||||
bool AsstAppendVisit(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->append_visit();
|
||||
}
|
||||
|
||||
bool AsstAppendMall(asst::Assistant* p_asst, bool with_shopping)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->append_mall(with_shopping);
|
||||
}
|
||||
|
||||
//bool AsstAppendProcessTask(asst::Assistant* p_asst, const char* task)
|
||||
//{
|
||||
// if (p_asst == nullptr) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return p_asst->append_process_task(task);
|
||||
//}
|
||||
|
||||
bool AsstStartRecruitCalc(asst::Assistant* p_asst, const int select_level[], int required_len, bool set_time)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<int> level_vector;
|
||||
level_vector.assign(select_level, select_level + required_len);
|
||||
return p_asst->start_recruit_calc(level_vector, set_time);
|
||||
}
|
||||
|
||||
bool AsstAppendInfrast(asst::Assistant* p_asst, int work_mode, const char** order, int order_size, const char* uses_of_drones, double dorm_threshold)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> order_vector;
|
||||
order_vector.assign(order, order + order_size);
|
||||
|
||||
return p_asst->append_infrast(
|
||||
static_cast<asst::infrast::WorkMode>(work_mode),
|
||||
order_vector,
|
||||
uses_of_drones,
|
||||
dorm_threshold);
|
||||
}
|
||||
|
||||
bool AsstAppendRecruit(asst::Assistant* p_asst, int max_times, const int select_level[], int select_len, const int confirm_level[], int confirm_len, bool need_refresh)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<int> required_vector;
|
||||
required_vector.assign(select_level, select_level + select_len);
|
||||
std::vector<int> confirm_vector;
|
||||
confirm_vector.assign(confirm_level, confirm_level + confirm_len);
|
||||
|
||||
return p_asst->append_recruit(max_times, required_vector, confirm_vector, need_refresh);
|
||||
}
|
||||
|
||||
bool AsstStart(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->start();
|
||||
}
|
||||
|
||||
bool AsstStop(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_asst->stop();
|
||||
}
|
||||
|
||||
bool AsstSetPenguinId(asst::Assistant* p_asst, const char* id)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
p_asst->set_penguin_id(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool AsstSetParam(asst::Assistant* p_asst, const char* type, const char* param, const char* value)
|
||||
//{
|
||||
// if (p_asst == nullptr) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return p_asst->set_param(type, param, value);
|
||||
//}
|
||||
|
||||
const char* AsstGetVersion()
|
||||
{
|
||||
return asst::Version;
|
||||
}
|
||||
|
||||
bool AsstAppendDebug(asst::Assistant* p_asst)
|
||||
{
|
||||
if (p_asst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
#if LOG_TRACE
|
||||
return p_asst->append_debug();
|
||||
#else
|
||||
return false;
|
||||
#endif // LOG_TRACE
|
||||
}
|
||||
@@ -20,7 +20,6 @@ namespace asst
|
||||
constexpr static int WindowHeightDefault = 720;
|
||||
|
||||
constexpr static double TemplThresholdDefault = 0.8;
|
||||
constexpr static double HistThresholdDefault = 0.8;
|
||||
|
||||
struct Point
|
||||
{
|
||||
@@ -46,6 +45,10 @@ namespace asst
|
||||
{
|
||||
return { x, y, static_cast<int>(width * rhs), static_cast<int>(height * rhs) };
|
||||
}
|
||||
int area() const noexcept
|
||||
{
|
||||
return width * height;
|
||||
}
|
||||
Rect center_zoom(double scale, int max_width = INT_MAX, int max_height = INT_MAX) const
|
||||
{
|
||||
int half_width_scale = static_cast<int>(width * (1 - scale) / 2);
|
||||
@@ -98,7 +101,7 @@ namespace asst
|
||||
explicit operator Rect() const noexcept { return rect; }
|
||||
std::string to_string() const
|
||||
{
|
||||
return text + " : " + rect.to_string();
|
||||
return text + " : " + rect.to_string() + ", score: " + std::to_string(score);
|
||||
}
|
||||
TextRect& operator=(const TextRect&) = default;
|
||||
TextRect& operator=(TextRect&&) noexcept = default;
|
||||
@@ -109,6 +112,7 @@ namespace asst
|
||||
|
||||
std::string text;
|
||||
Rect rect;
|
||||
float score;
|
||||
};
|
||||
using TextRectProc = std::function<bool(TextRect&)>;
|
||||
|
||||
@@ -196,6 +200,8 @@ namespace asst
|
||||
int retry_times = INT_MAX; // 未找到图像时的重试次数
|
||||
Rect roi; // 要识别的区域,若为0则全图识别
|
||||
Rect rect_move; // 识别结果移动:有些结果识别到的,和要点击的不是同一个位置。即识别到了res,点击res + result_move的位置
|
||||
bool cache = false; // 是否使用缓存区域
|
||||
Rect region_of_appeared; // 缓存区域:上次识别成功过,本次只在这个rect里识别,省点性能
|
||||
};
|
||||
|
||||
// 文字识别任务的信息
|
||||
@@ -206,8 +212,6 @@ namespace asst
|
||||
bool need_full_match = false; // 是否需要全匹配,否则搜索到子串就算匹配上了
|
||||
std::unordered_map<std::string, std::string>
|
||||
replace_map; // 部分文字容易识别错,字符串强制replace之后,再进行匹配
|
||||
bool cache = false; // 是否使用历史区域
|
||||
std::unordered_set<Rect> region_of_appeared; // 曾经出现过的区域:上次处理该任务时,在一些rect里识别到过text,这次优先在这些rect里识别,省点性能
|
||||
};
|
||||
|
||||
// 图片匹配任务的信息
|
||||
@@ -216,9 +220,8 @@ namespace asst
|
||||
virtual ~MatchTaskInfo() = default;
|
||||
std::string templ_name; // 匹配模板图片文件名
|
||||
double templ_threshold = 0; // 模板匹配阈值
|
||||
double hist_threshold = 0; // 直方图比较阈值
|
||||
double special_threshold = 0; // 某些任务使用的特殊的阈值
|
||||
std::pair<int, int> mask_range; // 掩码的二值化范围
|
||||
bool cache = false; // 是否使用缓存(直方图),false时就一直用模板匹配。默认为true
|
||||
};
|
||||
|
||||
struct HandleInfo
|
||||
@@ -239,6 +242,7 @@ namespace asst
|
||||
std::string display;
|
||||
std::string display_format;
|
||||
std::string screencap;
|
||||
std::string release;
|
||||
//std::string pullscreen;
|
||||
int display_width = 0;
|
||||
int display_height = 0;
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <ostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <json.h>
|
||||
#include <meojson/json.h>
|
||||
|
||||
namespace asst
|
||||
{
|
||||
@@ -24,8 +24,8 @@ namespace asst
|
||||
ReachedLimit, // 单个原子任务达到次数上限
|
||||
ReadyToSleep, // 准备开始睡眠
|
||||
EndOfSleep, // 睡眠结束
|
||||
AppendProcessTask, // [已弃用] 新增流程任务,Assistance内部消息,外部不需要处理
|
||||
AppendTask, // [已弃用] 新增任务,Assistance内部消息,外部不需要处理
|
||||
AppendProcessTask, // [已弃用] 新增流程任务,Assistant内部消息,外部不需要处理
|
||||
AppendTask, // [已弃用] 新增任务,Assistant内部消息,外部不需要处理
|
||||
TaskCompleted, // 单个原子任务完成
|
||||
PrintWindow, // 截图消息
|
||||
ProcessTaskStopAction, // 流程任务执行到了Stop的动作
|
||||
@@ -43,6 +43,7 @@ namespace asst
|
||||
RecruitSpecialTag, // 公招识别到了特殊的Tag
|
||||
RecruitResult, // 公开招募结果
|
||||
RecruitSelected, // 选择了Tags
|
||||
RecruitError, // 公招错误
|
||||
/* Infrast Msg */
|
||||
InfrastSkillsDetected = 4000, // 识别到了基建技能(当前页面)
|
||||
InfrastSkillsResult, // 识别到的所有可用技能
|
||||
@@ -64,6 +65,7 @@ namespace asst
|
||||
{ AsstMsg::ImageMatched, "ImageMatched" },
|
||||
{ AsstMsg::StageDrops, "StageDrops" },
|
||||
{ AsstMsg::TaskMatched, "TaskMatched" },
|
||||
{ AsstMsg::RecruitError, "RecruitError" },
|
||||
{ AsstMsg::ReachedLimit, "ReachedLimit" },
|
||||
{ AsstMsg::ReadyToSleep, "ReadyToSleep" },
|
||||
{ AsstMsg::EndOfSleep, "EndOfSleep" },
|
||||
@@ -10,24 +10,6 @@ namespace asst
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
static std::string get_cur_dir()
|
||||
{
|
||||
static std::string cur_dir;
|
||||
if (cur_dir.empty()) {
|
||||
char exepath_buff[_MAX_PATH] = { 0 };
|
||||
::GetModuleFileNameA(NULL, exepath_buff, _MAX_PATH);
|
||||
std::string exepath(exepath_buff);
|
||||
cur_dir = exepath.substr(0, exepath.find_last_of('\\') + 1);
|
||||
}
|
||||
return cur_dir;
|
||||
}
|
||||
|
||||
static std::string get_resource_dir()
|
||||
{
|
||||
static std::string res_dir = get_cur_dir() + "resource\\";
|
||||
return res_dir;
|
||||
}
|
||||
|
||||
static std::string string_replace_all(const std::string& src, const std::string& old_value, const std::string& new_value)
|
||||
{
|
||||
std::string str = src;
|
||||
@@ -153,6 +135,56 @@ namespace asst
|
||||
return dist;
|
||||
}
|
||||
|
||||
static std::string callcmd(const std::string& cmdline)
|
||||
{
|
||||
SECURITY_ATTRIBUTES pipe_sec_attr = { 0 };
|
||||
pipe_sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
pipe_sec_attr.lpSecurityDescriptor = nullptr;
|
||||
pipe_sec_attr.bInheritHandle = TRUE;
|
||||
HANDLE pipe_read = nullptr;
|
||||
HANDLE pipe_child_write = nullptr;
|
||||
CreatePipe(&pipe_read, &pipe_child_write, &pipe_sec_attr, 4096);
|
||||
|
||||
STARTUPINFOA si = { 0 };
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
si.hStdOutput = pipe_child_write;
|
||||
si.hStdError = pipe_child_write;
|
||||
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
BOOL p_ret = CreateProcessA(NULL, const_cast<LPSTR>(cmdline.c_str()), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
|
||||
std::string pipe_str;
|
||||
if (p_ret) {
|
||||
DWORD read_num = 0;
|
||||
DWORD std_num = 0;
|
||||
do {
|
||||
while (::PeekNamedPipe(pipe_read, NULL, 0, NULL, &read_num, NULL) && read_num > 0) {
|
||||
char* pipe_buffer = new char[read_num];
|
||||
BOOL read_ret = ::ReadFile(pipe_read, pipe_buffer, read_num, &std_num, NULL);
|
||||
if (read_ret) {
|
||||
pipe_str.append(pipe_buffer, pipe_buffer + std_num);
|
||||
}
|
||||
if (pipe_buffer != nullptr) {
|
||||
delete[] pipe_buffer;
|
||||
pipe_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
} while (::WaitForSingleObject(pi.hProcess, 0) == WAIT_TIMEOUT);
|
||||
|
||||
DWORD exit_ret = -1;
|
||||
::GetExitCodeProcess(pi.hProcess, &exit_ret);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
::CloseHandle(pipe_read);
|
||||
::CloseHandle(pipe_child_write);
|
||||
|
||||
return pipe_str;
|
||||
}
|
||||
|
||||
//template<typename T,
|
||||
// typename = typename std::enable_if<std::is_constructible<T, std::string>::value>::type>
|
||||
// std::string VectorToString(const std::vector<T>& vector, bool to_gbk = false) {
|
||||
@@ -2,93 +2,95 @@
|
||||
|
||||
#include "Resource.h"
|
||||
#include "OcrImageAnalyzer.h"
|
||||
#include "Controller.h"
|
||||
#include "RecruitImageAnalyzer.h"
|
||||
#include "ProcessTask.h"
|
||||
#include "Controller.h"
|
||||
#include "RecruitImageAnalyzer.h"
|
||||
#include "ProcessTask.h"
|
||||
#include "RecruitTask.h"
|
||||
|
||||
void asst::AutoRecruitTask::set_required_level(std::vector<int> required_level) noexcept
|
||||
{
|
||||
m_required_level = std::move(required_level);
|
||||
}
|
||||
|
||||
void asst::AutoRecruitTask::set_confirm_level(std::vector<int> confirm_level) noexcept
|
||||
{
|
||||
m_confirm_level = std::move(confirm_level);
|
||||
}
|
||||
|
||||
void asst::AutoRecruitTask::set_need_refresh(bool need_refresh) noexcept
|
||||
{
|
||||
m_need_refresh = need_refresh;
|
||||
}
|
||||
|
||||
void asst::AutoRecruitTask::set_select_level(std::vector<int> select_level) noexcept
|
||||
{
|
||||
m_select_level = std::move(select_level);
|
||||
}
|
||||
|
||||
void asst::AutoRecruitTask::set_confirm_level(std::vector<int> confirm_level) noexcept
|
||||
{
|
||||
m_confirm_level = std::move(confirm_level);
|
||||
}
|
||||
|
||||
void asst::AutoRecruitTask::set_need_refresh(bool need_refresh) noexcept
|
||||
{
|
||||
m_need_refresh = need_refresh;
|
||||
}
|
||||
|
||||
void asst::AutoRecruitTask::set_max_times(int max_times) noexcept
|
||||
{
|
||||
m_max_times = max_times;
|
||||
}
|
||||
|
||||
bool asst::AutoRecruitTask::_run()
|
||||
{
|
||||
}
|
||||
|
||||
bool asst::AutoRecruitTask::_run()
|
||||
{
|
||||
json::value task_start_json = json::object{
|
||||
{ "task_type", "RecruitTask" },
|
||||
{ "task_chain", m_task_chain },
|
||||
};
|
||||
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
|
||||
|
||||
int delay = resource.cfg().get_options().task_delay;
|
||||
|
||||
auto image = ctrler.get_image();
|
||||
int delay = Resrc.cfg().get_options().task_delay;
|
||||
|
||||
auto image = Ctrler.get_image();
|
||||
OcrImageAnalyzer start_analyzer(image);
|
||||
const auto start_task_ptr = std::dynamic_pointer_cast<OcrTaskInfo>(task.get("StartRecruit"));
|
||||
start_analyzer.set_task_info(*start_task_ptr);
|
||||
|
||||
if (!start_analyzer.analyze()) {
|
||||
return false;
|
||||
if (!start_analyzer.analyze()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& start_res = start_analyzer.get_result();
|
||||
for (; m_cur_times < start_res.size() && m_cur_times < m_max_times; ++m_cur_times) {
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
Rect start_rect = start_res.at(m_cur_times).rect;
|
||||
ctrler.click(start_rect);
|
||||
sleep(delay);
|
||||
|
||||
while (true) {
|
||||
RecruitTask recurit_task(m_callback, m_callback_arg);
|
||||
recurit_task.set_retry_times(10);
|
||||
recurit_task.set_param(m_required_level, true);
|
||||
recurit_task.set_task_chain(m_task_chain);
|
||||
|
||||
// 识别错误,放弃这个公招位,直接返回
|
||||
if (!recurit_task.run()) {
|
||||
click_return_button();
|
||||
break;
|
||||
}
|
||||
|
||||
int maybe_level = recurit_task.get_maybe_level();
|
||||
|
||||
// 尝试刷新
|
||||
if (m_need_refresh && maybe_level == 3
|
||||
&& !recurit_task.get_has_special_tag()
|
||||
&& recurit_task.get_has_refresh()) {
|
||||
ProcessTask refresh_task(*this, { "RecruitRefresh" });
|
||||
if (refresh_task.run()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (std::find(m_confirm_level.cbegin(), m_confirm_level.cend(), maybe_level) != m_confirm_level.cend()) {
|
||||
ProcessTask confirm_task(*this, { "RecruitConfirm" });
|
||||
if (!confirm_task.run()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
click_return_button();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Rect start_rect = start_res.at(m_cur_times).rect;
|
||||
Ctrler.click(start_rect);
|
||||
sleep(delay);
|
||||
|
||||
while (true) {
|
||||
RecruitTask recurit_task(m_callback, m_callback_arg);
|
||||
recurit_task.set_retry_times(10);
|
||||
recurit_task.set_param(m_select_level, true);
|
||||
recurit_task.set_task_chain(m_task_chain);
|
||||
|
||||
// 识别错误,放弃这个公招位,直接返回
|
||||
if (!recurit_task.run()) {
|
||||
m_callback(AsstMsg::RecruitError, json::value(), m_callback_arg);
|
||||
click_return_button();
|
||||
break;
|
||||
}
|
||||
|
||||
int maybe_level = recurit_task.get_maybe_level();
|
||||
|
||||
// 尝试刷新
|
||||
if (m_need_refresh && maybe_level == 3
|
||||
&& !recurit_task.get_has_special_tag()
|
||||
&& recurit_task.get_has_refresh()) {
|
||||
ProcessTask refresh_task(*this, { "RecruitRefresh" });
|
||||
if (refresh_task.run()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (std::find(m_confirm_level.cbegin(), m_confirm_level.cend(), maybe_level) != m_confirm_level.cend()) {
|
||||
ProcessTask confirm_task(*this, { "RecruitConfirm" });
|
||||
if (!confirm_task.run()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
click_return_button();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace asst
|
||||
using AbstractTask::AbstractTask;
|
||||
virtual ~AutoRecruitTask() = default;
|
||||
|
||||
void set_required_level(std::vector<int> required_level) noexcept;
|
||||
void set_select_level(std::vector<int> select_level) noexcept;
|
||||
void set_confirm_level(std::vector<int> confirm_level) noexcept;
|
||||
void set_need_refresh(bool need_refresh) noexcept;
|
||||
void set_max_times(int max_times) noexcept;
|
||||
@@ -17,7 +17,7 @@ namespace asst
|
||||
protected:
|
||||
virtual bool _run() override;
|
||||
|
||||
std::vector<int> m_required_level;
|
||||
std::vector<int> m_select_level;
|
||||
std::vector<int> m_confirm_level;
|
||||
bool m_need_refresh = false;
|
||||
int m_max_times = 0;
|
||||
@@ -98,6 +98,7 @@ bool asst::Controller::connect_adb(const std::string& address)
|
||||
m_emulator_info.adb.click = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.click, "[Adb]", m_adb_path), "[Address]", address);
|
||||
m_emulator_info.adb.swipe = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.swipe, "[Adb]", m_adb_path), "[Address]", address);
|
||||
m_emulator_info.adb.screencap = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.screencap, "[Adb]", m_adb_path), "[Address]", address);
|
||||
m_emulator_info.adb.release = utils::string_replace_all(m_emulator_info.adb.release, "[Adb]", m_adb_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -115,6 +116,10 @@ asst::Controller::~Controller()
|
||||
m_cmd_thread.join();
|
||||
}
|
||||
|
||||
if (!m_emulator_info.adb.release.empty()) {
|
||||
call_command(m_emulator_info.adb.release);
|
||||
}
|
||||
|
||||
::CloseHandle(m_pipe_read);
|
||||
::CloseHandle(m_pipe_write);
|
||||
::CloseHandle(m_pipe_child_read);
|
||||
@@ -194,7 +199,7 @@ void asst::Controller::pipe_working_proc()
|
||||
}
|
||||
//else if (!m_thread_idle) { // 队列中没有任务,又不是闲置的时候,就去截图
|
||||
// cmd_queue_lock.unlock();
|
||||
// auto start_time = std::chrono::system_clock::now();
|
||||
// auto start_time = std::chrono::steady_clock::now();
|
||||
// screencap();
|
||||
// cmd_queue_lock.lock();
|
||||
// if (!m_cmd_queue.empty()) {
|
||||
@@ -211,14 +216,23 @@ void asst::Controller::pipe_working_proc()
|
||||
}
|
||||
}
|
||||
|
||||
void asst::Controller::set_dirname(std::string dirname) noexcept
|
||||
{
|
||||
m_dirname = std::move(dirname);
|
||||
}
|
||||
|
||||
bool asst::Controller::try_capture(const EmulatorInfo& info, bool without_handle)
|
||||
{
|
||||
LogTraceScope("try_capture | " + info.name);
|
||||
|
||||
if (!m_emulator_info.adb.release.empty()) {
|
||||
call_command(m_emulator_info.adb.release);
|
||||
}
|
||||
|
||||
const HandleInfo& handle_info = info.handle;
|
||||
|
||||
if (!without_handle) { // 使用模拟器自带的adb
|
||||
// 转成宽字符的
|
||||
// 转成宽字符的
|
||||
wchar_t* class_wbuff = nullptr;
|
||||
if (!handle_info.class_name.empty()) {
|
||||
size_t class_len = (handle_info.class_name.size() + 1) * 2;
|
||||
@@ -268,8 +282,8 @@ bool asst::Controller::try_capture(const EmulatorInfo& info, bool without_handle
|
||||
if (emulator_path.empty()) {
|
||||
return false;
|
||||
}
|
||||
resource.cfg().set_emulator_path(info.name, emulator_path);
|
||||
resource.user().set_emulator_path(info.name, emulator_path);
|
||||
Resrc.cfg().set_emulator_path(info.name, emulator_path);
|
||||
Resrc.user().set_emulator_path(info.name, emulator_path);
|
||||
}
|
||||
else {
|
||||
emulator_path = info.path;
|
||||
@@ -278,16 +292,16 @@ bool asst::Controller::try_capture(const EmulatorInfo& info, bool without_handle
|
||||
// 到这一步说明句柄和权限没问题了,接下来就是adb的事情了
|
||||
m_emulator_info = info;
|
||||
m_handle = window_handle;
|
||||
log.trace("Handle:", m_handle, "Name:", m_emulator_info.name);
|
||||
Log.trace("Handle:", m_handle, "Name:", m_emulator_info.name);
|
||||
|
||||
std::string adb_path = emulator_path.substr(0, emulator_path.find_last_of('\\') + 1);
|
||||
adb_path = '"' + utils::string_replace_all(m_emulator_info.adb.path, "[EmulatorPath]", adb_path) + '"';
|
||||
adb_path = utils::string_replace_all(adb_path, "[ExecDir]", utils::get_cur_dir());
|
||||
adb_path = utils::string_replace_all(adb_path, "[ExecDir]", m_dirname);
|
||||
m_adb_path = std::move(adb_path);
|
||||
}
|
||||
else { // 使用辅助自带的标准adb
|
||||
m_emulator_info = info;
|
||||
m_adb_path = '"' + utils::string_replace_all(m_emulator_info.adb.path, "[ExecDir]", utils::get_cur_dir()) + '"';
|
||||
m_adb_path = '"' + utils::string_replace_all(m_emulator_info.adb.path, "[ExecDir]", m_dirname) + '"';
|
||||
}
|
||||
|
||||
// 优先使用addresses里指定的地址
|
||||
@@ -316,7 +330,7 @@ bool asst::Controller::try_capture(const EmulatorInfo& info, bool without_handle
|
||||
address = smatch[1];
|
||||
}
|
||||
}
|
||||
log.trace("device address", address);
|
||||
Log.trace("device address", address);
|
||||
if (address.empty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -372,9 +386,9 @@ std::pair<bool, std::vector<unsigned char>> asst::Controller::call_command(const
|
||||
|
||||
::CloseHandle(process_info.hProcess);
|
||||
::CloseHandle(process_info.hThread);
|
||||
log.trace("Call", cmd, "ret", exit_ret, ", output size:", pipe_data.size());
|
||||
Log.trace("Call", cmd, "ret", exit_ret, ", output size:", pipe_data.size());
|
||||
if (!pipe_data.empty() && pipe_data.size() < 4096) {
|
||||
log.trace("output:", std::string(pipe_data.cbegin(), pipe_data.cend()));
|
||||
Log.trace("output:", std::string(pipe_data.cbegin(), pipe_data.cend()));
|
||||
}
|
||||
|
||||
return make_pair(!exit_ret, std::move(pipe_data));
|
||||
@@ -438,18 +452,18 @@ asst::Point asst::Controller::rand_point_in_rect(const Rect& rect)
|
||||
|
||||
void asst::Controller::random_delay() const
|
||||
{
|
||||
auto& opt = resource.cfg().get_options();
|
||||
auto& opt = Resrc.cfg().get_options();
|
||||
if (opt.control_delay_upper != 0) {
|
||||
LogTraceFunction;
|
||||
static std::default_random_engine rand_engine(
|
||||
std::chrono::system_clock::now().time_since_epoch().count());
|
||||
std::chrono::steady_clock::now().time_since_epoch().count());
|
||||
static std::uniform_int_distribution<unsigned> rand_uni(
|
||||
opt.control_delay_lower,
|
||||
opt.control_delay_upper);
|
||||
|
||||
unsigned rand_delay = rand_uni(rand_engine);
|
||||
|
||||
log.trace("random_delay |", rand_delay, "ms");
|
||||
Log.trace("random_delay |", rand_delay, "ms");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(rand_delay));
|
||||
}
|
||||
}
|
||||
@@ -482,12 +496,12 @@ bool asst::Controller::screencap()
|
||||
}
|
||||
m_cache_image = cv::imdecode(data, cv::IMREAD_COLOR);
|
||||
if (m_cache_image.empty()) {
|
||||
log.info("Data is not empty, but image is empty, try to convert lf");
|
||||
Log.info("Data is not empty, but image is empty, try to convert lf");
|
||||
convert_lf(data);
|
||||
m_cache_image = cv::imdecode(data, cv::IMREAD_COLOR);
|
||||
if (m_cache_image.empty()) {
|
||||
m_image_convert_lf = false;
|
||||
log.error("convert lf and retry decode falied!");
|
||||
Log.error("convert lf and retry decode falied!");
|
||||
return false;
|
||||
}
|
||||
m_image_convert_lf = true;
|
||||
@@ -496,7 +510,7 @@ bool asst::Controller::screencap()
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
log.error("Data is empty!");
|
||||
Log.error("Data is empty!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -522,7 +536,7 @@ int asst::Controller::click(const Rect& rect, bool block)
|
||||
int asst::Controller::click_without_scale(const Point& p, bool block)
|
||||
{
|
||||
if (p.x < 0 || p.x >= m_emulator_info.adb.display_width || p.y < 0 || p.y >= m_emulator_info.adb.display_height) {
|
||||
log.error("click point out of range");
|
||||
Log.error("click point out of range");
|
||||
}
|
||||
std::string cur_cmd = utils::string_replace_all(m_emulator_info.adb.click, "[x]", std::to_string(p.x));
|
||||
cur_cmd = utils::string_replace_all(cur_cmd, "[y]", std::to_string(p.y));
|
||||
@@ -557,7 +571,7 @@ int asst::Controller::swipe(const Rect& r1, const Rect& r2, int duration, bool b
|
||||
int asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int duration, bool block, int extra_delay, bool extra_swipe)
|
||||
{
|
||||
if (p1.x < 0 || p1.x >= m_emulator_info.adb.display_width || p1.y < 0 || p1.y >= m_emulator_info.adb.display_height || p2.x < 0 || p2.x >= m_emulator_info.adb.display_width || p2.y < 0 || p2.y >= m_emulator_info.adb.display_height) {
|
||||
log.error("swipe point out of range");
|
||||
Log.error("swipe point out of range");
|
||||
}
|
||||
std::string cur_cmd = utils::string_replace_all(m_emulator_info.adb.swipe, "[x1]", std::to_string(p1.x));
|
||||
cur_cmd = utils::string_replace_all(cur_cmd, "[y1]", std::to_string(p1.y));
|
||||
@@ -572,8 +586,8 @@ int asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int
|
||||
|
||||
int id = 0;
|
||||
|
||||
int extra_swipe_dist = resource.cfg().get_options().adb_extra_swipe_dist /* * m_control_scale*/;
|
||||
int extra_swipe_duration = resource.cfg().get_options().adb_extra_swipe_duration;
|
||||
int extra_swipe_dist = Resrc.cfg().get_options().adb_extra_swipe_dist /* * m_control_scale*/;
|
||||
int extra_swipe_duration = Resrc.cfg().get_options().adb_extra_swipe_duration;
|
||||
|
||||
// 额外的滑动:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来
|
||||
if (extra_swipe && extra_swipe_duration >= 0) {
|
||||
@@ -32,6 +32,8 @@ namespace asst
|
||||
return unique_instance;
|
||||
}
|
||||
|
||||
static void set_dirname(std::string dirname) noexcept;
|
||||
|
||||
bool try_capture(const EmulatorInfo& info, bool without_handle = false);
|
||||
cv::Mat get_image(bool raw = false);
|
||||
|
||||
@@ -72,6 +74,8 @@ namespace asst
|
||||
// 转换data中所有的crlf为lf:有些模拟器自带的adb,exec-out输出的\n,会被替换成\r\n,导致解码错误,所以这里转一下回来(点名批评mumu)
|
||||
static void convert_lf(std::vector<unsigned char>& data);
|
||||
|
||||
inline static std::string m_dirname;
|
||||
|
||||
bool m_thread_exit = false;
|
||||
//bool m_thread_idle = true;
|
||||
std::thread m_cmd_thread;
|
||||
@@ -101,5 +105,6 @@ namespace asst
|
||||
double m_control_scale = 1.0;
|
||||
};
|
||||
|
||||
static auto& ctrler = Controller::get_instance();
|
||||
//static auto& ctrler = Controller::get_instance();
|
||||
#define Ctrler Controller::get_instance()
|
||||
}
|
||||
@@ -98,4 +98,4 @@ bool asst::CreditShopImageAnalyzer::sold_out_analyze()
|
||||
}
|
||||
|
||||
return !m_result.empty();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ bool asst::CreditShoppingTask::_run()
|
||||
};
|
||||
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
|
||||
|
||||
const cv::Mat& image = ctrler.get_image();
|
||||
const cv::Mat& image = Ctrler.get_image();
|
||||
|
||||
CreditShopImageAnalyzer shop_analyzer(image);
|
||||
if (!shop_analyzer.analyze()) {
|
||||
@@ -31,7 +31,7 @@ bool asst::CreditShoppingTask::_run()
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
ctrler.click(commodity);
|
||||
Ctrler.click(commodity);
|
||||
|
||||
static int pre_delay = 1000;
|
||||
static int rare_delay = 1000;
|
||||
@@ -44,7 +44,7 @@ bool asst::CreditShoppingTask::_run()
|
||||
const auto buy_it_task_ptr = std::dynamic_pointer_cast<MatchTaskInfo>(
|
||||
task.get("CreditShop-BuyIt"));
|
||||
|
||||
const cv::Mat& buy_image = ctrler.get_image();
|
||||
const cv::Mat& buy_image = Ctrler.get_image();
|
||||
MatchImageAnalyzer buy_it_analyzer(buy_image);
|
||||
buy_it_analyzer.set_task_info(*buy_it_task_ptr);
|
||||
if (!buy_it_analyzer.analyze()) {
|
||||
@@ -59,11 +59,11 @@ bool asst::CreditShoppingTask::_run()
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
ctrler.click(buy_it_rect);
|
||||
Ctrler.click(buy_it_rect);
|
||||
sleep(rare_delay);
|
||||
|
||||
// 识别是否信用不足无法购买
|
||||
const cv::Mat& prompt_image = ctrler.get_image();
|
||||
const cv::Mat& prompt_image = Ctrler.get_image();
|
||||
|
||||
const auto no_money_task_ptr = std::dynamic_pointer_cast<OcrTaskInfo>(
|
||||
task.get("CreditShop-NoMoney"));
|
||||
@@ -75,7 +75,7 @@ bool asst::CreditShoppingTask::_run()
|
||||
}
|
||||
|
||||
// 这里随便点一下都行,把购买完弹出来物品的界面取消掉
|
||||
ctrler.click(buy_it_rect);
|
||||
Ctrler.click(buy_it_rect);
|
||||
sleep(rare_delay);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
#include "GeneralConfiger.h"
|
||||
|
||||
#include <json.h>
|
||||
#include <meojson/json.h>
|
||||
|
||||
bool asst::GeneralConfiger::parse(const json::value& json)
|
||||
{
|
||||
m_version = json.at("version").as_string();
|
||||
|
||||
const json::value& options_json = json.at("options");
|
||||
{
|
||||
const json::value& options_json = json.at("options");
|
||||
m_options.connect_type = static_cast<ConnectType>(options_json.at("connectType").as_integer());
|
||||
m_options.task_delay = options_json.at("taskDelay").as_integer();
|
||||
m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer();
|
||||
m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer();
|
||||
m_options.print_window = options_json.at("printWindow").as_boolean();
|
||||
m_options.penguin_report = options_json.at("penguinReport").as_boolean();
|
||||
m_options.penguin_report_cmd_line = options_json.at("penguinReportCmdLine").as_string();
|
||||
m_options.penguin_report_server = options_json.get("penguinReportServer", "CN");
|
||||
|
||||
m_options.ocr_gpu_index = options_json.get("ocrGpuIndex", -1);
|
||||
m_options.ocr_thread_number = options_json.at("ocrThreadNumber").as_integer();
|
||||
|
||||
//m_options.print_window = options_json.at("printWindow").as_boolean();
|
||||
m_options.adb_extra_swipe_dist = options_json.get("adbExtraSwipeDist", 100);
|
||||
m_options.adb_extra_swipe_duration = options_json.get("adbExtraSwipeDuration", -1);
|
||||
m_options.adb_extra_swipe_duration = options_json.get("adbExtraSwipeDuration", -1);
|
||||
|
||||
auto& penguin_report = options_json.at("penguinReport");
|
||||
m_options.penguin_report.enable = penguin_report.get("enable", true);
|
||||
m_options.penguin_report.cmd_format = penguin_report.get("cmdFormat", std::string());
|
||||
m_options.penguin_report.server = penguin_report.get("server", "CN");
|
||||
|
||||
if (options_json.exist("aipOcr")) {
|
||||
auto& aip_ocr = options_json.at("aipOcr");
|
||||
m_options.aip_ocr.enable = aip_ocr.get("enable", false);
|
||||
m_options.aip_ocr.accurate = aip_ocr.get("accurate", false);
|
||||
m_options.aip_ocr.client_id = aip_ocr.get("clientId", std::string());
|
||||
m_options.aip_ocr.client_secret = aip_ocr.get("clientSerect", std::string());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [name, emulator_json] : json.at("emulator").as_object()) {
|
||||
@@ -46,10 +52,11 @@ bool asst::GeneralConfiger::parse(const json::value& json)
|
||||
emulator_info.adb.display = adb_json.at("display").as_string();
|
||||
emulator_info.adb.display_format = adb_json.at("displayFormat").as_string();
|
||||
emulator_info.adb.screencap = adb_json.at("screencap").as_string();
|
||||
emulator_info.adb.release = adb_json.at("release").as_string();
|
||||
//emulator_info.adb.pullscreen = adb_json.at("pullscreen").as_string();
|
||||
|
||||
m_emulators_info.emplace(name, std::move(emulator_info));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -14,23 +14,35 @@ namespace asst
|
||||
{
|
||||
Emulator,
|
||||
Custom
|
||||
};
|
||||
|
||||
struct AipOcrCfg // 百度 OCR API 的配置
|
||||
{
|
||||
bool enable = false;
|
||||
bool accurate = false; // 是否使用高精度识别
|
||||
std::string client_id;
|
||||
std::string client_secret;
|
||||
};
|
||||
|
||||
struct PenguinReportCfg // 企鹅物流数据汇报 的配置
|
||||
{
|
||||
bool enable = false;
|
||||
std::string cmd_format; // 命令格式
|
||||
std::string extra_param; // 额外参数
|
||||
std::string server; // 上传参数中"server"字段,"CN", "US", "JP" and "KR".
|
||||
};
|
||||
|
||||
struct Options
|
||||
{
|
||||
ConnectType connect_type; // 连接类型
|
||||
ConnectType connect_type = ConnectType::Emulator; // 连接类型
|
||||
int task_delay = 0; // 任务间延时:越快操作越快,但会增加CPU消耗
|
||||
int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时
|
||||
int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时
|
||||
bool print_window = false; // 截图功能:开启后每次结算界面会截图到screenshot目录下
|
||||
bool penguin_report = false; // 企鹅数据汇报:每次到结算界面,是否汇报掉落数据至企鹅数据 https://penguin-stats.cn/
|
||||
std::string penguin_report_cmd_line; // 企鹅数据汇报的命令
|
||||
std::string penguin_report_extra_param; // 企鹅数据汇报的命令
|
||||
std::string penguin_report_server; // 企鹅数据汇报接口"server"字段,"CN", "US", "JP" and "KR".
|
||||
int ocr_gpu_index = -1; // OcrLite使用GPU编号,-1(使用CPU)/0(使用GPU0)/1(使用GPU1)/...
|
||||
int ocr_thread_number = 0; // OcrLite线程数量
|
||||
//bool print_window = false; // 截图功能:开启后每次结算界面会截图到screenshot目录下
|
||||
int adb_extra_swipe_dist = 0; // 额外的滑动距离:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来
|
||||
int adb_extra_swipe_duration = -1; // 额外的滑动持续时间:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来。若小于0,则关闭额外滑动功能
|
||||
int adb_extra_swipe_duration = -1; // 额外的滑动持续时间:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来。若小于0,则关闭额外滑动功能
|
||||
PenguinReportCfg penguin_report; // 企鹅数据汇报:每次到结算界面,汇报掉落数据至企鹅数据 https://penguin-stats.cn/
|
||||
AipOcrCfg aip_ocr; // 百度 OCR API 的配置
|
||||
};
|
||||
|
||||
class GeneralConfiger : public AbstractConfiger
|
||||
@@ -67,21 +67,21 @@ bool asst::InfrastAbstractTask::enter_facility(const std::string& facility, int
|
||||
};
|
||||
m_callback(AsstMsg::EnterFacility, enter_json, m_callback_arg);
|
||||
|
||||
const auto& image = ctrler.get_image();
|
||||
const auto& image = Ctrler.get_image();
|
||||
|
||||
InfrastFacilityImageAnalyzer analyzer(image);
|
||||
analyzer.set_to_be_analyzed({ facility });
|
||||
if (!analyzer.analyze()) {
|
||||
log.trace("result is empty");
|
||||
Log.trace("result is empty");
|
||||
return false;
|
||||
}
|
||||
Rect rect = analyzer.get_rect(facility, index);
|
||||
if (rect.empty()) {
|
||||
log.trace("facility index is out of range");
|
||||
Log.trace("facility index is out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
ctrler.click(rect);
|
||||
Ctrler.click(rect);
|
||||
|
||||
const auto enter_task_ptr = task.get("InfrastEnterFacility");
|
||||
sleep(enter_task_ptr->rear_delay);
|
||||
@@ -93,9 +93,9 @@ bool asst::InfrastAbstractTask::enter_oper_list_page()
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
auto image = ctrler.get_image();
|
||||
auto image = Ctrler.get_image();
|
||||
|
||||
// 识别右边的“进驻”按钮
|
||||
// 识别左边的“进驻”按钮
|
||||
const auto enter_task_ptr = std::dynamic_pointer_cast<OcrTaskInfo>(
|
||||
task.get("InfrastEnterOperList"));
|
||||
OcrImageAnalyzer enter_analyzer(image);
|
||||
@@ -103,31 +103,31 @@ bool asst::InfrastAbstractTask::enter_oper_list_page()
|
||||
|
||||
// 如果没找到,说明“进驻信息”这个按钮没有被点开,那就点开它
|
||||
if (!enter_analyzer.analyze()) {
|
||||
log.trace("ready to analyze the stationed info button");
|
||||
Log.trace("ready to analyze the stationed info button");
|
||||
OcrImageAnalyzer station_analyzer(image);
|
||||
|
||||
const auto stationedinfo_task_ptr = std::dynamic_pointer_cast<OcrTaskInfo>(
|
||||
task.get("InfrastStationedInfo"));
|
||||
station_analyzer.set_task_info(*stationedinfo_task_ptr);
|
||||
if (station_analyzer.analyze()) {
|
||||
log.trace("the stationed info button found");
|
||||
ctrler.click(station_analyzer.get_result().front().rect);
|
||||
Log.trace("the stationed info button found");
|
||||
Ctrler.click(station_analyzer.get_result().front().rect);
|
||||
sleep(stationedinfo_task_ptr->rear_delay);
|
||||
// 点开了按钮之后,再识别一次右边的
|
||||
image = ctrler.get_image();
|
||||
image = Ctrler.get_image();
|
||||
enter_analyzer.set_image(image);
|
||||
if (!enter_analyzer.analyze()) {
|
||||
log.error("no enterlist button");
|
||||
Log.error("no enterlist button");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.error("no stationed info button");
|
||||
Log.error("no stationed info button");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
log.trace("ready to click the enterlist button");
|
||||
ctrler.click(enter_analyzer.get_result().front().rect);
|
||||
Log.trace("ready to click the enterlist button");
|
||||
Ctrler.click(enter_analyzer.get_result().front().rect);
|
||||
sleep(enter_task_ptr->rear_delay);
|
||||
|
||||
return true;
|
||||
@@ -141,10 +141,10 @@ void asst::InfrastAbstractTask::async_swipe_of_operlist(bool reverse)
|
||||
static int duration = task.get("InfrastOperListSwipeBegin")->pre_delay;
|
||||
|
||||
if (!reverse) {
|
||||
m_last_swipe_id = ctrler.swipe(begin_rect, end_rect, duration, false, 0, true);
|
||||
m_last_swipe_id = Ctrler.swipe(begin_rect, end_rect, duration, false, 0, true);
|
||||
}
|
||||
else {
|
||||
m_last_swipe_id = ctrler.swipe(end_rect, begin_rect, duration, false, 0, true);
|
||||
m_last_swipe_id = Ctrler.swipe(end_rect, begin_rect, duration, false, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ void asst::InfrastAbstractTask::await_swipe()
|
||||
LogTraceFunction;
|
||||
static int extra_delay = task.get("InfrastOperListSwipeBegin")->rear_delay;
|
||||
|
||||
ctrler.wait(m_last_swipe_id);
|
||||
Ctrler.wait(m_last_swipe_id);
|
||||
sleep(extra_delay);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ bool asst::InfrastAbstractTask::click_bottomleft_tab()
|
||||
{
|
||||
LogTraceFunction;
|
||||
const auto task_ptr = task.get("InfrastBottomLeftTab");
|
||||
ctrler.click(task_ptr->specific_rect);
|
||||
Ctrler.click(task_ptr->specific_rect);
|
||||
sleep(task_ptr->rear_delay);
|
||||
return true;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ bool asst::InfrastAbstractTask::click_clear_button()
|
||||
{
|
||||
LogTraceFunction;
|
||||
const auto task_ptr = task.get("InfrastClearButton");
|
||||
ctrler.click(task_ptr->specific_rect);
|
||||
Ctrler.click(task_ptr->specific_rect);
|
||||
sleep(task_ptr->rear_delay);
|
||||
return true;
|
||||
}
|
||||
@@ -180,7 +180,7 @@ bool asst::InfrastAbstractTask::click_confirm_button()
|
||||
LogTraceFunction;
|
||||
const auto task_ptr = std::dynamic_pointer_cast<OcrTaskInfo>(
|
||||
task.get("InfrastConfirmButton"));
|
||||
ctrler.click(task_ptr->specific_rect);
|
||||
Ctrler.click(task_ptr->specific_rect);
|
||||
sleep(task_ptr->rear_delay);
|
||||
|
||||
// 识别“正在提交反馈至神经”,如果网不好一直确认不了,就多等一会
|
||||
@@ -190,7 +190,7 @@ bool asst::InfrastAbstractTask::click_confirm_button()
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
const auto& image = ctrler.get_image();
|
||||
const auto& image = Ctrler.get_image();
|
||||
analyzer.set_image(image);
|
||||
if (!analyzer.analyze()) {
|
||||
sleep(task_ptr->rear_delay);
|
||||
@@ -201,26 +201,26 @@ bool asst::InfrastAbstractTask::click_confirm_button()
|
||||
return false;
|
||||
}
|
||||
|
||||
void asst::InfrastAbstractTask::sync_swipe_of_operlist(bool reverse)
|
||||
void asst::InfrastAbstractTask::swipe_of_operlist(bool reverse)
|
||||
{
|
||||
async_swipe_of_operlist(reverse);
|
||||
await_swipe();
|
||||
}
|
||||
|
||||
void asst::InfrastAbstractTask::swipe_to_the_left_of_operlist()
|
||||
void asst::InfrastAbstractTask::swipe_to_the_left_of_operlist(int loop_times)
|
||||
{
|
||||
LogTraceFunction;
|
||||
static Rect begin_rect = task.get("InfrastOperListSwipeToTheLeftBegin")->specific_rect;
|
||||
static Rect end_rect = task.get("InfrastOperListSwipeToTheLeftEnd")->specific_rect;
|
||||
static int duration = task.get("InfrastOperListSwipeToTheLeftBegin")->pre_delay;
|
||||
static int extra_delay = task.get("InfrastOperListSwipeToTheLeftBegin")->rear_delay;
|
||||
static int loop_times = task.get("InfrastOperListSwipeToTheLeftBegin")->max_times;
|
||||
static int cfg_loop_times = task.get("InfrastOperListSwipeToTheLeftBegin")->max_times;
|
||||
|
||||
for (int i = 0; i != loop_times; ++i) {
|
||||
for (int i = 0; i != cfg_loop_times * loop_times; ++i) {
|
||||
if (need_exit()) {
|
||||
return;
|
||||
}
|
||||
ctrler.swipe(end_rect, begin_rect, duration, true, 0, false);
|
||||
Ctrler.swipe(end_rect, begin_rect, duration, true, 0, false);
|
||||
}
|
||||
sleep(extra_delay);
|
||||
}
|
||||
@@ -233,7 +233,7 @@ void asst::InfrastAbstractTask::swipe_to_the_left_of_main_ui()
|
||||
static int duration = task.get("InfrastOperListSwipeToTheLeftBegin")->pre_delay;
|
||||
static int extra_delay = task.get("InfrastOperListSwipeToTheLeftBegin")->rear_delay;
|
||||
|
||||
ctrler.swipe(end_rect, begin_rect, duration, true, extra_delay, false);
|
||||
Ctrler.swipe(end_rect, begin_rect, duration, true, extra_delay, false);
|
||||
}
|
||||
|
||||
void asst::InfrastAbstractTask::swipe_to_the_right_of_main_ui()
|
||||
@@ -244,5 +244,5 @@ void asst::InfrastAbstractTask::swipe_to_the_right_of_main_ui()
|
||||
static int duration = task.get("InfrastOperListSwipeToTheLeftBegin")->pre_delay;
|
||||
static int extra_delay = task.get("InfrastOperListSwipeToTheLeftBegin")->rear_delay;
|
||||
|
||||
ctrler.swipe(begin_rect, end_rect, duration, true, extra_delay, false);
|
||||
Ctrler.swipe(begin_rect, end_rect, duration, true, extra_delay, false);
|
||||
}
|
||||
@@ -15,16 +15,17 @@ namespace asst
|
||||
virtual void set_work_mode(infrast::WorkMode work_mode) noexcept;
|
||||
virtual void set_mood_threshold(double mood_thres) noexcept;
|
||||
|
||||
constexpr static int OperSelectRetryTimes = 3;
|
||||
protected:
|
||||
virtual bool on_run_fails() override;
|
||||
|
||||
virtual bool enter_facility(const std::string& facility, int index = 0);
|
||||
virtual bool enter_oper_list_page(); // 从刚点进基建的界面,到干员列表页
|
||||
|
||||
virtual void swipe_to_the_left_of_operlist(); // 滑动到干员列表的最左侧
|
||||
virtual void swipe_to_the_left_of_operlist(int loop_times = 1); // 滑动到干员列表的最左侧
|
||||
virtual void swipe_to_the_left_of_main_ui(); // 滑动基建的主界面到最左侧
|
||||
virtual void swipe_to_the_right_of_main_ui(); // 滑动基建的主界面到最右侧
|
||||
virtual void sync_swipe_of_operlist(bool reverse = false);
|
||||
virtual void swipe_of_operlist(bool reverse = false);
|
||||
virtual void async_swipe_of_operlist(bool reverse = false);
|
||||
virtual void await_swipe();
|
||||
|
||||
@@ -35,4 +35,4 @@ bool asst::InfrastClueImageAnalyzer::clue_analyze()
|
||||
{
|
||||
// todo
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,11 @@ bool asst::InfrastClueVacancyImageAnalyzer::analyze()
|
||||
task.get(clue_vacancy + suffix));
|
||||
analyzer.set_task_info(*task_ptr);
|
||||
if (!analyzer.analyze()) {
|
||||
log.trace("no", clue_vacancy, suffix);
|
||||
Log.trace("no", clue_vacancy, suffix);
|
||||
continue;
|
||||
}
|
||||
Rect rect = analyzer.get_result().rect;
|
||||
log.trace("has", clue_vacancy, suffix);
|
||||
Log.trace("has", clue_vacancy, suffix);
|
||||
#ifdef LOG_TRACE
|
||||
cv::rectangle(m_image_draw, utils::make_rect<cv::Rect>(rect), cv::Scalar(0, 0, 255), 2);
|
||||
cv::putText(m_image_draw, suffix, cv::Point(rect.x, rect.y + 1), 0, 1, cv::Scalar(0, 0, 255), 2);
|
||||