Compare commits

...

2 commits

Author SHA1 Message Date
e5ff27e8e3 Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2025-01-31 18:46:18 +08:00
6fc2a0431f 水平拼接orb flann 自动识别重叠区域 无接缝修复 森空岛基本信息(练度读取) 2025-01-30 14:12:23 +08:00
2 changed files with 191 additions and 0 deletions

View file

@ -0,0 +1,49 @@
import json
import requests
from mower.utils import config
from mower.utils.path import get_path
from mower.utils.skland import (
get_binding_list,
get_cred_by_token,
get_sign_header,
header,
log,
)
class cultivate:
solver_name = "森空岛数据获取"
def __init__(self):
self.record_path = get_path("@app/tmp/cultivate.json")
self.reward = []
self.sign_token = ""
self.all_recorded = True
def start(self):
item = config.conf.skland_info[0]
if item.isCheck:
a = get_cred_by_token(log(item))
self.save_param(a)
print(a)
for i in get_binding_list(self.sign_token):
body = {"gameId": 1, "uid": i.get("uid")}
ingame = f"https://zonai.skland.com/api/v1/game/player/info?uid={i.get('uid')}"
resp = requests.get(
ingame,
headers=get_sign_header(ingame, "get", body, self.sign_token),
timeout=5,
).json()
print(resp)
with open(self.record_path, "w", encoding="utf-8") as file:
json.dump(resp, file, ensure_ascii=False, indent=4)
def save_param(self, cred_resp):
header["cred"] = cred_resp["cred"]
self.sign_token = cred_resp["token"]
a = cultivate()
a.start()

View file

@ -0,0 +1,142 @@
import cv2
import numpy as np
from glob import glob
class ImageStitcher:
def __init__(self, folder_path=None):
self.images = [] # 存储图像的列表
self.offsets = [] # 存储每对图像的偏移量
if folder_path:
self.load_images(folder_path) # 如果提供了文件夹路径,则加载图像
def load_images(self, folder_path):
"""加载指定文件夹中的所有PNG图像,并裁剪掉顶部300像素。"""
self.images = []
for item in glob(f"{folder_path}/*.png"):
img = cv2.imread(item)[300:]
if img is not None:
self.images.append(img) # 裁剪掉顶部300像素
else:
print(f"Warning: Unable to load image {item}")
def calculate_offsets(self):
"""计算每对相邻图像的偏移量。"""
if len(self.images) < 2:
raise ValueError("At least two images are required to calculate offsets.")
# 初始化 ORB 检测器
orb = cv2.ORB_create()
# 初始化 FLANN 匹配器(针对二进制描述符)
FLANN_INDEX_LSH = 6 # LSH 算法适用于二进制描述符
index_params = dict(
algorithm=FLANN_INDEX_LSH,
table_number=6, # 哈希表数量
key_size=12, # 哈希键大小
multi_probe_level=1, # 多探针级别
)
search_params = dict(checks=20) # 控制搜索精度,值越大越精确但越慢
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 预计算所有图像的关键点和描述符
keypoints_and_descriptors = []
for img in self.images:
keypoints, descriptors = orb.detectAndCompute(img, None)
keypoints_and_descriptors.append((keypoints, descriptors))
self.offsets = [] # 清空偏移量
for i in range(len(self.images) - 1):
keypoints1, descriptors1 = keypoints_and_descriptors[i]
keypoints2, descriptors2 = keypoints_and_descriptors[i + 1]
# 使用 FLANN 进行特征匹配
matches = flann.knnMatch(descriptors1, descriptors2, k=2)
# 过滤匹配点,使用 Lowe's ratio test
good_matches = []
for match_pair in matches:
if len(match_pair) == 2: # 确保每个匹配对有两个点
m, n = match_pair
if m.distance < 0.8 * n.distance: # Lowe's ratio test
good_matches.append(m)
# 至少需要 4 个匹配点来计算单应性矩阵
if len(good_matches) >= 4:
src_pts = np.float32(
[keypoints1[m.queryIdx].pt for m in good_matches]
).reshape(-1, 1, 2)
dst_pts = np.float32(
[keypoints2[m.trainIdx].pt for m in good_matches]
).reshape(-1, 1, 2)
# 计算单应性矩阵
H, _ = cv2.findHomography(dst_pts, src_pts, cv2.RANSAC, 5.0)
# 计算 curr_img 的四个角在 prev_img 坐标系中的位置
h, w = self.images[i + 1].shape[:2]
corners = np.float32(
[[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]
).reshape(-1, 1, 2)
warped_corners = cv2.perspectiveTransform(corners, H)
# 计算偏移量
offset_x = int(warped_corners[0][0][0]) # 左上角的 x 坐标
offset_y = int(warped_corners[0][0][1]) # 左上角的 y 坐标
self.offsets.append((offset_x, offset_y))
else:
raise ValueError(
f"Not enough matches found between image {i} and image {i + 1}."
)
def stitch_images(self):
"""根据偏移量统一拼接所有图像。"""
if not self.images:
raise ValueError("No images provided for stitching.")
if not self.offsets:
self.calculate_offsets() # 如果没有计算偏移量,则先计算
# 计算每张图像在最终拼接图像中的绝对位置
absolute_positions = [(0, 0)] # 第一张图像的绝对位置为 (0, 0)
for i in range(1, len(self.images)):
prev_x, prev_y = absolute_positions[i - 1]
offset_x, offset_y = self.offsets[i - 1]
absolute_positions.append((prev_x + offset_x, prev_y + offset_y))
# 计算最终拼接图像的大小
min_x = min(pos[0] for pos in absolute_positions)
min_y = min(pos[1] for pos in absolute_positions)
max_x = max(
pos[0] + img.shape[1] for pos, img in zip(absolute_positions, self.images)
)
max_y = max(
pos[1] + img.shape[0] for pos, img in zip(absolute_positions, self.images)
)
# 创建空白图像用于存储拼接结果
stitched_image = np.zeros((max_y - min_y, max_x - min_x, 3), dtype=np.uint8)
# 将每张图像放置到正确的位置
for img, (x, y) in zip(self.images, absolute_positions):
x -= min_x
y -= min_y
stitched_image[y : y + img.shape[0], x : x + img.shape[1]] = img
return stitched_image
def main():
folder_path = "./img" # 图像文件夹路径
# 创建 ImageStitcher 实例并加载图像
stitcher = ImageStitcher(folder_path)
# 拼接图像
stitched_image = stitcher.stitch_images()
# 保存结果
cv2.imwrite("result.png", stitched_image)
if __name__ == "__main__":
main()