python 梦幻西游_tensorflow实践:梦幻西游人物弹窗识别(二)
由上一篇的思路我們可以定義以下的具體實現步驟
本篇將圍繞窗口捕獲、屏幕截圖、截圖切分講述screen.py代碼
環境描述C:\Users\SF>ver
Microsoft Windows [版本 10.0.18363.720]
C:\Users\SF>python --version
Python 3.7.6
啟動方式 多標簽版
分辨率 800x600
界面風格 暖風
窗口截圖
主要是使用了PyQt5進行截圖
hwnd_title = dict()
def get_all_hwnd(hwnd,mouse):
if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):
hwnd_title.update({hwnd:win32gui.GetWindowText(hwnd)})
def shot():
win32gui.EnumWindows(get_all_hwnd, 0)
mhxy_title = ''
for h,t in hwnd_title.items():
if t.startswith('夢幻西游 ONLINE'):
mhxy_title = t
print(mhxy_title)
hwnd = win32gui.FindWindow(None, mhxy_title)
app = QApplication(sys.argv)
desktop_id = app.desktop().winId()
screen= QApplication.primaryScreen()
img_desk = screen.grabWindow(desktop_id).toImage()
img_sc = screen.grabWindow(hwnd).toImage()
img_desk.save(img_desktop_path)
img_sc.save(img_sc_path)
print(f'img_desktop save to -> {os.path.abspath(img_desktop_path)}')
print(f'img_mhxy save to -> {os.path.abspath(img_sc_path)}')
if mhxy_title == '':
print('mhxy not start')
return False
return True
于是我們在路徑
images
|- desktop.jpg
|- mhxy.jpg
得到一張全屏截圖以及一張夢幻的窗口截圖
截圖切分
得到屏幕截圖后,我們將對截圖進行切分
戰斗狀態判斷
因為進入戰斗才會彈窗,所以首先對戰斗狀態進行判斷
戰斗狀態的判斷是依據了夢幻窗口最右側戰斗標識,不同的界面風格標識的顏色是不同的,我用的是暖風界面風格
戰斗標識路徑
images
|- flag
|- fighting_flag.jpg
截取相同區域的圖片使用opencv與戰斗標識進行相似性判斷,如果相似度大于%95則判定為戰斗狀態
# 戰斗截圖
def fight_crop():
util.log_title('戰斗標識截圖')
return crop(c.img_sc_path,c.fighting_img_path,c.fight_shape)
# 是否在戰斗
def is_fight():
util.log_title('狀態判斷')
rate = compare_image(c.fighting_flag_img_path,c.fighting_img_path)
if rate > 0.95:
print('戰斗 狀態')
return True
else:
print('非戰斗 狀態')
return False
# 相似性判斷
def compare_image(path_image1, path_image2):
imageA = cv.imread(path_image1)
imageB = cv.imread(path_image2)
grayA = cv.cvtColor(imageA, cv.COLOR_BGR2GRAY)
grayB = cv.cvtColor(imageB, cv.COLOR_BGR2GRAY)
(score, diff) = structural_similarity(grayA, grayB, full=True)
print("SSIM: {}".format(score))
return score
# 裁剪
def crop(source_path,target_path,shape):
with Image.open(source_path) as img:
fighting_flag_img = img.crop(shape)
fighting_flag_img.save(target_path)
return True
截取戰斗標識相同區域的路徑為
images
|- sub
|- fighting.jpg
判斷是否彈窗
接下來我們開始判斷是否彈窗,目前見到的彈窗形式有兩種,可以使用如下兩種彈窗標識去匹配夢幻窗口
所以彈窗判斷的思路如下
使用 OpenCV Template Matching 對夢幻窗口進行匹配,并返回最匹配(得分最高)的區域
def popup_sub_crop():
util.log_title('彈窗判斷')
shape_dict = {}
for i in range(len(c.popup_flag_img_paths)):
shape,score = template_match(c.popup_flag_img_paths[i],c.img_sc_path)
shape_dict[shape] = (score,i)
print(shape_dict)
max_shape = max(shape_dict, key=shape_dict.get)
score,i = shape_dict[max_shape]
print(f'最大區域 {max_shape} 最終得分為 {score}' )
if score >=3 :
sub_shape = (
max_shape[0]+c.popup_move_shapes[i][0],
max_shape[1]+c.popup_move_shapes[i][1],
max_shape[2]+c.popup_move_shapes[i][2],
max_shape[3]+c.popup_move_shapes[i][3]
)
print(f'彈框區域 {sub_shape}')
return crop(c.img_sc_path,c.popup_sub_img_path,sub_shape)
print(f'沒有彈框')
return False
def template_match(template_path,src_path):
img = cv.imread(src_path,0)
img2 = img.copy()
template = cv.imread(template_path,0)
w, h = template.shape[::-1]
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED','cv.TM_CCORR',
'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
shape_dict = {}
for meth in methods:
img = img2.copy()
method = eval(meth)
# Apply template Matching
res = cv.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# cv.rectangle(img,top_left, bottom_right, 255, 2)
# plt.subplot(121),plt.imshow(res,cmap = 'gray')
# plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
# plt.subplot(122),plt.imshow(img,cmap = 'gray')
# plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
# plt.suptitle(meth)
# plt.show()
shape = (top_left[0],top_left[1],bottom_right[0],bottom_right[1])
# print(shape)
if shape_dict.get(shape) == None:
shape_dict[shape] = 1;
else:
shape_dict[shape] = shape_dict[shape]+1
max_shape = max(shape_dict, key=shape_dict.get)
return max_shape,shape_dict[max_shape]
切出包含4個人物的大圖
這個包含四個人物的圖片寬高為360 x 120
def popup_sub_crop():
util.log_title('彈窗判斷')
shape_dict = {}
for i in range(len(c.popup_flag_img_paths)):
shape,score = template_match(c.popup_flag_img_paths[i],c.img_sc_path)
shape_dict[shape] = (score,i)
print(shape_dict)
max_shape = max(shape_dict, key=shape_dict.get)
score,i = shape_dict[max_shape]
print(f'最大區域 {max_shape} 最終得分為 {score}' )
if score >=3 :
sub_shape = (
max_shape[0]+c.popup_move_shapes[i][0],
max_shape[1]+c.popup_move_shapes[i][1],
max_shape[2]+c.popup_move_shapes[i][2],
max_shape[3]+c.popup_move_shapes[i][3]
)
print(f'彈框區域 {sub_shape}')
return crop(c.img_sc_path,c.popup_sub_img_path,sub_shape)
print(f'沒有彈框')
return False
路徑如下
images
|- sub
|- pop_sub.jpg
再切出單個人物
單個人物寬高為90 x 120
def crop_4():
util.log_title('彈窗人物切分')
w = 90
h = 120
for i in range(len(c.crop_4_img_names)):
shape = (w*i, 0, w*(i+1), h)
crop(c.popup_sub_img_path,c.crop_4_img_paths[i],shape)
路徑如下
images
|- sub
|- 1.jpg
|- 2.jpg
|- 3.jpg
|- 4.jpg
組合
于是我們將以上步驟組合起來
def task():
print()
if shot(): ## 截圖
if image_check(c.img_sc_path,c.screen_size): ## 檢查截圖大小
fight_crop() ## 戰斗標識截圖
if is_fight(): ## 判斷是否在戰斗
if popup_sub_crop(): ## 彈窗識別 與 人物區域切出
if image_check(c.popup_sub_img_path,c.sub_size): ## 彈窗人物截圖檢查
crop_4() ## 彈窗人物切分
print()
return True
return False
if __name__ == '__main__':
task()
-------- 截圖 ----------
夢幻西游 ONLINE - (xxxxxxx - xxxxx[xxxxx])
img_desktop save to -> d:\gitRepo\mhxy\images\desktop.jpg
img_mhxy save to -> d:\gitRepo\mhxy\images\mhxy.jpg
-------- 截圖檢查 ----------
size=(812, 663) ok
-------- 戰斗標識截圖 ----------
-------- 狀態判斷 ----------
SSIM: 0.9955642623257255
戰斗 狀態
-------- 彈窗判斷 ----------
{(277, 221, 457, 234): (1, 0), (334, 223, 430, 237): (4, 1)}
最大區域 (334, 223, 430, 237) 最終得分為 4
彈框區域 (252, 252, 612, 372)
-------- 截圖檢查 ----------
size=(360, 120) ok
-------- 彈窗人物切分 ----------
回顧
到這里,窗口捕獲、屏幕截圖、截圖切分部分就已經完畢,我們再來看一下進度
是不是勝利指日可待!
聲明
本人無任何商業目的,僅用于學習和娛樂,源代碼采用了AGPL3.0開源協議
本文為博主原創文章,任何人未經過博主同意不得轉載
總結
以上是生活随笔為你收集整理的python 梦幻西游_tensorflow实践:梦幻西游人物弹窗识别(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 测试用例
- 下一篇: python莫比乌斯环_【干货】用pyt