//目标跟踪,参数位检测的屏幕区域位置、及检测到的对象位置 private void AutoAction(DetectionResult4Rect detectionResult4Rect) { //计算对象的中心点,基于实际检测区域计算 int objCenterX = detectionResult4Rect.maxConfidencePos.x1 + (detectionResult4Rect.maxConfidencePos.x2 - detectionResult4Rect.maxConfidencePos.x1) / 2; int objCenterY = detectionResult4Rect.maxConfidencePos.y1 + (detectionResult4Rect.maxConfidencePos.y2 - detectionResult4Rect.maxConfidencePos.y1) / 3; objCenterX = detectionResult4Rect.detectionRect.x + objCenterX; objCenterY = detectionResult4Rect.detectionRect.y + objCenterY; //计算屏幕中心点,要基于原始窗口区域计算 int screenCenterX = detectionResult4Rect.rawDetectionRect.x + detectionResult4Rect.rawDetectionRect.w / 2; int screenCenterY = detectionResult4Rect.rawDetectionRect.y + detectionResult4Rect.rawDetectionRect.h / 2; //对于目前的3D游戏,瞄准就是把屏幕中心点,移动到对象中心点 //计算准星到对象中心点的相对位置 int moveX = objCenterX - screenCenterX; int moveY = objCenterY - screenCenterY; //自动开枪 bool fireing = false; if (autoFire) { fireing = AutoFire(detectionResult4Rect, moveX, moveY); } //自动追踪 if ((autoTrace && autoTraceType == 1) || (autoTrace && autoTraceType == 2 && autoTraceTimeOut > 0)) { //持续追踪或则鼠标右键瞄准触发追踪 AutoTrace(detectionResult4Rect, moveX, moveY); } }
public long toltalMillis; //检测执行的时间 public void setValues(DetectionRect rawDetectionRect1, DetectionRect detectionRect1, Mat frameMat1, List <ObjectPosRect> objectPosRects1, ObjectPosRect maxConfidencePos1, int maxPersonW1, long toltalMillis1) { detectionResult4Rect = new DetectionResult4Rect(); detectionResult4Rect.rawDetectionRect = rawDetectionRect1; detectionResult4Rect.detectionRect = detectionRect1; detectionResult4Rect.maxConfidencePos = maxConfidencePos1; detectionResult4Rect.maxPersonW = maxPersonW1; frameMat = frameMat1; objectPosRects = objectPosRects1; toltalMillis = toltalMillis1; }
//自动开枪 private bool AutoFire(DetectionResult4Rect detectionResult4Rect, int moveX, int moveY) { bool fired = false; //判断是否已瞄准对象 if (moveX <= (detectionResult4Rect.maxConfidencePos.x2 - detectionResult4Rect.maxConfidencePos.x1) / 4 && moveY <= (detectionResult4Rect.maxConfidencePos.y2 - detectionResult4Rect.maxConfidencePos.y1) / 6) { //调用异步的自动开枪方法 AutoFireAction(this.processName, this.gunType); fired = true; } return(fired); }
//执行自动鼠键操作 public void DoAutoAction(DetectionResult4Rect detectionResult4Rect) { //先检测是否打开了NumLock键,打开了就启动自动开枪 //目前的设备,获取不到NumLock的键状态 //int numLock = GetNumLock(); //if (numLock != 2) // return; //检查设备状态 if (!usbDeviceStatus) { this.OpenUsbDevice(); } //自动追踪/自动开火 if (usbDeviceStatus) { AutoAction(detectionResult4Rect); } }
//鼠标操作后台线程 private void backgroundWorker_usbdev_DoWork(object sender, DoWorkEventArgs e) { var bgWorker = (BackgroundWorker)sender; //在后台线程中循环处理鼠标键盘操作 DetectionResult4Rect result = new DetectionResult4Rect(); while (!bgWorker.CancellationPending) { try { //如果队列中有多个需要处理的鼠标移动对象,则全部丢弃,只剩最后一个 //这样做的目的是在鼠标操作积压的时候,直接使用最新的图片位置检测结果,来移动鼠标,保障更实时的鼠标操作 while (posQueue.Count > 1) { posQueue.TryTake(out result); } //处理最后一个鼠标移动对象 if (posQueue.TryTake(out result, 100)) { //持续获取并处理检测结果 if (result.maxConfidencePos.confidence > 0) { this.usbDevice.DoAutoAction(result); systemStatus.currentX = this.usbDevice.currentX; systemStatus.currentY = this.usbDevice.currentY; this.textBox_msg.Text = systemStatus.GetSytemStatus(); } } //bgWorker.ReportProgress(0, null); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
//自动跟踪 private void AutoTrace(DetectionResult4Rect detectionResult4Rect, int moveX, int moveY) { //如果位置很接近了,则直接退出 if (Math.Abs(moveX) < 5 && Math.Abs(moveY) < 5) { return; } //由于是3D游戏,位置是3维坐标,物体越远,移动距离要乘的系数就越大。 //暂时没有好的方法通过图片检测计算3维坐标,先使用对象的大小初略计算z坐标,但是开镜后的大小暂时无法处理。 //为了处理太远图片的问题,在按对数log计算一个倍数,实现位置越远倍数不能太大的效果。 double zParam = 0; if (detectionResult4Rect.maxPersonW > 0) { zParam = (detectionResult4Rect.maxPersonW) / (detectionResult4Rect.maxConfidencePos.x2 - detectionResult4Rect.maxConfidencePos.x1); if (zParam > 1) { zParam = Math.Log(2 * zParam, 2); } } //再根据x/y的距离作为一个乘积参数,距离越小参数倍数越小,实现位置越近移动距离更小的效果。 if (moveX != 0 && moveY != 0) { double zParam2 = Math.Log(Math.Abs(moveX) + Math.Abs(moveY), 50); zParam = zParam * zParam2; } //另外由于游戏设置了鼠标灵敏度,所以鼠标移动,高根据游戏里面灵敏度设置,乘一个比例。 //使用模拟移动函数移动鼠标 Point point = GetCursorPosition(); if (point != null && zParam > 0) { currentX = point.X; currentY = point.Y; //如果坐标超出原始检测区域所在范围,则不再移动 //if (currentX > (detectionResult4Rect.rawDetectionRect.x + detectionResult4Rect.rawDetectionRect.w)) // return; //if (currentY < detectionResult4Rect.detectionRect.y || currentY > (detectionResult4Rect.detectionRect.y + detectionResult4Rect.detectionRect.h)) // return; if (this.processName.Equals(processNames[0])) { //绝地求生追踪的步长,对应游戏鼠标灵敏度设置,大概为50, //测试发现游戏控制了鼠标移动速度,移动距离和鼠标移动时间时间有关系, //最好把图像检测和鼠标移动任务分开,在单独的线程中执行鼠标移动操作,保障移动鼠标的执行时间。 //初略计算3d坐标移动倍数,乘以10避免小数位丢失 int multiple = (int)(zParam * 10); int targetX = currentX + multiple * moveX / 30; int targetY = currentY + multiple * moveY / 30; SimulationMove(targetX, targetY); } else if (this.processName.Equals(processNames[1])) { //逆战追踪的步长,对应游戏鼠标灵敏度设置,大概为10, //初略计算3d坐标移动倍数,乘以10避免小数位丢失 int multiple = (int)(zParam * 10); int targetX = currentX + multiple * moveX / 50; int targetY = currentY + multiple * moveY / 50; SimulationMove(targetX, targetY); } } }