1 Star 0 Fork 21

tina/懒人原神AI

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
anglerecognition.py 10.69 KB
一键复制 编辑 原始数据 按行查看 历史
老大哥 提交于 2024-07-22 21:42 . 1.78开源
# -*- coding: utf-8 -*-
import copy
import time
import cv2
import os
import numpy as np
def get_view(small_img,radius=70):
"""
返回当前视野角度 感谢网友飞宇提供的识别方法
Returns:以正北方向为0度计算
"""
# radius = 70 # 定义截屏的宽度和长度
# # 获取窗口句柄
# hwnd = win32gui.FindWindow("UnityWndClass", "原神") # 替换成你实际的窗口句柄
#
#
# small_img = screenshot(hwnd,(98+radius,55+radius), radius=radius)
#
#
channels = cv2.split(small_img)
# 提取Alpha通道
alpha3 = channels[3] # 索引为3,因为Alpha通道是第四个通道
# cv2.imshow('Alpha Channel', alpha3)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# _, alpha = cv2.threshold(small_img, 10, 255, cv2.THRESH_BINARY) #这个是提取蓝色箭头图像
# 假设 gray_channel 是你的灰度图像
# 创建一个掩膜,将150-200之间的值设为255,其他设为0
mask = np.zeros_like(alpha3)
mask[alpha3 >= 151] = 255
mask[alpha3 < 151] = 0
mask[alpha3 > 229] = 0
img = np.zeros((radius * 2, radius * 2), dtype=np.uint8)
center = (radius, radius)
max_overlap = 0 # 最佳的重叠面积
max_angle = -1 # 最佳的角度
increment = 20 # 递增的角度,这里设置为10度
for angle in range(0, 360, increment):
img_copy = img.copy()
# 画一个扇形
cv2.ellipse(img_copy, center, (radius, radius), 225 + angle, 0, 90, 255, -1)
overlap = np.logical_and(img_copy, mask).sum()
if overlap > max_overlap:
max_overlap = overlap
max_angle = angle
start_angle = max_angle - 10
if start_angle < 0:
start_angle = 0
end_angle = start_angle + 10
else:
end_angle = start_angle + 20
for angle in range(start_angle, end_angle, 1):
img_copy = img.copy()
# 画一个扇形
cv2.ellipse(img_copy, center, (radius, radius), 225 + angle, 0, 90, 255, -1)
overlap = np.logical_and(img_copy, mask).sum()
if overlap > max_overlap:
max_overlap = overlap
max_angle = angle
# print(f'最匹配角度:{max_angle},重叠面积:{max_overlap}')
# print(f'用时:{time.time() - old_time}')
#cv2.destroyAllWindows()
return max_angle
def get_view2(small_img,radius=70):
"""
返回当前视野角度 感谢网友飞宇提供的识别方法
Returns:以正北方向为0度计算
"""
# radius = 70 # 定义截屏的宽度和长度
# # 获取窗口句柄
# hwnd = win32gui.FindWindow("UnityWndClass", "原神") # 替换成你实际的窗口句柄
#
#
# small_img = screenshot(hwnd,(98+radius,55+radius), radius=radius)
#
#
channels = cv2.split(small_img)
# 提取Alpha通道
alpha3 = channels[3] # 索引为3,因为Alpha通道是第四个通道
#cv2.imshow('Alpha Channel', alpha3)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
# _, alpha = cv2.threshold(small_img, 10, 255, cv2.THRESH_BINARY) #这个是提取蓝色箭头图像
# 假设 gray_channel 是你的灰度图像
# 创建一个掩膜,将150-200之间的值设为255,其他设为0
mask = np.zeros_like(alpha3)
mask[alpha3 >= 9] = 255
mask[alpha3 < 9] = 0
mask[alpha3 > 190] = 0
img = np.zeros((radius * 2, radius * 2), dtype=np.uint8)
center = (radius, radius)
max_overlap = 0 # 最佳的重叠面积
max_angle = -1 # 最佳的角度
increment = 20 # 递增的角度,这里设置为10度
for angle in range(0, 360, increment):
img_copy = img.copy()
# 画一个扇形
cv2.ellipse(img_copy, center, (radius, radius), 225 + angle, 0, 90, 255, -1)
overlap = np.logical_and(img_copy, mask).sum()
if overlap > max_overlap:
max_overlap = overlap
max_angle = angle
start_angle = max_angle - 10
if start_angle < 0:
start_angle = 0
end_angle = start_angle + 10
else:
end_angle = start_angle + 20
for angle in range(start_angle, end_angle, 1):
img_copy = img.copy()
# 画一个扇形
cv2.ellipse(img_copy, center, (radius, radius), 225 + angle, 0, 90, 255, -1)
overlap = np.logical_and(img_copy, mask).sum()
if overlap > max_overlap:
max_overlap = overlap
max_angle = angle
return max_angle
def pyramid_template_matching(image, template, mask=None):
'''
返回当前导航的角度
:param image:
:param template:
:param mask:
:return:
'''
result = image.copy()
# 创建掩码
if mask is not None:
mask = mask.astype(np.uint8)
# 金字塔层级
#pyramid_levels =1
best_angle = 0 # 最佳匹配角度
max_similarity = 0 # 最大相似度
best_res=0
best_rotated_template=""
h, w = template.shape[:2]
scaled_mask = mask.astype(np.uint8)
scaled_image=image
scaled_template=template
# for level in range(pyramid_levels):
# # 缩放大图和小图
# scaled_image = cv2.resize(image, (0, 0), fx=1 / (2 ** level), fy=1 / (2 ** level))
# scaled_template = cv2.resize(template, (0, 0), fx=1 / (2 ** level), fy=1 / (2 ** level))
# if mask is not None:
# scaled_mask = cv2.resize(mask, (0, 0), fx=1 / (2 ** level), fy=1 / (2 ** level))
# scaled_mask = scaled_mask.astype(np.uint8)
# 旋转模板并进行匹配
for angle in range(0, 360, 10):
rotated_mask = rotate_image(scaled_mask, angle)
rotated_mask[rotated_mask >1] = 255 # 将灰色也变成白色
rotated_template = rotate_image(scaled_template, angle)
#save_rotated_image(rotated_template, "./datas/img", f"{angle}_template")
#save_rotated_image(rotated_mask, "./datas/img",f"{angle}_mask")
res = cv2.matchTemplate(scaled_image, rotated_template, cv2.TM_CCORR_NORMED, mask=rotated_mask)
similarity = cv2.minMaxLoc(res)[1] # 获取匹配相似度
if similarity > max_similarity:
max_similarity = similarity
best_angle = angle
best_res= res
best_rotated_template = rotated_template
best_angle_bk= copy.copy(best_angle)
start_angle=best_angle_bk-10
if start_angle<0:
start_angle=0
end_angle=start_angle+10
else:
end_angle = start_angle + 20
for angle in range(start_angle,end_angle,1):
rotated_mask = rotate_image(scaled_mask, angle)
rotated_mask[rotated_mask > 1] = 255 # 将灰色像素值改为黑色像素值
rotated_template = rotate_image(scaled_template, angle)
res = cv2.matchTemplate(scaled_image, rotated_template, cv2.TM_CCORR_NORMED, mask=rotated_mask)
similarity = cv2.minMaxLoc(res)[1] # 获取匹配相似度
if similarity > max_similarity:
max_similarity = similarity
best_angle = angle
best_res = res
best_rotated_template=rotated_template
#min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(best_res)
#top_left = max_loc
#bottom_right = (top_left[0] + w, top_left[1] + h)
# 绘制角度
#cv2.putText(result, f"{int(best_angle)}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 在原始大图上绘制矩形框标记匹配区域
#cv2.rectangle(result, top_left, bottom_right, (0, 255, 0), 2)
return result,max_similarity,best_angle,best_rotated_template
def save_rotated_image(rotated_image, save_dir, index):
save_path = os.path.join(save_dir, f"{index}.png")
cv2.imwrite(save_path, rotated_image)
def rotate_image(image, angle):
'''
将图片旋转多少度
:param image:
:param angle:
:return:
'''
h, w = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, -angle, 1.0)
rotated_image = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_NEAREST, borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0, 0))
return rotated_image
def template_matching(image, template, threshold=0.8,maxcnt=0,mask=None):
'''
模板匹配 多个
:param image:
:param template:
:param mask:
:return:
'''
method = cv2.TM_CCOEFF_NORMED
# 创建掩码
if mask is not None:
mask = mask.astype(np.uint8)
scaled_mask = mask.astype(np.uint8)
else:
scaled_mask=mask
scaled_image=image
scaled_template=template
h, w = scaled_template.shape[:2]
res = cv2.matchTemplate(scaled_image, scaled_template, method, mask=scaled_mask)
result = []
while True:
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
if max_val < threshold or max_val == np.inf:
break
middle_point = [top_left[0] + w // 2, top_left[1] + h // 2]
result.append(dict(
result=middle_point,
rectangle=(top_left, (top_left[0], top_left[1] + h), (top_left[0] + w, top_left[1]),
(top_left[0] + w, top_left[1] + h)),
confidence=round(max_val, 2)
))
if maxcnt and len(result) >= maxcnt:
break
cv2.floodFill(res, None, max_loc, (-1000,), max_val - threshold + 0.1, 1, flags=cv2.FLOODFILL_FIXED_RANGE)
return result
if __name__ == '__main__':
# 读取图像和模板
# old_time=time.time()
# image = cv2.imdecode(np.fromfile(file=r"大图.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED) # 加载大图
# template = cv2.imdecode(np.fromfile(file=r"小图.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED) # 加载透明图
# mask = template[:, :, 3] # 提取透明度通道作为掩码
# result,max_similarity, best_angle = pyramid_template_matching(image, template, mask=mask)
# print(f"相似度:{max_similarity} 角度:{best_angle} 用时:{int((time.time()-old_time)*1000)}ms")
#
# # 显示结果图像
# cv2.imshow("Result", result)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
old_time=time.time()
image = cv2.imdecode(np.fromfile(file=r"D:\QQ聊天记录\111.bmp", dtype=np.uint8), cv2.IMREAD_COLOR) # 加载大图
template = cv2.imdecode(np.fromfile(file=r"D:\QQ聊天记录\p.png", dtype=np.uint8), cv2.IMREAD_COLOR) # 加载透明图
RET = template_matching(image, template, mask=None)
for result in RET:
print(result)
# 转换为 NumPy 数组
pts = np.array((result['rectangle'][0], result['rectangle'][1], result['rectangle'][3],
result['rectangle'][2]), np.int32)
cv2.polylines(image, [pts], True, (0, 255, 0), 5)
# 显示结果图像
cv2.imshow("324234", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/tina2088/lanren-genshin-impact-ai.git
[email protected]:tina2088/lanren-genshin-impact-ai.git
tina2088
lanren-genshin-impact-ai
懒人原神AI
master

搜索帮助