棋盘棋谱+识别脚本等图片打包下载:
识别象棋盘.ahk
#NoEnv SetBatchLines -1 #SingleInstance, force SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. #Include <FindText> #Include <Gdip> Gui, -DPIScale ini := A_ScriptDir "\config.ini" IniRead, winTitle, %ini% , config, winTitle , IniRead, winID, %ini% , config, winID , IniRead, QPxywh, %ini% , config, QPxywh , 未框选... global TargetWindow ,QP ,QP_L , QP_R , viewQP , QPDate QP_L:=9 , QP_R:=10 ;棋盘的列 行数 WinGetPos, winX, winy, winW, winH,% winTitle TargetWindow:={title:winTitle , ID:winID , winX:winx , winY:winY , winW: winW ,winH:winH , QParea:QPxywh} ; 目标窗口信息 Gui,font,s10 ,微软雅黑 Gui,add,button,xm ym g指定窗口 vBT_getTargetWin,选择目标窗口 winTitleInfo:=(winID="" or winID="error") ? "未选择..." : winTitle " - " winID Gui,add,edit ,x+5 w300 vT_TargetWindow Disabled,% winTitleInfo Gui,add,button ,xm y+10 g框选棋盘范围,框选棋盘范围 Gui,add,edit ,x+5 w300 vT_QPsize Disabled,% QPxywh ; gui,add,button,xm y+20 g绘制棋盘窗口 ,绘制棋盘窗口 Gui,add,button,xm y+10 g识别棋盘 ,识别棋盘 Gui,add,text,x+5 y+-22 vT_tip w200 r1, ;---预览棋盘的 大小设定 getD:=getKJxywh(1,"T_QPsize") preViewQP_w:=getD.x + getD.w preViewQP_h:=(preViewQP_w /9) * 10 aGird:= preViewQP_w / QP_L ; 棋盘内框到外框的范围,预留空间给棋子, 棋盘的格子应该比整个pic显示区域要小一些,不然棋子超出范围的部分就看不到 girdW := (preViewQP_w - aGird) / (QP_L -1) ;格子的宽度 viewQP:={outWidth: preViewQP_w , outHeight: preViewQP_h , inWidth: preViewQP_w - aGird , inHeight: preViewQP_H - aGird , girdWidth: girdW , girdHeight: girdW , margin: aGird/2 } ; 棋盘大小信息 gui Add, Progress, xm y+5 h6 w%preViewQP_w% cGreen vPG_tipCHeck ,0 ; 识别进度条 Gui Add, Picture, xm y+5 w%preViewQP_w% h%preViewQP_h% 0xE vGidpPic ; 必须有个图片控件,因为gdip引用该图片的指针来修改内容 getGidpPic:=getKJxywh(1,"GidpPic") Gui +Resize Gui show gui,+LastFound hwnd1 := WinExist() GoSub, Gdip绘制棋盘 return getFind(Text){ ; 全屏范围 , 范围越小速度越快 ; get:=FindText(X, Y, 667-150000, 806-150000, 667+150000, 806+150000, 00, 0, Text) ; 目标窗口的范围 ; x1:=TargetWindow.winX , y1:=TargetWindow.winY , x2:=x1 + TargetWindow.winW , y2:=y1 + TargetWindow.winH ; 目标窗口的棋盘范围 + 一个格子的范围 x1:=TargetWindow.winX + QP.x - QP.GirdWidth y1:=TargetWindow.winY + QP.y - QP.GirdWidth x2:=TargetWindow.winX + QP.x + QP.Width + QP.GirdWidth y2:=TargetWindow.winY + QP.y + QP.height + QP.GirdWidth X:=Y:="" get:=FindText(X, Y, x1, y1, x2, y2, 0, 0, Text) return get } 指定窗口: while ! GetKeyState("lbutton","P") { MouseGetPos, cx, cy, winID, kj WinGetTitle, winTitle, ahk_id %winID% ToolTip ,% "xy:" cx "," cy "`n标题:" winTitle "`nID:" winID "`n点击鼠标左键确定坐标" } ToolTip GuiControl,, T_TargetWindow , % winTitle " - " winID "" TargetWindow["Title"]:=winTitle TargetWindow["ID"]:=winID IniWrite, %winTitle%, %ini% , config, winTitle IniWrite, %winID%, %ini% , config, winID 棋盘左上边缘 := "|<>0xD8C4A5@0.92$11.000000zlzXz7yDwTszs" 棋盘右下边缘 := "|<>0x513F22@0.96$15.010080100801008010080100801008zz00000000U" FindText().BindWindow(winID,1) ; 后台绑定模式目前有0-4 WinGetPos, pX, pY, pW, pH, ahk_id %winID% if ( FindText(棋盘X, 棋盘Y, pX, pY, pX+pW, pY+pH, 0, 0, 棋盘左上边缘, ,0) and FindText(棋盘X2, 棋盘Y2, pX, pY, pX+pW, pY+pH, 0, 0, 棋盘右下边缘, ,0) ) { 棋盘X:=棋盘X -pX , 棋盘Y:=棋盘Y-pY QPxywh:= 棋盘X+36 "," 棋盘Y+39 "," 棋盘X2-棋盘X-145 "," 棋盘Y2-棋盘Y-242 ToolTip % 棋盘X2-棋盘X """" 棋盘Y2-棋盘Y ; Gosub 自动识别棋盘边缘 } Return 框选棋盘范围: CoordMode, Mouse CoordMode, ToolTip SysGet, allWin_w, 78 SysGet, allWin_h, 79 Gui,9: Destroy Gui,9: +LastFound +AlwaysOnTop Gui,9: Color, black WinSet, Transparent, 50 Gui,9: -Caption +ToolWindow +E0x08000000 Gui,9: Show, NA x0 y0 w%allWin_w% h%allWin_h% ;gui9为了避免框选时候响应文件夹或者桌面(用冻结显示后,次窗口的作用仅作为做个白底提示当前正在截图) ;----------------------------- Gui,8: Destroy Gui,8: +LastFound +AlwaysOnTop WinSet, Transparent, 100 Gui,8: -Caption +ToolWindow +E0x08000000 Gui,8: Color, red ; ------ WinGetPos, winX, winy, winW, winH,% TargetWindow.Title down=0 Loop { Sleep, 50 MouseGetPos, x, y if (down=0) { ToolTip, %x%,%y%`n按住鼠标左键选择范围!`n取消请按【esc】键 mx1:=x , my1:=y if GetKeyState("LButton","P") down:=1, x1:=x, y1:=y if GetKeyState("esc","P") Break } else { mx2:=x , my2:=y w:=Abs(x-x1), h:=Abs(y-y1) x:=x1<x ? x1:x, y:=y1<y ? y1:y qpX:=x -winX , qpY:=y-winY ToolTip % "坐标:" x "," y "`n棋盘坐标:" qpX "," qpY "`n选区:" w "x" h "`n`n松开鼠标左键确定范围!" Gui,8: Show, NA x%x% y%y% w%w% h%h% if not GetKeyState("LButton","P") Break } } ToolTip ; Gdip_Shutdown(pToken) ;关闭冻结的画面 Gui,9: Destroy Gui,8: Destroy ; qpY+8是个人修正识别坐标 QPxywh:= qpX "," qpY+8 "," w "," h 自动识别棋盘边缘: GuiControl, ,T_QPsize,% QPxywh IniWrite, %QPxywh%, %ini% , config, QPxywh TargetWindow["QParea"]:=QPxywh ; 更新棋盘的区域 Gosub, 识别棋盘 Return 识别棋盘: gui,Submit,NoHide ; ---获取更新游戏窗口大小,计算棋盘格子大小 WinGetPos, winX, winy, winW, winH,% TargetWindow.title TargetWindow["winX"]:=winx TargetWindow["winY"]:=winY TargetWindow["winW"]:=winW TargetWindow["winH"]:=winH arr:=StrSplit(TargetWindow.QParea, ",") QP:={x:arr[1] , y: arr[2] , width: arr[3] , height: arr[4] , GirdWidth:0} QP["GirdWidth"]:=QP.width / (QP_L-1) ; 单个格子宽, 正方形 ; Gird:={width: QP.width / (QP_L-1) , height: QP.height / (QP_R-1)} ; 单个格子长宽 ; ---棋子字库 ZK:=[] ZK["红方"]:=[] ZK["黑方"]:=[] ZK["红方"]["兵"]:="|<>#359@1.00$31.20Ts01zzzk0Tk1w0D0000300001U0000TzzU0Dzzk070M002080010A000UT000zzz07zzzzzw00zrU007n000000C0000y1w01y0Tk0y07s0M01s000081" ZK["红方"]["砲"]:="|<>#435@1.00$32.000U00008007U6007z1U01zkzzkTkD0M607061U10F0E1zwEC37207zV021zsEEUzy7w8911y00EEM104A40U1210M0T0Ew07UA0010300000N01007z1k017zs000Dw0000S8" ZK["红方"]["馬"]:="|<>0xAC2000@0.90$28.00zzkTzzz0S1U01UC0037zz0DzkQ0kA0021zy0TzkE1sA0060k00kTzz3zzzwDw03Vs00600EkE0V1l2247As800nU006A0Dzs00Tz000Tw8" ZK["红方"]["仕"]:="|<>#267@1.00$31.0E0E00Q0801y0403y0603y0300z03k0T0TzzbXzzzUlzzzk8z73k48300201U0100k00U0M00E0A0080C00A0Tw065zzk37zzw1Xzzz0ks070M000040001" ZK["红方"]["車"]:="|<>0xAC2000@0.90$32.00600003zw0TzzzsDyC06201U0000zs03zzzy0zlU3060M0U1Uzzs0TnUS060E1U30C0M0zzzy0TUM3U40600001U000DzzXTzzzzzzzXzvy0M3ws0606001U0000M0000600001002" ZK["红方"]["相"]:="|<>#390@1.00$31.0M1zw0S3zzlzszrzzwA0Pzk40Bsk2040M1zy0A0zz0D0M1UDs80ETy609wU37wwE1zyA81s3040k1U20M0k10A0M0U60A0E7zy087zz04703Y" ZK["红方"]["帅"]:="|<>#138@1.00$29.0w040zz081zy1wN08zzW0Fzy43Xa4Dz6A8TwAMEk0EkV00VV271327zW64Dy4AAE4MMMU8kkn0lVVbza33DzM67S00A5000M0000k000108" ZK["黑方"]["炮"]:="|<>0x1A1A1A@0.55$34.000E000k3U0030A000A0s000nbzyE3CzzsTDvzzVwkT0A7m3nwkTMzza1tUTyM361klU0N3DC03iDsk0CxzX01vrsQ0DDQ3U5wtrw0TU7Dk3w0QA0Dk1k03Q07zUs00TzzU01zzy0007zk0003y8" ZK["黑方"]["馬"]:="|<>0x1A1A1A@0.90$28.00zzkTzzz0S1U01U60037zz0DzkQ0kA0021zy0TzkE1sA0060k00EDzw3zzzwDw03Vs006000kE011V0247AM800nU006A0Dzs00Tz000Tw8" ZK["黑方"]["車"]:="|<>#465@0.90$32.00600003zw0TzzzsDyC06201U0000zs03zzzy0zlU3060M0U1Uzzs0TnUS060E1U30C0M0zzzy0TUM3U40600001U0007zw1TzzzzzzzXzvy0M3ws0606001U0000M0000600001002" ZK["黑方"]["士"]:="|<>#263@1.00$31.00A000060000300003U0001k000Dzy03zzzzzzzzzjz70zrs3U7XU1k0000s0000Q0000C0000700003U0001k0001w0003zz02Tzzs1zzzw0zzzy0T0001" ; 发现卒有两种不一样的棋子 ZK["黑方"]["卒"]:="|<>#417@1.00$31.00M0000S0001zzy1zz7b0zk1U00s1k00S0w00T0z00Rklk0M10A0M0U0000s0007zw01zzzzzz67zrw30Tnk1U1k00k0000M0000A000060000300001U0000k00U" ZK["黑方"]["卒2"]:="|<>0x1A1A1A@0.90$31.00Q0000T0001zzy1zz7b0zk3U00s1k00S1w00T0z00Rklk0Q10Q0M1U00E0s0007zw01zzzzzz7Dzrw30Tvs1U3k00k0000M0000A000060000300001U0000k00U" ZK["黑方"]["象"]:="|<>#313@1.00$30.00Q0003Uy03s0s0zU100zUT00tzzzs0yC0s0UA0U1UC101nzz03sk0041k0006k200kQ7070680M27000MDU01UGE0S32A0kA2600k67k3U43yD0A1zM0M0y03k0MU" ZK["黑方"]["将"]:="|<>#181@1.00$32.0007k160zA017z300FyEk0484A0301z08k3w07w1s03XDk00UFk000400M4201zz1UTzzbszUNkWA0208U00U283s8023s200Us0U48008120060EU010080zk000Dk0U" ZKarr:=[] for group,a in ZK { for z ,b in ZK[group]{ ZKarr.push( {group: group , text: ZK[group][z] , name: z } ) } } ; ---棋子配色 ; QZ_color:=[] ; QZ_color["红方"]:={fontColor: "ffffff" , BackgroundColor: "ff5932"} ; QZ_color["黑方"]:={fontColor: "32abff" , BackgroundColor: "11172d"} ; ---清空棋盘落子横纵数据 QPDate:=[] loop % QP_L { cLie:=A_Index loop % QP_R QPDate[cLie "_" a_index] := { qzName:"" , qzGroup:"" , zkName: ""} ; zkName 识别字库的名字,就有些棋子可能多个不同的图 } ; ---识别位置,并绘制,并储存到棋盘数据 timeA:=A_TickCount gui,2:font,s14 loop % ZKarr.Length(){ get:=getFind( ZKarr[a_index].text ) qzGroup :=ZKarr[a_index].group qzName:=ZKarr[a_index].name GuiControl,, PG_tipCHeck, % (a_index / ZKarr.Length()) * 100 ; 识别进度条 loop % get.Length(){ ; 棋子在游戏窗口里的坐标 QZinWinX:=get[A_Index].1-TargetWindow.winX QZinWinY:=get[A_Index].2-TargetWindow.winY ; 将坐标转换为格子横纵编号:1_2 3_5 QZ_L:=Ceil( (QZinWinX - QP.x) / QP.GirdWidth) + 1 ;列 QZ_H:=Ceil( (QZinWinY - QP.y) / QP.GirdWidth) + 1 ;行 QPDate[ QZ_L "_" QZ_H ]["qzName"] := SubStr(qzName, 1 , 1) ; 棋子名字,只取一个字(比如 卒2 只取 卒) QPDate[ QZ_L "_" QZ_H ]["qzGroup"]:= qzGroup QPDate[ QZ_L "_" QZ_H ]["zkName"]:= qzName ; ; pos:="x" QZinWinX " y" QZinWinY " w" get[A_Index].3 " h" get[A_Index].4 ; gui,2:add,progress,% pos " c" QZ_color[qzGroup].BackgroundColor ,100 ; pos:="x" QZinWinX + 5 " y" QZinWinY - 5 ; gui,2:add,text,% pos " BackgroundTrans c" QZ_color[qzGroup].fontColor, % qzName ; gui,2:add,text,% pos " BackgroundTrans c" QZ_color[qzGroup].fontColor, % qzName } ; MsgBox, % "旗子:" ZKarr[a_index].name "`n找到:" get.Length() " `qzGroup:" ZKarr[a_index].Group } timeLen:=A_TickCount - timeA ; timeLen_str:= timeLen > 1000 ? GuiControl, , T_tip , % "用时:" timeLen / 1000 " 秒" GuiControl,, PG_tipCHeck, 0 ; 识别进度条 Gosub, Gdip绘制棋盘 Return /* 使用GUI progress 绘制棋盘(弃用) 绘制棋盘窗口: gui,Submit,NoHide WinGetPos, winX, winy, winW, winH,% TargetWindow.title TargetWindow["winX"]:=winx TargetWindow["winY"]:=winY TargetWindow["winW"]:=winW TargetWindow["winH"]:=winH arr:=StrSplit(T_QPsize, ",") QP:={x:arr[1] , y: arr[2] , width: arr[3] , height: arr[4] } Gird:={width: QP.width / (QP_L-1) , height: QP.height / (QP_R-1)} ; 单个格子长宽 gui,2: Destroy gui,2:font,s10 ,微软雅黑 loop % QP_R gui,2:add,Progress, % "x" QP.x " y" (a_index-1) * Gird.height + QP.y " h3 w" QP.width " c888888", 100 loop % QP_L { lineH:=(a_index>1 and a_index< QP_L) ? Gird.height * 4 : QP.height gui,2:add,Progress, % "y" QP.y " x" (a_index-1) * Gird.width + QP.x " w3 h" lineH " c888888", 100 if(a_index>1 and a_index< QP_L) gui,2:add,Progress, % "y" Gird.height * 5 + QP.y " x" (a_index-1) * Gird.width + QP.x " w3 h" lineH " c888888", 100 } gui,2: +Resize gui,2:show,% "w" TargetWindow.winW " h" TargetWindow.winH Return */ getKJxywh(win,kjName){ ; win gui窗口编号,例如 gui:11 ; kjName 控件的变量名 gui,Submit,NoHide GuiControlGet,%kjName%,%win%:pos x:=%kjName%x , y:=%kjName%y , w:=%kjName%w , h:=%kjName%h ; arr:=[x,y,w,h] Return {x:x,y:y,w:w,h:h} } Gdip绘制棋盘: ;-----------------------------画图表 Gdip_Startup() GuiControlGet, hwnd, hwnd, GidpPic ; 绘图范围 , 从图片控件绘制图片 , 绘制边缘的平滑度 pBitmap := Gdip_CreateBitmap(preViewQP_w, preViewQP_h) G := Gdip_GraphicsFromImage(pBitmap) Gdip_SetSmoothingMode(G, 4) ; --画外框线 cMargin:=viewQP.margin*0.8 pPen := Gdip_CreatePen( "0xFF000000" , 2 ) ; 棋盘四个角的点位,1:左上角 2:右上角 3:右下角 4:左下角 Point:=[] point[1]:={x:0+cMargin , y:0+cMargin} point[2]:={x:viewQP.outWidth-cMargin , y:0+cMargin} point[3]:={x:viewQP.outWidth-cMargin , y:viewQP.outHeight-cMargin} point[4]:={x:0+cMargin , y:viewQP.outHeight-cMargin} pBrush := Gdip_BrushCreateSolid("0xffffe8c7" ) Gdip_FillRectangle(G, pBrush, point[1].x, point[1].y, point[2].x-point[1].x, point[4].y - point[1].y) ;棋盘背景色 Gdip_DrawLine(G, pPen, point[1].x, point[1].y, point[2].x, point[2].y) Gdip_DrawLine(G, pPen, point[1].x, point[1].y, point[4].x, point[4].y) Gdip_DrawLine(G, pPen, point[3].x, point[3].y, point[2].x, point[2].y) Gdip_DrawLine(G, pPen, point[3].x, point[3].y, point[4].x, point[4].y) ; --画内格子线 pPen := Gdip_CreatePen( "0xFF31240f" , 1 ) loop % QP_R { getA:=girdToViewQPpos( "1_" A_Index ) getB:=girdToViewQPpos( "9_" A_Index ) Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) } loop % QP_L { if(a_index>1 and a_index< QP_L) { getA:=girdToViewQPpos(A_Index "_1") getB:=girdToViewQPpos(A_Index "_5") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) getA:=girdToViewQPpos(A_Index "_6") getB:=girdToViewQPpos(A_Index "_10") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) } Else { getA:=girdToViewQPpos(A_Index "_1") getB:=girdToViewQPpos(A_Index "_10") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) } } ; --画米字 getA:=girdToViewQPpos("4_1") , getB:=girdToViewQPpos("6_3") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) getA:=girdToViewQPpos("4_3") , getB:=girdToViewQPpos("6_1") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) getA:=girdToViewQPpos("4_8") , getB:=girdToViewQPpos("6_10") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) getA:=girdToViewQPpos("4_10") , getB:=girdToViewQPpos("6_8") Gdip_DrawLine(G, pPen, getA.x, getA.y, getB.x, getB.y) ; --画炮、兵点位线 pPen := Gdip_CreatePen( "0xFF000000" , 2 ) curArr:=[ "2_3","8_3","2_8","8_8" , "1_4","3_4","5_4","7_4","9_4","1_7","3_7","5_7","9_7" ] loop % curArr.Length() { get := girdToViewQPpos(curArr[A_Index]) margin:=3 , len:=viewQP.girdWidth * 0.18 cc:=[[-1,-1] ,[1,-1] ,[-1,1] , [1,1] ] ;[ 上左,上右,下左,下右] cLie:= SubStr(curArr[A_Index], 1 , 1) loop 4 { if( (cLie = 1 && a_index=1) or (cLie = 1 && a_index=3) or (cLie = QP_L && a_index=2) or (cLie = QP_L && a_index=4) ) Continue x1:=get.x + cc[A_Index][1] * margin y1:=get.y + cc[A_Index][2] * margin index:=a_index loop % 2{ x2:=(a_index=1) ? x1 : x1 + cc[index][1] * len ;先画竖线 y2:=(a_index=1) ? y1 + cc[index][2] * len : y1 Gdip_DrawLine(G, pPen, x1, y1, x2, y2) } } } ; --画棋子 Qz_width:= girdW * 0.8 ; --棋子配色 QZ_color:=[] QZ_color["红方"]:={fontColor: "ac2000" , BackgroundColor: "efae7f" , BackgroundColor2: "642b09" } QZ_color["黑方"]:={fontColor: "1a1a1a" , BackgroundColor: "ffc974" , BackgroundColor2: "703f00" } for LR , i in QPdate { cQz:=QPdate[LR] if(cQz.qzName="") Continue get:=girdToViewQPpos(LR) cx:=get.x - Qz_width/2 , cy:=get.y - Qz_width/2 ; pBrush := Gdip_BrushCreateHatch("0xffdb6c64" , "0xffFFFFFF", a_index) ; backColor , forcCOlor, bursh样式 ; pBrush := Gdip_BrushCreateSolid("0xff" QZ_color[cQz.qzGroup].BackgroundColor2) Gdip_FillEllipse(G, pBrush, cx, cy, Qz_width + 4, Qz_width + 4) ;棋子底层 pBrush := Gdip_BrushCreateSolid("0xff" QZ_color[cQz.qzGroup].BackgroundColor) Gdip_FillEllipse(G, pBrush, cx, cy, Qz_width, Qz_width) ;棋子表层 Gdip_TextToGraphics(G, cQz.qzName ,"x" cx+2 "y" cy+5 "c" "FF" QZ_color[cQz.qzGroup].fontColor " s26 Center Bold ", "微软雅黑", Qz_width, Qz_width) ;文字 } hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap) SetImage(hwnd, hBitmap) ;应用图片内容 Gdip_DeleteBrush(pBrush) , Gdip_DeletePen(pPen) ;删除不再需要的画笔释放内存 Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap) Gdip_Shutdown(pToken) Return girdToViewQPpos(str:="1_1"){ arr:=StrSplit(str, "_" ) cx:= viewQP.girdWidth * (arr[1]-1) + viewQP.margin cy:= viewQP.girdheight * (arr[2]-1) + viewQP.margin ; MsgBox, % viewQP.girdWidth "`n" viewQP.girdheight "`n " viewQP.margin return {x:cx , y:cy} } GuiClose: ExitApp
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)