WinMove;<hr>;<blockquote>

本文介绍了HTML中的常用元素,如&lt;hr&gt;用于创建水平线,&lt;blockquote&gt;用于定义块引用,以及如何使div居中显示。此外,还详细讲解了使用WinMove函数调整窗口位置和大小的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<hr> 标签在 HTML 页面中创建一条水平线。

水平分隔线(horizontal rule)可以在视觉上将文档分隔成各个部分。


<blockquote> 标签定义块引用。

<blockquote> 与 </blockquote> 之间的所有文本都会从常规文本中分离出来,经常会在左、右两边进行缩进(增加外边距),而且有时会使用斜体。也就是说,块引用拥有它们自己的空间。

style="text-align:center”  设置文本居中显示       不用&nbsp;

DIV相对页面居中,其实不建议用text-align:center来做DIV的居中   ,  会遇到各种浏览器兼容的问题。

只要定义div的width:900px; margin:0 auto; 这个DIV就会居中了。

<div style="height:60px"></div>    来设置页面空白部分高度



WinMove

Moves and/or resizes a window.

WinMove ( "title", "text", x, y [, width [, height [, speed]]] )

Parameters

titleThe title/hWnd/class of the window to move/resize. See Title special definition.
textThe text of the window to move/resize. See Text special definition.
xX coordinate to move to.
yY coordinate to move to.
width[optional] New width of the window.
height[optional] New height of the window.
speed[optional] the speed to move the windows in the range 1 (fastest) to 100 (slowest). If not defined the move is instantaneous.

Return Value

Success:a handle to the window.
Failure:0 if the window is not found.

Remarks

WinMove() has no effect on minimized windows, butWinMove() works on hidden windows.
If the width and height are small (or negative), the window will go no smaller than 112 x 27 pixels. If width and height are large, the window will go no larger than approximately [12+@DesktopWidth] x [12+@DesktopHeight] pixels.
Negative values are allowed for the x and y coordinates. In fact, you can move a window off screen; and if the window's program is one that remembers its last window position, the window will appear in the corner (but fully on-screen) the next time you launch the program.
If multiple windows match the criteria, the most recently active window is used.

If x and y equal to the Default keyword no move occurs, just resizing.

When speed is used the move is done with the new size.

Related

WinActivate,WinClose, WinGetClientSize, WinGetPos, WinSetState

Example

Example()

Func Example()
    ; Run Notepad
    Run("notepad.exe")

    ; Wait 10 seconds for the Notepad window to appear.
    Local $hWnd = WinWait("[CLASS:Notepad]", "", 10)

    ; Retrieve the position as well as the height and width of the Notepad window. We will use this when we have to move the window back to the original position.
    Local $aPos = WinGetPos($hWnd)

    ; Move the Notepad to the x, y position of 0, 0 and set the height and width at 200, 200.
    WinMove($hWnd, "", 0, 0, 200, 200)

    ; Wait for 2 seconds to display the new position of the Notepad window.
    Sleep(2000)

    ; Move the Notepad window back to the original position by using the array returned by WinGetPos.
    WinMove($hWnd, "", $aPos[0], $aPos[1], $aPos[2], $aPos[3])

    ; Wait for 2 seconds to display the original position of the Notepad window.
    Sleep(2000)

    ; Close the Notepad window using the handle returned by WinWait.
    WinClose($hWnd)
EndFunc   ;==>Example


