-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCatFeed.py
More file actions
463 lines (343 loc) · 12.1 KB
/
Copy pathCatFeed.py
File metadata and controls
463 lines (343 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
"""
用於統計得到物品用
"""
import time,math
import threading
import win32gui
import win32ui,win32con,numpy
class WinTool:
"""
一些工具函式
"""
def get_distance(point1, point2):
"""get_distance 計算兩點偏差值
Arguments:
point1 -- Dict{'x':30,'y':30}
point2 -- Dict{'x':30,'y':30}
Returns:
偏差值
"""
x1, y1 = point1['x'], point1['y']
x2, y2 = point2['x'], point2['y']
return round(math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2))
def Thread(func,argsR=None,Mode=0):
"""Thread 運行新線程
會運行func的內容
Arguments:
func -- 指定觸發函式
argsR -- 傳遞給指定函式的參數
Mode -- 1 加入線程列表
"""
if argsR:
T1=threading.Thread(target=func,args=argsR)
else:T1 = threading.Thread(target=func)
#print(T1.getName(),T1.is_alive())
if Mode==0:
T1.start()
else:
T1.start()
T1.join()
def FindW(Window=None,Class=None):
"""
用於指定窗口定位
Window 查找特定窗口名稱
Class 纇名
Return -- list
[0]:ClassName
[1]:WindowText
[2]:WindowRect
[3]:handle
"""
handle=win32gui.FindWindow(Class,Window)
if handle == 0:
return None
else:
temp=[
win32gui.GetClassName(handle),
win32gui.GetWindowText(handle),
win32gui.GetWindowRect(handle),
handle,
]
return temp
def FWScale(Find_W='雷電模擬器',width=1920,height=1080,tip=0):
"""FWScale 用於計算縮放百分比
Keyword Arguments:
Find_W -- 查找指定窗口 (default: {'雷電模擬器'})
width -- 原始圖片分辨率 (default: {1920})
height -- 原始圖片分辨率 (default: {1080})
原始圖片分辨率是 指在原始窗口最大寬高下進行擷取的分辨率
tip -- 1 啟用偵錯信息 (default: {0})
Returns:
[0.3,0.1] 寬百分比 & 高百分比
"""
FWinD=__class__.FindW(Window=Find_W)
if FWinD:
WH=FWinD[2] #取得窗口範圍
widthW,heightH=WH[2]-WH[0],WH[3]-WH[1]
if tip==1:print(WH,widthW,heightH)
ScaleW,ScaleH=round(widthW/width,2),round(heightH/height,2)
if tip==1:print(ScaleW,ScaleH)
return [ScaleW,ScaleH]
def WCall(handle,extra):
"""
WCall - 獲取窗口標題並打印
handle 句柄
extra 格式設定
"""
wind=extra
temp=[]
temp.append(win32gui.GetWindowText(handle))
wind[handle]=temp
print(f"{handle}:{extra}")
def CheckActiveWindow():
"""
此方法獲取正在使用窗口信息
return 字典 Dict
窗口標題 Text 標題長度 Len
纇名 Class 窗口大小 Rect(x1,y1,x2,y2)
枸柄Handle
"""
ActWindow=win32gui.GetForegroundWindow() #取當前正在使用的窗口
WindowLen=win32gui.GetWindowTextLength(ActWindow)
if win32gui.GetWindowText(ActWindow) == "":
WindowT="沒有窗口標題"
else:
WindowT=win32gui.GetWindowText(ActWindow)
Result={
"Text":WindowT,
"Len":WindowLen,
"Class":win32gui.GetClassName(ActWindow),
"Rect":win32gui.GetWindowRect(ActWindow),
"Handle":ActWindow
}
return Result
def WinDC(handle):
"""
取得特定窗口的畫面
handle - 要獲取的窗口枸柄
Return - Dict 字典
| Dict 鍵值 | 說明 |
| --- | --- |
| RGB | 3通道圖像 |
| BGRA | 原始4通道圖像 |
| BITMAP | BitMap數據 |
"""
x1,y1,x2,y2=win32gui.GetWindowRect(handle)
width,height=x2-x1,y2-y1
hwin=win32gui.GetWindowDC(handle)
srcDC=win32ui.CreateDCFromHandle(hwin)
memDC=srcDC.CreateCompatibleDC()
bmap=win32ui.CreateBitmap()
bmap.CreateCompatibleBitmap(srcDC,width,height)
memDC.SelectObject(bmap)
memDC.BitBlt((0,0),(width,height),srcDC,(0,0),win32con.SRCCOPY)
ArrayScr=bmap.GetBitmapBits(True)
img=numpy.frombuffer(ArrayScr,dtype=numpy.uint8)
img.shape=(height,width,4) #原始4通道
b,g,r,a=cv2.split(img) #通道分割
RGBIMG=cv2.merge((b,g,r),img)
Result={
"RGB":RGBIMG,
"BGRA":img,
"BITMAP":ArrayScr,
"srcDC":srcDC
}
srcDC.DeleteDC()
memDC.DeleteDC()
#最大化動畫關閉
#win32gui.SystemParametersInfo(win32con.SPI_SETANIMATION,0)
win32gui.ReleaseDC(handle,hwin)
win32gui.DeleteObject(bmap.GetHandle())
return Result
def send_bitmap(hwnd, bmp):
"""
將位圖數據傳遞給窗口
"""
import win32ui,win32con,numpy
# 創建 device context
hdc = win32gui.GetDC(hwnd)
memdc = win32ui.CreateDCFromHandle(hdc)
bmpdc = memdc.CreateCompatibleDC()
# 創建 bitmap 對象
bmpobj = win32ui.CreateBitmap()
bmpobj.CreateCompatibleBitmap(memdc, bmp.shape[1], bmp.shape[0])
# 將圖像數據寫入 bitmap 對象
img = numpy.ascontiguousarray(bmp[..., ::-1])
bmp_info = {
'bmType': 0,
'bmWidth': img.shape[1],
'bmHeight': img.shape[0],
'bmPlanes': 1,
'bmBitsPixel': 24,
'bmBits': img.tobytes(),
}
import win32api
win32api.SetBitmapBits(bmp_info['bmBits'])
# 將 bitmap 對象寫入 device context
bmpdc.SelectObject(bmpobj)
win32gui.SendMessage(hwnd, win32con.WM_PAINT, 0, 0)
# 刪除 device context 和 bitmap 對象
memdc.DeleteDC()
bmpdc.DeleteDC()
win32gui.ReleaseDC(hwnd, hdc)
bmpobj.DeleteObject()
def NowTime(Format=f"%Y/%m/%d %p %H:%M:%S",**Replace):
"""
Format:f"%Y/%m/%d" 顯示樣式調整
Replace:文字替換
使用方法:設定一個你要替換的參數
例:NowTime(AM="上午")
字串結果裡會找到替換AM成上午
例2:NowTime(_2023=2023年)
如果你要用數字只要前面先加上_即可
會取_後的文字
Return:String 本地時間
"""
curTime=time.time()
format_time=time.localtime(curTime) #本地時間
str=time.strftime(Format,format_time) #格式轉換
for key in Replace:
if key.find("_") != -1:
keyS=key.split("_")[1]
else:
keyS=key
str = str.replace(keyS, Replace[key])
return str
from PIL import Image,ImageDraw
import matplotlib.pyplot as PLT #交互窗口
import matplotlib
from matplotlib.animation import FuncAnimation
matplotlib.use("TkAgg",force=True)
class PILTool:
def ShowIM(self,img,hwnd):
print("test")
import cv2
class cv2Tool:
"""
此類整合了 關於使用cv2方法
"""
def ShowImage(img=None,title="TestShowImg",Delay=5000):
"""ShowImage 顯示圖片
Keyword Arguments:
img -- 指定圖片位置 (default: {None})
title -- 顯示窗口名稱 (default: "TestShowImg")
Delay -- 設定圖片展示幾秒後關閉 (default: {5000})
"""
if img is None:
print("沒有圖片輸入!")
return
WinTool.Thread(
lambda:( #用於快捷定義func運行多個命令
cv2.imshow(title,img),
cv2.waitKey(Delay),
cv2.destroyAllWindows()
),Mode=1
)
def Search(img1,imgF,ORB=cv2.SIFT.create(1000),matcher=cv2.BFMatcher(),confi=0.7):
"""Search 使用SIFT算法進行匹配
Arguments:
img1 --你要在那張圖片上找
imgF -- 查找用圖片
Keyword Arguments:
ORB -- 圖像算法器 (default: {cv2.SIFT.create(1000)})
matcher -- 匹配器 (default: {cv2.BFMatcher()})
confi -- 差距值 (default:0.7)
Return: List
[0] List 存儲找到的點
[1] -> [0]KP1 [1] KP2 (包含kp&des)
"""
#查找用
KP1=cv2Tool.GetKP(imgF,SIFT=ORB)
#截圖
KP2=cv2Tool.GetKP(img1,SIFT=ORB)
if KP1[1] is None or KP2[1] is None:
print("沒有找到特徵")
return None
matcher_bf=matcher.knnMatch(KP1[1],KP2[1],k=2)
good=[]
for m,n in matcher_bf:
if m.distance < confi*n.distance:
good.append([m])
Result=[
good,
[KP1,KP2],
]
if len(good)>=1:
FindP=KP2[0][good[0][0].trainIdx].pt
print(f'找到的點:{FindP}')
print(f'找到的數量:{len(good)}')
return Result
def GetKP(img,Mask=None,SIFT=cv2.SIFT_create()):
"""GetKP 取得關鍵點與特徵
Arguments:
img -- 圖片數據Image
Mask -- 指定檢測的關鍵點
Keyword Arguments:
SIFT -- 創建器 (default: {cv2.SIFT_create()})
Returns: List
[0] Keypoints 關鍵點
[1] Descriptors 特徵
"""
kp,des=SIFT.detectAndCompute(img,Mask)
return [kp,des]
class GetItem:
"""主要進行統計加減值"""
def __init__(self):
"""初始化"""
self.Hour=0
self.Play=0
self.xp={
'Count':0,
'5KCount':0,
'1WCount':0,
'3WCount':0,
'5WCount':0,
'Value':0
}
self.feed={'Count':0,'Value':0}
self.CC=0
self.Rest=False
def __str__(self) -> str:
return f'已探險{self.Play}次 共{self.Hour}小時 '
def AddXP(self,value,Type_D='Count'):
"""
value -- 增加xp值
type -- xp字典分類(default:Count)
Dict:(5W/3W/1W/5K)Count/Count
Ex:5WCount/3WCount..
增加xp次數&給定xp
"""
self.xp['Value']+=value
self.xp[Type_D]+=1
def AddFeed(self,value):
"""增加罐頭次數&給定罐頭"""
self.feed['Value']+=value
self.feed['Count']+=1
def Range(self):
"""獲得統計概率 回傳為字典"""
All=self.xp['Count']+self.feed['Count']
if All==0:return None
XPRange=round((self.xp['Count']/All)*100)
FeedRange=round((self.feed['Count']/All)*100)
return {'XP':XPRange,'Feed':FeedRange,'Count':All}
def Result(self):
"""獲得統計數量"""
return f"""
已探險{self.Play}次
獲得 xp:{self.xp['Count']}次 +{self.xp['Value']} 貓罐頭:{self.feed['Count']}次 +{self.feed['Value']}
共{self.Hour}小時 元寶 得到:{self.CC}個
"""
def ResultH(self):
"""獲得統計數量(只取xp&貓罐頭) 和次數"""
return f"獲得 xp:{self.xp['Count']}次 +{self.xp['Value']} 貓罐頭:{self.feed['Count']}次 +{self.feed['Value']} 已探險{self.Play}次 共{self.Hour}小時"
# import win32con
# E=win32gui.CreateWindowEx(0,'Static',"Test",win32con.WS_VISIBLE,0,0,640,360,None,None,None,None)
# hwnd = win32gui.FindWindow(None, "Window Title")
# send_bitmap(hwnd, numpy.zeros((100,100)))
# while True:
# Wi=WinTool.FindW(Window="雷電模擬器")
# if Wi:
# EEE=WinTool.WinDC(Wi[3])
# if EEE:
# win32gui.SendMessage(E, win32con.STM_SETIMAGE, win32con.IMAGE_BITMAP, EEE[0])
# win32gui.SendMessage(E, "Hello",win32con.SEL_TEXT)