Skip to content

Commit

Permalink
更换模型,修复分析模式Bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincentzyx committed Jul 11, 2022
1 parent e523baf commit 2ab9b69
Show file tree
Hide file tree
Showing 28 changed files with 863 additions and 146 deletions.
676 changes: 676 additions & 0 deletions README.html

Large diffs are not rendered by default.

103 changes: 86 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,66 @@
# VinXiangQi
基于Yolov5的中国象棋连线工具
一款基于深度学习(YOLOv5)的中国象棋连线工具

模型训练集中天天象棋的样本较多,其他棋盘的识别效果不一定好。
该程序当前阶段还缺少许多功能,**希望有人能加入一起完善**
#### 软件/技术交流群:755655813

目前仅测试过天天象棋和JJ象棋,JJ象棋因为等待时有动画,所以识别效果不是很理想。
## 软件简介

该程序当前阶段只是一个想法验证,还缺少许多功能,**希望有人能加入一起完善**
#### 交流群:755655813
#### 0、界面介绍

## 使用方法
![image-20220711145322503](assets/image-20220711145322503.png)

**1、识别画面**

![image-20220711145437807](assets/image-20220711145437807.png)

显示Yolo模型对画面的识别情况

**2、识别结果**

![image-20220711145528668](assets/image-20220711145528668.png)

显示目前局面的稳定识别结果以及引擎的走法,**注意:该部分棋子可以点击,点击时会自动把对棋子的点击转发到被连线的游戏和软件中,方便对游戏中点击位置进行调试**

**3、引擎设置**

![image-20220711145715450](assets/image-20220711145715450.png)

**4、识别设置**

![image-20220711145734293](assets/image-20220711145734293.png)

**5、引擎思考输出**

![image-20220711145912807](assets/image-20220711145912807.png)

**6、引擎设置**

![image-20220711145946599](assets/image-20220711145946599.png)

通过UCI或者UCCI协议获取到的关于引擎的设置选项

**7、开局库设置**

![image-20220711150033775](assets/image-20220711150033775.png)

选择是否使用云库和开局库

**8、自动点击管理**

![image-20220711150109702](assets/image-20220711150109702.png)

当连线设置中的自动点击被勾选时,软件会自动点击画面中保存模板的位置,可以实现自动续盘等功能。

使用方式:在右侧的画面中,点击需要框选的区域的左上和右下的点,确认无误后点击保存,即可保存自动点击的模板。

**9、保存方案**

![image-20220711150256531](assets/image-20220711150256531.png)

当使用 “寻找窗口句柄” 功能创建方案后,确定方案可用后,点击 “保存当前方案” 即可将当前方案保存下来下次使用。

**需要注意的是,如果截图标题中包含有关当前对局或者网址的信息,可以将截图标题删去,保留截图类,可能方案会更通用。**

#### 1、创建方案或使用内置方案

Expand Down Expand Up @@ -44,26 +96,41 @@
#### 2、确认窗体缩放比

1. 选中你想要使用的方案
2. ![image-20220711143552442](assets/image-20220711143552442.png)
3. 根据左上角截图情况调整缩放比:如果截图显示不全,则增大缩放比;如果截图存在黑边,就减小缩放比,直到窗口完美覆盖图片。
4. 关闭调试状态

2. 勾选调试模式
#### 3、前台与后台

![image-20220705022934060](assets/image-20220705022934060.png)
![image-20220711143729937](assets/image-20220711143729937.png)

3. 根据左上角截图清空调整缩放比:如果截图显示不全,则增大缩放比;如果截图存在黑边,就减小缩放比,直到窗口完美覆盖图片。
#### 截图模式

4. 关闭调试状态
**后台截图:仅对窗口,而不是整个桌面进行截屏,在该模式下,连线的目标窗体可以被遮挡,不影响截图。**

#### 3、开始下棋
但需要注意的是,该模式并非通用方法,有的游戏和软件因为渲染方式的不同,并不能使用该方式截到图,这时调试状态显示的画面为黑色的。如果遇到这类软件,就需要勾选前台截图,使用截取屏幕的方式进行截图。

​ 1.勾选自动走棋
**前台截图:通用模式,所有游戏和软件都可以使用,但是要求窗口不能被遮挡。**

​ 2.对于等待中没有动画的棋盘(如天天象棋)则关闭持续识别模式;对于等待中存在动画的棋盘(如JJ象棋)则打开持续识别模式
#### 鼠标模式

​ 3.打开象棋对局
**后台鼠标:通过给目标窗口发送系统消息的方式进行鼠标操作,不是所有软件和游戏都能用。**

​ 4.这时连线应该已经自动开始了,如没有开始,则点击重新检测棋盘来刷新
该方式允许你在进行连线的时候鼠标同时操作别的事务,请优先选择该模式,如果遇到点击失败,则勾选前台鼠标模式。