#pragma once #include <vector> #include <string> class Config { public: Config(); bool loadFromFile(const std::string& filePath); // === 可视化 & 推理阈值 === int show_window; // 窗口显示开关 (0=不显示,1=显示) float conf_threshold; // 检测置信度阈值 [0.0,1.0] float nms_threshold; // NMS 重叠阈值 [0.0,1.0] // === 瞄准 & FOV === int aim_part; // 瞄准部位 (0=头,1=胸 等) float xfov, yfov; // 水平 / 垂直 视野因子 // === 截图方式 === int screenshot_method; // 0=DXGI, 1=Win32 BitBlt // === 卡尔曼滤波参数 === float kalman_Q; // 过程噪声协方差 float kalman_R; // 测量噪声协方差 int kalman_enable; // 0=禁用,1=启用 // === 鼠标控制参数 === int move_type; // 0=WinMove,1=GBIL 等 int aim_key; // 触发键1 (VK code) int aim_key1; // 触发键2 (VK code) int tracking_toggle_key; // 跟踪开启/关闭键 (VK code) int exit_key; // 退出程序键 (VK code) // === 单目标追踪锁定参数 === float lock_threshold; // 距离中心锁定阈值 (像素) int lock_frames; // 锁定前需持续多少帧 // === 平滑 (PID) 参数 === float xkp, xki, xkd; // X 方向 PID 三项系数 float ykp, yki, ykd; // Y 方向 PID 三项系数 // === 类别过滤 === std::vector<int> valid_classes; // 可跟踪类别列表 // === 锚点偏移比 === float anchor_x; // 框内 X 方向锚点比例 [0.0,1.0] float anchor_y; // 框内 Y 方向锚点比例 [0.0,1.0] // === 多目标跟踪 (MOT) 关联参数 === float iou_threshold; // IOU 关联阈值 [0.0,1.0] int max_lost_frames; // Track 丢失后允许的最大未匹配帧数 int min_hits; // Track 在被认为“有效”前需连续命中帧数 // === 预测系统参数 === int prediction_enable; // 0=禁用, 1=启用 float prediction_coefficient; // 预测系数 int prediction_history_size; // 历史记录数量 int system_delay; // 系统延迟(毫秒) float min_velocity_threshold; // 最小速度阈值 // === ADRC控制器参数(新增) === float adrc_w0; // 观测器带宽 float adrc_b0; // 控制增益 float adrc_wn; // 闭环带宽 float adrc_sigma; // 阻尼系数 };config.h代码和 #include "config.h" #include <windows.h> #include <cstring> Config::Config() { // ---- 默认值 ---- show_window = 1; conf_threshold = 0.4f; nms_threshold = 0.5f; aim_part = 1; xfov = 1.0f; yfov = 1.33f; screenshot_method = 0; kalman_Q = 0.0001f; kalman_R = 10.0f; kalman_enable = 1; move_type = 0; aim_key = 0x10; // Shift aim_key1 = 0x02; // 鼠标右键 tracking_toggle_key = 0x24; // Home exit_key = 0x23; // End lock_threshold = 50.0f; lock_frames = 5; xkp = 0.8f; xki = 0.005f; xkd = 0.15f; ykp = 0.8f; yki = 0.005f; ykd = 0.15f; anchor_x = 0.5f; anchor_y = 0.5f; // MOT 新增部分 iou_threshold = 0.3f; max_lost_frames = 5; min_hits = 3; // 预测系统默认值 prediction_enable = 1; prediction_coefficient = 0.8f; prediction_history_size = 10; system_delay = 50; min_velocity_threshold = 50.0f; // === ADRC默认参数(新增) === adrc_w0 = 50.0f; // 观测器带宽 adrc_b0 = 0.8f; // 控制增益 adrc_wn = 50.0f; // 闭环带宽 adrc_sigma = 1.0f; // 阻尼系数 } bool Config::loadFromFile(const std::string& filePath) { // ---- WINDOWS ---- show_window = GetPrivateProfileIntA("WINDOWS", "show_windows", show_window, filePath.c_str()); // ---- PRED ---- conf_threshold = GetPrivateProfileIntA("PRED", "conf_threshold", static_cast<int>(conf_threshold * 100), filePath.c_str()) / 100.0f; nms_threshold = GetPrivateProfileIntA("PRED", "nms_threshold", static_cast<int>(nms_threshold * 100), filePath.c_str()) / 100.0f; aim_part = GetPrivateProfileIntA("PRED", "aim_part", aim_part, filePath.c_str()); xfov = GetPrivateProfileIntA("PRED", "xfov", static_cast<int>(xfov * 100), filePath.c_str()) / 100.0f; yfov = GetPrivateProfileIntA("PRED", "yfov", static_cast<int>(yfov * 100), filePath.c_str()) / 100.0f; screenshot_method = GetPrivateProfileIntA("PRED", "Screenshot_method", screenshot_method, filePath.c_str()); // ---- 锚点 ---- anchor_x = GetPrivateProfileIntA("PRED", "anchor_x", static_cast<int>(anchor_x * 100), filePath.c_str()) / 100.0f; anchor_y = GetPrivateProfileIntA("PRED", "anchor_y", static_cast<int>(anchor_y * 100), filePath.c_str()) / 100.0f; // ---- 类别过滤 ---- valid_classes.clear(); { char buffer[256]; GetPrivateProfileStringA("PRED", "track_class", "", buffer, sizeof(buffer), filePath.c_str()); char* next = nullptr; char* token = strtok_s(buffer, ",", &next); while (token) { valid_classes.push_back(std::atoi(token)); token = strtok_s(nullptr, ",", &next); } } // ---- KALMAN ---- kalman_Q = GetPrivateProfileIntA("KALMAN", "process_noise", static_cast<int>(kalman_Q * 1e6), filePath.c_str()) / 1e6f; kalman_R = GetPrivateProfileIntA("KALMAN", "obs_noise", static_cast<int>(kalman_R * 100), filePath.c_str()) / 100.0f; kalman_enable = GetPrivateProfileIntA("KALMAN", "enable", kalman_enable, filePath.c_str()); // ---- MOUSE & CONTROL ---- move_type = GetPrivateProfileIntA("MOUSE", "move_type", move_type, filePath.c_str()); aim_key = GetPrivateProfileIntA("CONTROL", "aim_key", aim_key, filePath.c_str()); aim_key1 = GetPrivateProfileIntA("CONTROL", "aim_key1", aim_key1, filePath.c_str()); tracking_toggle_key = GetPrivateProfileIntA("CONTROL", "tracking_toggle_key", tracking_toggle_key, filePath.c_str()); exit_key = GetPrivateProfileIntA("CONTROL", "exit_key", exit_key, filePath.c_str()); // ---- TRACK (单目标) ---- lock_threshold = static_cast<float>(GetPrivateProfileIntA("TRACK", "lock_threshold", static_cast<int>(lock_threshold), filePath.c_str())); lock_frames = GetPrivateProfileIntA("TRACK", "lock_frames", lock_frames, filePath.c_str()); // ---- SMOOTH (PID) ---- xkp = GetPrivateProfileIntA("SMOOTH", "xkp", static_cast<int>(xkp * 100), filePath.c_str()) / 100.0f; xki = GetPrivateProfileIntA("SMOOTH", "xki", static_cast<int>(xki * 1000), filePath.c_str()) / 1000.0f; xkd = GetPrivateProfileIntA("SMOOTH", "xkd", static_cast<int>(xkd * 100), filePath.c_str()) / 100.0f; ykp = GetPrivateProfileIntA("SMOOTH", "ykp", static_cast<int>(ykp * 100), filePath.c_str()) / 100.0f; yki = GetPrivateProfileIntA("SMOOTH", "yki", static_cast<int>(yki * 1000), filePath.c_str()) / 1000.0f; ykd = GetPrivateProfileIntA("SMOOTH", "ykd", static_cast<int>(ykd * 100), filePath.c_str()) / 100.0f; // ---- 预测系统参数 ---- prediction_enable = GetPrivateProfileIntA("PREDICTION", "prediction_enable", prediction_enable, filePath.c_str()); prediction_coefficient = GetPrivateProfileIntA("PREDICTION", "prediction_coefficient", static_cast<int>(prediction_coefficient * 100), filePath.c_str()) / 100.0f; prediction_history_size = GetPrivateProfileIntA("PREDICTION", "prediction_history_size", prediction_history_size, filePath.c_str()); system_delay = GetPrivateProfileIntA("PREDICTION", "system_delay", system_delay, filePath.c_str()); min_velocity_threshold = static_cast<float>(GetPrivateProfileIntA("PREDICTION", "min_velocity_threshold", static_cast<int>(min_velocity_threshold), filePath.c_str())); // ---- MOT 关联配置 ---- iou_threshold = GetPrivateProfileIntA("MOT", "iou_threshold", static_cast<int>(iou_threshold * 100), filePath.c_str()) / 100.0f; max_lost_frames = GetPrivateProfileIntA("MOT", "max_lost_frames", max_lost_frames, filePath.c_str()); min_hits = GetPrivateProfileIntA("MOT", "min_hits", min_hits, filePath.c_str()); // === ADRC参数加载(修改后) === char buffer[32]; if (GetPrivateProfileStringA("ADRC", "w0", "", buffer, sizeof(buffer), filePath.c_str())) { adrc_w0 = std::stof(buffer); } if (GetPrivateProfileStringA("ADRC", "b0", "", buffer, sizeof(buffer), filePath.c_str())) { adrc_b0 = std::stof(buffer); } if (GetPrivateProfileStringA("ADRC", "wn", "", buffer, sizeof(buffer), filePath.c_str())) { adrc_wn = std::stof(buffer); } if (GetPrivateProfileStringA("ADRC", "sigma", "", buffer, sizeof(buffer), filePath.c_str())) { adrc_sigma = std::stof(buffer); } // 打印ADRC参数加载结果 printf("配置文件读取-ADRC参数: w0=%.1f, b0=%.2f, wn=%.1f, sigma=%.1f\n", adrc_w0, adrc_b0, adrc_wn, adrc_sigma); return true; }config.cpp代码,把修改后的完整代码发我 因为主程序的 // ==== 初始化控制器 ==== PIDController pid_x(config.xkp, config.xki, config.xkd); PIDController pid_y(config.ykp, config.yki, config.ykd); // ===== 新增:滑模控制器(解决动态目标跟踪延迟)===== SlidingModeController smc_x(config.smc_k, config.smc_lambda, config.smc_epsilon); SlidingModeController smc_y(config.smc_k, config.smc_lambda, config.smc_epsilon); // ===== 新增:轨迹管理器(解决目标丢失拖影)===== TrajectoryManager trajectory_mgr(config.max_misses, config.decay_factor); KalmanFilter kf(config.kalman_Q, config.kalman_R); printf("主程序-控制参数: PID X[%.2f, %.3f, %.2f] Y[%.2f, %.3f, %.2f]\n", config.xkp, config.xki, config.xkd, config.ykp, config.yki, config.ykd); printf("主程序-滑模参数: k=%.1f, λ=%.1f, ε=%.2f\n", config.smc_k, config.smc_lambda, config.smc_epsilon);和 // 应用移动(带平滑处理) mouse->updateTarget(final_dx * config.sensitivity, final_dy * config.sensitivity);报凑
07-14
#include "dml-module.h" #include "cap.h" #include "cap_win.h" #include <nms.h> #include <opencv2/opencv.hpp> #include "AIMBOT.cpp" #include "mouse_controller.h" #include <windows.h> #include <chrono> #include <string> #include <filesystem> #include <iostream> #include <functional> #include <atomic> #include <mutex> #include <vector> #include <algorithm> #include <optional> #include "gbil_mouse_controller.h" #include "config.h" // ===== 新增:ADRC控制器结构体(自抗扰控制,解决动态目标扰动问题)===== struct ADRCController { float w0; // 观测器带宽 float b0; // 控制增益 float w_n; // 闭环带宽 float sigma; // 阻尼系数 float time_delta; // 时间步长(ms转换为秒) // 扩张状态观测器变量 float z1{ 0 }, z2{ 0 }, z3{ 0 }; // 状态观测值(位置、速度、扰动) float u_p{ 0 }; // 上一时刻控制量 std::mutex mtx; // 初始化ADRC参数(从配置文件读取) ADRCController(float w0_, float b0_, float w_n_, float sigma_, float dt) : w0(w0_), b0(b0_), w_n(w_n_), sigma(sigma_), time_delta(dt) { } // *核心方法:根据目标值和当前值计算补偿后的控制量 float update(float target, float current) { std::lock_guard<std::mutex> lock(mtx); float err = current - z1; // 跟踪误差 // 扩张状态观测器(ESO)更新 float fhan = this->fhan(err, z2, w_n, sigma); z1 += time_delta * (z2 + w0 * w0 * err); // 位置观测 z2 += time_delta * (z3 + 2 * w0 * z2 + w0 * w0 * fhan); // 速度观测 z3 += time_delta * (-3 * w0 * z3 + w0 * w0 * w0 * (current - z1)); // 扰动观测 // 控制律计算(补偿扰动) float u0 = w_n * w_n * (target - z1) - 2 * sigma * w_n * z2; float u = (u0 - z3) / b0; u_p = u; // 保存当前控制量 return u; } // 快速跟踪微分器(处理非线性特性) float fhan(float x1, float x2, float r, float h0) { float d = r * h0 * h0; float d0 = h0 * d; float y = x1 + h0 * x2; float a0 = sqrt(d * (d + 8 * abs(y))); float a; if (abs(y) > d0) { a = x2 + (a0 - d) / 2 * (y > 0 ? 1 : -1); } else { a = x2 + y / h0; } if (abs(a) > d) { return -r * (a > 0 ? 1 : -1); } else { return -r * a / d; } } void reset() { std::lock_guard<std::mutex> lock(mtx); z1 = z2 = z3 = 0; u_p = 0; } }; // ===== PID控制器结构体(保留原有功能,与ADRC级联)===== struct PIDController { float kp, ki, kd; float integral{ 0 }, last_error{ 0 }; std::mutex mtx; PIDController(float p, float i, float d) : kp(p), ki(i), kd(d) {} float compute(float error) { std::lock_guard<std::mutex> lock(mtx); integral += error; float derivative = error - last_error; last_error = error; return kp * error + ki * integral + kd * derivative; } void reset() { std::lock_guard<std::mutex> lock(mtx); integral = 0; last_error = 0; } }; // ===== 卡尔曼滤波类(参数可配置)===== class KalmanFilter { public: KalmanFilter(float process_noise, float obs_noise) { kf.init(4, 2, 0); kf.transitionMatrix = (cv::Mat_<float>(4, 4) << 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1); cv::setIdentity(kf.measurementMatrix); cv::setIdentity(kf.processNoiseCov, cv::Scalar::all(process_noise)); cv::setIdentity(kf.measurementNoiseCov, cv::Scalar::all(obs_noise)); cv::setIdentity(kf.errorCovPost, cv::Scalar::all(1)); } cv::Point2f predict(float x, float y) { cv::Mat measurement = (cv::Mat_<float>(2, 1) << x, y); kf.predict(); cv::Mat estimated = kf.correct(measurement); return cv::Point2f(estimated.at<float>(0), estimated.at<float>(1)); } private: cv::KalmanFilter kf; }; // ===== 新增:贝塞尔曲线生成工具(解决移动拖影,实现类人平滑路径)===== class BezierCurve { public: // 生成从起点到终点的贝塞尔曲线路径点 static std::vector<cv::Point2f> generatePoints( cv::Point2f start, cv::Point2f end, int num_points = 10) { // 路径点数量(越多越平滑)数值越大越慢 std::vector<cv::Point2f> points; // 生成随机内点(增加路径自然性) std::vector<cv::Point2f> control_points; control_points.push_back(start); // 添加2个随机内点(在起点和终点范围内) control_points.push_back(cv::Point2f( start.x + (end.x - start.x) * 0.3f + rand() % 5 - 2, // 微小随机偏移 start.y + (end.y - start.y) * 0.3f + rand() % 5 - 2 )); control_points.push_back(cv::Point2f( start.x + (end.x - start.x) * 0.7f + rand() % 5 - 2, start.y + (end.y - start.y) * 0.7f + rand() % 5 - 2 )); control_points.push_back(end); // 贝塞尔曲线采样 for (int i = 0; i < num_points; ++i) { float t = (float)i / (num_points - 1); points.push_back(bezier(t, control_points)); } return points; } private: // 贝塞尔曲线计算 static cv::Point2f bezier(float t, const std::vector<cv::Point2f>& points) { int n = points.size() - 1; cv::Point2f result(0, 0); for (int i = 0; i <= n; ++i) { float bernstein = binomial(n, i) * pow(t, i) * pow(1 - t, n - i); result.x += points[i].x * bernstein; result.y += points[i].y * bernstein; } return result; } // 二项式系数计算 static float binomial(int n, int k) { if (k < 0 || k > n) return 0; if (k == 0 || k == n) return 1; k = std::min(k, n - k); float res = 1; for (int i = 1; i <= k; ++i) { res = res * (n - k + i) / i; } return res; } }; // ===== 目标选择函数(安全封装)===== std::optional<Box> selectTarget( std::vector<Box>& filtered, int& tracked_id, int& tracking_counter, float anchor_x, float anchor_y, int width, int height ) { // 优先选择上次追踪目标 for (auto& box : filtered) { if (box.id == tracked_id) { tracking_counter++; return box; } } // 未找到则选择距离中心最近的目标 if (!filtered.empty()) { float min_dist = FLT_MAX; Box* best_target = nullptr; for (auto& box : filtered) { float cx = box.left + (box.right - box.left) * anchor_x; float cy = box.top + (box.bottom - box.top) * anchor_y; float dist = std::hypot(cx - width / 2.0f, cy - height / 2.0f); if (dist < min_dist) { min_dist = dist; best_target = &box; } } if (best_target) { tracked_id = best_target->id; tracking_counter = 1; return *best_target; } } return std::nullopt; } int main() { // ------ 新增:检查自身实例是否已在运行 开始 ------ // 通过创建全局命名互斥锁(Named Mutex)来判断是否已有一个实例在运行 HANDLE hInstanceMutex = CreateMutexW(nullptr, FALSE, L"Global\\GblidDemoVC_Mutex"); if (!hInstanceMutex || GetLastError() == ERROR_ALREADY_EXISTS) { MessageBoxW(NULL, L"请勿重复运行", L"提示", MB_OK | MB_ICONWARNING); if (hInstanceMutex) { CloseHandle(hInstanceMutex); } ExitProcess(0); // 已有实例,退出当前进程 } // ------ 新增:检查自身实例是否已在运行 结束 ------ // 隐藏控制台窗口 HWND consoleWindow = GetConsoleWindow(); // 获取当前控制台窗口句柄 ShowWindow(consoleWindow, SW_HIDE); // 隐藏控制台窗口(如果需要调试可以注释掉这行)//==========需要调试可以注释================== // ==== 加载配置 ==== Config config; if (!config.loadFromFile("./config.ini")) { printf("主程序-配置文件加载失败!\n"); return -1; } bool baim = (config.aim_part == 0); timeBeginPeriod(1); // 设置定时器精度为1ms // === 自动加载模型 === std::string model_dir = "onnx"; std::string model_path; for (const auto& entry : std::filesystem::directory_iterator(model_dir)) { if (entry.path().extension() == ".onnx") { model_path = entry.path().string(); break; } } if (model_path.empty()) { printf("主程序-未在 'onnx' 文件夹中找到任何 .onnx 模型文件!\n"); return -1; } printf("主程序-加载模型路径: %s\n", model_path.c_str()); // 初始化模型类 auto* frame = new IDML(); if (!frame->AnalyticalModel(model_path)) { printf("主程序-模型加载失败。\n"); return -2; } const auto& input_dims = frame->getInputDims(); if (input_dims.size() != 4) { printf("主程序-模型输入维度异常,当前维度数量: %llu\n", input_dims.size()); return -3; } int channels = static_cast<int>(input_dims[1]); int height = static_cast<int>(input_dims[2]); int width = static_cast<int>(input_dims[3]); printf("主程序-输入图像尺寸: %d x %d\n", width, height); // ==== 初始化控制器(*修改:新增ADRC控制器)==== PIDController pid_x(config.xkp, config.xki, config.xkd); PIDController pid_y(config.ykp, config.yki, config.ykd); // *ADRC参数(从配置文件读取,可根据动态目标特性调整) float adrc_dt = 0.016f; // 约60FPS的时间步长(1/60≈0.016s) ADRCController adrc_x(config.adrc_w0, config.adrc_b0, config.adrc_wn, config.adrc_sigma, adrc_dt); ADRCController adrc_y(config.adrc_w0, config.adrc_b0, config.adrc_wn, config.adrc_sigma, adrc_dt); KalmanFilter kf(config.kalman_Q, config.kalman_R); printf("主程序-控制参数: PID X[%.2f, %.3f, %.2f] Y[%.2f, %.3f, %.2f]\n", config.xkp, config.xki, config.xkd, config.ykp, config.yki, config.ykd); printf("主程序-ADRC参数: w0=%.1f, b0=%.2f, wn=%.1f, sigma=%.1f\n", config.adrc_w0, config.adrc_b0, config.adrc_wn, config.adrc_sigma); int screenW = GetSystemMetrics(SM_CXSCREEN); int screenH = GetSystemMetrics(SM_CYSCREEN); std::function<BYTE* ()> capture_func; void* cap_impl = nullptr; // 选择截图方式 if (config.screenshot_method == 0) { auto* c = new capture(screenW, screenH, width, height, "CrossFire"); cap_impl = c; capture_func = [c]() -> BYTE* { return (BYTE*)c->cap(); }; printf("主程序-截图方式: DXGI\n"); } else { auto* c = new capture_win32(screenW, screenH, width, height, "CrossFire"); cap_impl = c; capture_func = [c]() -> BYTE* { return c->cap(); }; printf("主程序-截图方式: Win32 BitBlt\n"); } // 初始化鼠标控制器 IMouseController* mouse = nullptr; if (config.move_type == 0) { mouse = new WinMouseController(); printf("主程序-使用鼠标控制器: WinMove\n"); } else if (config.move_type == 1) { mouse = new GBILMouseController(); printf("主程序-使用鼠标控制器: GBIL\n"); } else { printf("主程序-未知的 move_type 类型: %d,未启用鼠标移动!\n", config.move_type); } using Clock = std::chrono::high_resolution_clock; auto last_time = Clock::now(); float fps = 0.0f; // ==== 持续追踪状态 ==== static int tracked_id = -1; static int tracking_counter = 0; static int lost_counter = 0; // ==== 跟踪功能开关状态 ==== std::atomic<bool> tracking_enabled{ true }; bool last_tracking_toggle_state = false; bool last_exit_key_state = false; // ==== 新增:记录上一时刻鼠标位置(用于贝塞尔路径生成)==== cv::Point2f last_mouse_pos(0, 0); // ==== 主循环 ==== static bool target_locked = false; static int lock_frames_counter = 0; static float last_min_dist = FLT_MAX; while (true) { auto start = Clock::now(); // ==== 检查退出键 ==== bool current_exit_state = (GetAsyncKeyState(config.exit_key) & 0x8000) != 0; if (current_exit_state && !last_exit_key_state) { // 使用MB_SYSTEMMODAL标志使对话框置顶 [1,8](@ref) int result = MessageBoxA( NULL, "确定要退出YAK吗?", "退出确认", MB_OKCANCEL | MB_ICONQUESTION | MB_SYSTEMMODAL // 添加MB_SYSTEMMODAL标志 ); if (result == IDOK) { break; } } last_exit_key_state = current_exit_state; // ==== 检查跟踪开关键 ==== bool current_tracking_toggle = (GetAsyncKeyState(config.tracking_toggle_key) & 0x8000) != 0; if (current_tracking_toggle && !last_tracking_toggle_state) { tracking_enabled = !tracking_enabled; printf("主程序-跟踪功能已%s\n", tracking_enabled ? "开启" : "关闭"); } last_tracking_toggle_state = current_tracking_toggle; // 截图 BYTE* s = capture_func(); auto after_cap = Clock::now(); // 目标检测 float* data = frame->Detect(s); auto after_detect = Clock::now(); // 计算性能指标 float capture_ms = std::chrono::duration<float, std::milli>(after_cap - start).count(); float detect_ms = std::chrono::duration<float, std::milli>(after_detect - after_cap).count(); float frame_time = std::chrono::duration<float>(after_detect - last_time).count(); last_time = after_detect; fps = 1.0f / frame_time; std::vector<Box> oldbox; std::vector<Box> newbox = generate_yolo_proposals(data, oldbox, frame->out1, frame->out2, config.conf_threshold, config.nms_threshold); // ==== 目标过滤 ==== static std::vector<Box> filtered; filtered.clear(); for (auto& box : newbox) { if (config.valid_classes.empty() || std::find(config.valid_classes.begin(), config.valid_classes.end(), box.class_label) != config.valid_classes.end()) { filtered.push_back(box); } } // ==== 目标选择与锁定机制 ==== std::optional<Box> current_target = std::nullopt; if (tracking_enabled) { if (target_locked) { for (auto& box : filtered) { if (box.id == tracked_id) { current_target = box; tracking_counter++; lost_counter = 0; break; } } if (!current_target) { if (++lost_counter > 5) { target_locked = false; tracked_id = -1; tracking_counter = 0; lost_counter = 0; last_min_dist = FLT_MAX; } } } else if (!filtered.empty()) { float min_dist = FLT_MAX; Box* best_target = nullptr; for (auto& box : filtered) { float cx = box.left + (box.right - box.left) * config.anchor_x; float cy = box.top + (box.bottom - box.top) * config.anchor_y; float dist = std::hypot(cx - width / 2.0f, cy - height / 2.0f); if (dist < min_dist && (tracked_id == -1 || dist < last_min_dist * 0.8f)) { min_dist = dist; best_target = &box; } } if (best_target) { current_target = *best_target; tracked_id = best_target->id; tracking_counter = 1; last_min_dist = min_dist; if (min_dist < config.lock_threshold) { if (++lock_frames_counter >= config.lock_frames) { target_locked = true; lock_frames_counter = 0; } } else { lock_frames_counter = 0; } } } } // ==== 鼠标控制逻辑(*核心修改:PID+ADRC级联控制+贝塞尔路径平滑)==== bool aim_key_pressed = (GetAsyncKeyState(config.aim_key) & 0x8000) != 0; bool aim_key1_pressed = (GetAsyncKeyState(config.aim_key1) & 0x8000) != 0; bool any_aim_key_pressed = aim_key_pressed || aim_key1_pressed; if (any_aim_key_pressed && mouse && tracking_enabled) { if (current_target) { // 计算锚点位置 float center_x = current_target->left + (current_target->right - current_target->left) * config.anchor_x; float center_y = current_target->top + (current_target->bottom - current_target->top) * config.anchor_y; cv::Point2f smoothed; if (config.kalman_enable) { smoothed = kf.predict(center_x, center_y); } else { smoothed = cv::Point2f(center_x, center_y); } // 计算原始偏移(目标与屏幕中心的偏差) float raw_dx = smoothed.x - width / 2.0f; float raw_dy = smoothed.y - height / 2.0f; // *步骤1:PID计算基础移动量(比例+积分+微分) float pid_dx = pid_x.compute(raw_dx); float pid_dy = pid_y.compute(raw_dy); // *步骤2:ADRC补偿动态扰动(解决动态目标跟踪延迟) float adrc_dx = adrc_x.update(pid_dx, raw_dx); // 输入PID输出和原始偏差 float adrc_dy = adrc_y.update(pid_dy, raw_dy); // *步骤3:贝塞尔曲线生成平滑路径(解决移动拖影) cv::Point2f target_pos(last_mouse_pos.x + adrc_dx, last_mouse_pos.y + adrc_dy); std::vector<cv::Point2f> path = BezierCurve::generatePoints(last_mouse_pos, target_pos); // *步骤4:按平滑路径移动鼠标 for (const auto& p : path) { mouse->updateTarget(p.x - last_mouse_pos.x, p.y - last_mouse_pos.y); last_mouse_pos = p; // 更新当前鼠标位置 Sleep(1); // 微小延迟,确保平滑效果 } } else { // 无目标时重置 mouse->updateTarget(0.0f, 0.0f); pid_x.reset(); pid_y.reset(); adrc_x.reset(); // *重置ADRC adrc_y.reset(); last_mouse_pos = cv::Point2f(0, 0); target_locked = false; tracked_id = -1; lock_frames_counter = 0; } } else { // 未按触发键时重置 if (mouse) mouse->updateTarget(0.0f, 0.0f); target_locked = false; tracked_id = -1; tracking_counter = 0; lock_frames_counter = 0; pid_x.reset(); pid_y.reset(); adrc_x.reset(); // *重置ADRC adrc_y.reset(); last_mouse_pos = cv::Point2f(0, 0); } // ==== 调试窗口显示 ==== if (config.show_window) { cv::Mat a(height, width, CV_8UC3, s); if (!newbox.empty()) { for (const Box& detection : newbox) { cv::Scalar color = (current_target && detection.id == current_target->id) ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0); int thickness = (current_target && detection.id == current_target->id) ? 2 : 1; cv::rectangle(a, cv::Point((int)detection.left, (int)detection.top), cv::Point((int)detection.right, (int)detection.bottom), color, thickness ); std::string class_str = std::to_string(detection.class_label); char conf_str[16]; snprintf(conf_str, sizeof(conf_str), "%.2f", detection.confidence); int fontFace = cv::FONT_HERSHEY_SIMPLEX; double fontScale = 0.4; int textThickness = 1; cv::Point textOrg((int)detection.left, (int)detection.top - 4); if (textOrg.y < 10) textOrg.y = 10; cv::putText(a, class_str, textOrg, fontFace, fontScale, cv::Scalar(0, 0, 255), textThickness); cv::Size textSize = cv::getTextSize(class_str, fontFace, fontScale, textThickness, nullptr); cv::Point confOrg = textOrg + cv::Point(textSize.width + 4, 0); cv::putText(a, conf_str, confOrg, fontFace, fontScale, cv::Scalar(0, 255, 0), textThickness); } } // 绘制锚点和追踪线 if (current_target && any_aim_key_pressed && tracking_enabled) { int anchor_x_pos = current_target->left + (current_target->right - current_target->left) * config.anchor_x; int anchor_y_pos = current_target->top + (current_target->bottom - current_target->top) * config.anchor_y; cv::circle(a, cv::Point(anchor_x_pos, anchor_y_pos), 5, cv::Scalar(255, 0, 255), -1); cv::line(a, cv::Point(width / 2, height / 2), cv::Point(anchor_x_pos, anchor_y_pos), cv::Scalar(0, 255, 255), 1); } // 性能指标显示 int base_y = 20; int line_height = 18; double font_scale = 0.5; int thickness = 1; auto draw_metric = [&](const std::string& label, const std::string& value, int line) { int y = base_y + line * line_height; cv::putText(a, label, cv::Point(10, y), cv::FONT_HERSHEY_SIMPLEX, font_scale, cv::Scalar(0, 0, 255), thickness); cv::putText(a, value, cv::Point(80, y), cv::FONT_HERSHEY_SIMPLEX, font_scale, cv::Scalar(0, 255, 0), thickness); }; draw_metric("FPS:", std::to_string((int)fps), 0); draw_metric("CAPTURE:", std::to_string((int)capture_ms) + "ms", 1); draw_metric("DETECT:", std::to_string((int)detect_ms) + "ms", 2); draw_metric("TRACK:", tracking_enabled ? "ON" : "OFF", 3); // 状态信息显示 if (current_target) { std::string track_info = "TRACK: " + std::to_string(tracking_counter); cv::putText(a, track_info, cv::Point(width - 120, 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(200, 200, 0), 1); } if (target_locked) { std::string lock_info = "LOCKED: " + std::to_string(tracked_id); cv::putText(a, lock_info, cv::Point(width - 120, 60), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 200, 255), 1); } if (lost_counter > 0) { std::string lost_info = "LOST: " + std::to_string(lost_counter); cv::putText(a, lost_info, cv::Point(width - 120, 90), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 200, 200), 1); } // 窗口置顶设置 static bool topmost_set = false; if (!topmost_set) { HWND hwnd = FindWindowA(NULL, "c"); if (hwnd) { SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); } topmost_set = true; } cv::imshow("c", a); cv::waitKey(1); } } // 退出前释放资源 if (mouse) { mouse->stop(); delete mouse; mouse = nullptr; } delete frame; if (cap_impl) { if (config.screenshot_method == 0) { delete static_cast<capture*>(cap_impl); } else { delete static_cast<capture_win32*>(cap_impl); } } timeEndPeriod(1); return 0; }这个是c++程序,你帮忙分析一下,为什么跟踪目标会跟不上,还会有拖影
07-14