欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python 梦幻西游_tensorflow实践:梦幻西游人物弹窗识别(二)

发布时间:2024/3/12 python 57 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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实践:梦幻西游人物弹窗识别(二)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。