![image-20220705022917134](assets/image-20220705022917134.png)
**前台鼠标:通用模式,所有游戏和软件都可以用,但是会占用鼠标,如果在连线点击下棋的过程中移动了鼠标,就有可能导致点击失败。**



#### 3、开始下棋

​ 1.打开游戏中的对局

​ 2.根据当前轮到我方或者对方,选择我方开始或是对方开始

​ 3.这时连线应该已经自动开始了,如没有开始,则点击重新检测棋盘来刷新

![image-20220711145322503](assets/image-20220711145322503.png)

#### 4、自动续盘

Expand Down Expand Up @@ -95,7 +162,7 @@

##### 4. 勾选自动点击

![image-20220705023904934](assets/image-20220705023904934.png)
![image-20220711150802910](assets/image-20220711150802910.png)

启用自动点击后,即可自动点击保存截图中的按钮,进行自动续盘

Expand All @@ -106,3 +173,5 @@
对于不能点击的情况,可以勾选前台鼠标,该方式占用鼠标进行点击,为通用方法。

如使用过程中出现停止分析(持续识别模式时有概率出现),则点击重新检测棋盘来检测。

**如果更多问题或者发现Bug,请加入软件/技术交流群:755655813,来反馈!**
Binary file added README.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
114 changes: 71 additions & 43 deletions VinXiangQi/DetectionLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ partial class Mainform

public string ExpectedMove = "";
public bool ChangeDetectedAfterClick = false;
public bool StartFromOpponent = false;
public bool TurnToOpponent = false;
public bool BackgroundAnalyzing = false;

//Dictionary<string, Bitmap> TemplateList = new Dictionary<string, Bitmap>();
Expand Down Expand Up @@ -99,6 +99,7 @@ void AutoClickLoop()
void DetectionLoop()
{
int gcCount = 0;
int getHandleCount = 0;
while (Running)
{
DateTime startTime = DateTime.Now;
Expand All @@ -118,6 +119,15 @@ void DetectionLoop()
}
if (GameHandle == IntPtr.Zero || !DetectEnabled)
{
if (Settings.SelectedSolution != "")
{
getHandleCount++;
if (getHandleCount % 10 == 0)
{
getHandleCount = 0;
comboBox_solution_SelectedIndexChanged(this, null);
}
}
Thread.Sleep(100);
continue;
}
Expand Down Expand Up @@ -304,7 +314,7 @@ bool CheckNewBoard()
if (Settings.AutoGo && !ChangeDetectedAfterClick)
{
AutoGoFailingCheckCount++;
if (AutoGoFailingCheckCount >= 3 && ClickRetryCount < 2)
if (AutoGoFailingCheckCount >= 5 && ClickRetryCount < 2)
{
AutoGoFailingCheckCount = 0;
ClickRetryCount++;
Expand Down Expand Up @@ -385,11 +395,7 @@ bool GetBoardFromPrediction(List<YoloPrediction> predictions, bool refreshBoard
{
tmpBoard[xPos, yPos] = prediction.Label.Name;
}
else if (xPos == -1 || xPos == 9 || yPos == -1 || yPos == 10)
{
Debug.WriteLine(prediction.Label.Name + " 位置检测错误");
return false;
}

if (prediction.Label.Name == "r_jiang")
{
if (yPos < 5)
Expand Down Expand Up @@ -566,33 +572,29 @@ await Task.Run(new Action(() =>

void ReloadBoard()
{
if (CurrentBoard == null) return;
var compareWithLast = Utils.CompareBoard(LastBoard, CurrentBoard);
var compareWithExpected = Utils.CompareBoard(ExpectedSelfGoBoard, CurrentBoard);
if (compareWithLast.DiffCount == 0) return;
string opponentSymbol =RedSide ? "b_" : "r_";
string mySymbol = RedSide ? "r_" : "b_";
Debug.WriteLine($"Diff Result: {compareWithLast.DiffCount} R: {compareWithLast.RedDiff} B: {compareWithLast.BlackDiff}");
if (StartFromOpponent)
string startingFen = "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR";
string currentFen = Utils.BoardToFen(CurrentBoard, RedSide ? "w" : "b", RedSide ? "w" : "b");
if (currentFen.StartsWith(startingFen) && !RedSide)
{
StartFromOpponent = false;
if (Settings.AnalyzingMode)
{
InvalidCount = 0;
LastBoard = (string[,])CurrentBoard.Clone();
DisplayStatus("分析对手");
string oppofen = Utils.BoardToFen(CurrentBoard,RedSide ? "w" : "b",RedSide ? "b" : "w");
EngineAnalyzingBoard = (string[,])CurrentBoard.Clone();
StartAnalyze(oppofen);
}
else
{
LastBoard = (string[,])CurrentBoard.Clone();
ExpectedSelfGoBoard = null;
ExpectedMove = "";
RenderDisplayBoard();
DisplayStatus("从对手开始");
return;
}
TurnToOpponent = true;
}

if (TurnToOpponent && !Settings.AnalyzingMode)
{
TurnToOpponent = false;
LastBoard = (string[,])CurrentBoard.Clone();
ExpectedSelfGoBoard = null;
ExpectedMove = "";
RenderDisplayBoard();
DisplayStatus("从对手开始,跳过当前局面");
return;
}
if (compareWithLast.BlackDiff > 1 || compareWithLast.RedDiff > 1)
{
Expand All @@ -616,29 +618,37 @@ void ReloadBoard()
}
return;
}
if (compareWithLast.DiffCount == 2 && compareWithLast.Chess != null && compareWithLast.Chess.Contains(mySymbol))
if (compareWithLast.DiffCount == 2 && compareWithLast.Chess != null)
{
RenderDisplayBoard();
if (Settings.AnalyzingMode)
if (compareWithLast.Chess.Contains(mySymbol))
{
InvalidCount = 0;
LastBoard = (string[,])CurrentBoard.Clone();
EngineAnalyzeCount++;
DisplayStatus("开始引擎计算");
string oppofen = Utils.BoardToFen(CurrentBoard,RedSide ? "w" : "b",RedSide ? "b" : "w");
EngineAnalyzingBoard = (string[,])CurrentBoard.Clone();
Engine.StartAnalyze(oppofen, Settings.EngineStepTime, Settings.EngineDepth);
RenderDisplayBoard();
if (Settings.AnalyzingMode)
{
InvalidCount = 0;
LastBoard = (string[,])CurrentBoard.Clone();
EngineAnalyzeCount++;
DisplayStatus("开始引擎计算");
string oppofen = Utils.BoardToFen(CurrentBoard, RedSide ? "w" : "b", RedSide ? "b" : "w");
EngineAnalyzingBoard = (string[,])CurrentBoard.Clone();
Engine.StopAnalyze();
StartAnalyze(oppofen);
}
else
{
InvalidCount = 0;
LastBoard = (string[,])CurrentBoard.Clone();
DisplayStatus("己方棋子变化,跳过分析");
ExpectedMove = "";
}
return;
}
else
{
InvalidCount = 0;
LastBoard = (string[,])CurrentBoard.Clone();
DisplayStatus("己方棋子变化,跳过分析");
ExpectedMove = "";
TurnToOpponent = false;
}
return;
}
if (compareWithExpected.DiffCount == 0)
if (compareWithExpected.DiffCount == 0 && !Settings.AnalyzingMode)
{
LastBoard = (string[,])CurrentBoard.Clone();
ExpectedMove = "";
Expand All @@ -662,6 +672,24 @@ void ReloadBoard()
EngineAnalyzeCount++;
LastBoard = (string[,])CurrentBoard.Clone();

if (Settings.AnalyzingMode)
{
InvalidCount = 0;
string analyzeFen;
if (TurnToOpponent)
{
analyzeFen = Utils.BoardToFen(CurrentBoard, RedSide ? "w" : "b", RedSide ? "b" : "w");
}
else
{
analyzeFen = Utils.BoardToFen(CurrentBoard, RedSide ? "w" : "b", RedSide ? "w" : "b");
}
Engine.StopAnalyze();
EngineAnalyzingBoard = (string[,])CurrentBoard.Clone();
StartAnalyze(analyzeFen);
return;
}

string fen = Utils.BoardToFen(CurrentBoard,RedSide ? "w" : "b",RedSide ? "w" : "b");
if (Settings.BackgroundAnalysis && BackgroundAnalyzing)
{
Expand Down
20 changes: 18 additions & 2 deletions VinXiangQi/EngineHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class EngineHelper
public int AnalyzeCount = 0;
public int SkipCount = 0;
public DateTime LastOutputTime = new DateTime();
public string IgnoreMove = "";


public EngineHelper(string enginePath, Dictionary<string, string> configs = null)
Expand All @@ -40,7 +41,7 @@ public void Stop()
{
try
{
if (Engine != null && Engine.Handle != IntPtr.Zero && !Engine.HasExited)
if (Engine != null)
{
Engine.Kill();
}
Expand All @@ -66,7 +67,22 @@ public void Init()
Engine.StartInfo.WorkingDirectory = string.Join("\\", pathParams.Take(pathParams.Length - 1));
Engine.OutputDataReceived += Engine_OutputDataReceived;
Engine.Start();
Engine.PriorityClass = ProcessPriorityClass.BelowNormal;
int tryCount = 10;
bool success = false;
while (!success && tryCount > 0)
{
tryCount--;
try
{
Engine.PriorityClass = ProcessPriorityClass.BelowNormal;
success = true;
}
catch (Exception ex)
{
Debug.WriteLine("加载引擎时失败: " + ex.ToString());
Thread.Sleep(500);
}
}
ThreadHandleOutput = new Thread(new ThreadStart(WaitForExit));
ThreadHandleOutput.Start();
Engine.BeginOutputReadLine();
Expand Down
2 changes: 1 addition & 1 deletion VinXiangQi/Mainform.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 2ab9b69

Please sign in to comment.