美文网首页
python 识别minecraft截图坐标

python 识别minecraft截图坐标

作者: Lupino | 来源:发表于2020-11-09 22:03 被阅读0次

作为一个我的世界资深玩家,从一个地方到另外的一个地方也得徒步旅行,哪怕是开船,骑马也是很慢的,通过下界还可以,远点也要跑好久。

我是服务器的 op 角色可以直接使用 tp 命令到达某个地方,依然有个很头疼的地方,不知道要去的地方乍样,坐标如何。

于是我就想着做一个相册,然后通过 OCR 来识别坐标,然后点击一下图片就能到那一个地方。

我们来开一下几个 tp 命令吧

execute in world tp user x y z  

我们需要把截图的世界类型和坐标识别出来,我试了一些现成的 OCR 工具不能很好的识别出来,于是自己用 python 写了一个。

2020-10-09_21.40.43.png

分析截图,我们发现坐标和世界类型位置比较固定,我们使用 graphicsmagick 将坐标和世界类型截下来。

gm convert -crop 600x30+0+260 ${image} world.jpg     # 切出世界类型
gm convert -crop 800x30+90+330 ${image} position.jpg # 切出坐标图

初始化,并对图片进行预处理

import numpy as np
from PIL import Image

读取一张图片转成 numpy 数组

data = np.array(Image.open('world.jpg').convert("L"))

图片进行二值化

def normal_image(data, revert = False):
    # 获取矩阵(图像)的长宽
    data = np.copy(data)
    rows, cols = data.shape
    for i in range(rows):
        for j in range(cols):
            # 与阈值比较
            if data[i, j] <= 220:
                # 设为灰度最小值
                if revert:
                    data[i, j] = 0
                else:
                    data[i, j] = 1
            else:
                # 设为灰度最大值
                if revert:
                    data[i, j] = 1
                else:
                    data[i, j] = 0

    return data

data = normal_image(data)

切除图片的空白边框

def strip_row(data):
    # 每行最小值
    row_min = np.min(data, axis=1)
    # 找到第一个有图像的行
    row_start = np.argmin(row_min)
    # 找到最后一个有图像的行
    row_end = np.argmin(np.flip(row_min))
    # 只取有图像的行
    if row_end > 0:
        data = data[row_start:-row_end, :]
    else:
        data = data[row_start:, :]

    return data

def strip_col(data):
    # 每行最小值
    col_min = np.min(data, axis=0)
    # 找到第一个有图像的行
    col_start = np.argmin(col_min)
    # 找到最后一个有图像的行
    col_end = np.argmin(np.flip(col_min))
    # 只取有图像的行
    if col_end > 0:
        data = data[:, col_start:-col_end]
    else:
        data = data[:, col_start:]

    return data

data = strip_row(data)
data = strip_col(data)

识别世界类型

我的世界类型在原版的只有三种类型,minecraft:overworld, minecraft:the_netherminecraft:the_end
我们只要比对三张图片是否一致就可以。

分别找到三个世界类型的图片,分别预处理后保存成图片,作为世界类型库。

def to_image_array(data):
    data = np.copy(data)
    # 获取矩阵(图像)的长宽
    rows, cols = data.shape
    for i in range(rows):
        for j in range(cols):
            # 与阈值比较
            if data[i, j] == 0:
                # 设为灰度最小值
                data[i, j] = 0
            else:
                # 设为灰度最大值
                data[i, j] = 255

    return data

data = to_image_array(data)
img = Image.fromarray(data)
img.save('datasets/overworld.jpg') # 保存成黑白图
# img.save('datasets/the_nether.jpg') 
# img.save('datasets/the_end.jpg') 

读取世界类型库

datasets = []
dataset = np.array(Image.open('dataset/overworld.jpg').convert("L"))
dataset = normal_image(dataset, True)
datasets.append(dataset)

对比两个世界类型是不是一样(识别)

def recog_one(data, datasets):
    x = data.flatten()
    got = -1
    score = -1
    for num, dataset in datasets:
        try:
            new_score = np.sum(x ^ dataset)
            if score == -1:
                score = new_score
                got = num

            if score > new_score:
                score = new_score
                got = num
        except Exception:
            pass

    return got, score

recog_one(data, datasets)

到这里我们已经把世界类型识别给搞定了。

识别坐标

识别坐标与识别世界类型相识,我们需要把数字切出来,然后手动做字库,最后比对数字,拼成坐标字符就可以搞定。

找出数字的坐标

def find_num_poses(data):
    poses = [0]
    for pos in range(4, data.shape[1]):
        img_matrix_spited = data[:, :pos]
        col_min = np.min(img_matrix_spited, axis=0)
        col_end = np.argmin(np.flip(col_min))
        if col_end > 0:
            rel_pos = pos - col_end
            if rel_pos not in poses:
                poses.append(rel_pos)

    return poses

poses = find_num_poses(data)

将数字切出来并保存成文件

poses_start = poses[0:-1]
poses_end = poses[1:]

got_nums = []
for col_start, col_end in zip(poses_start, poses_end):
    img_matrix_spited = img_matrix[:, col_start:col_end]
    img_matrix_spited = strip_col(img_matrix_spited)
    save_image(img_matrix_spited, 'position-{}-{}'.format(col_start, col_end))

手工制作字体库

同样的方法识别每一个数字,最后形成一个坐标。

总结

我们到此位置已经完成了我的世界截图的坐标识别和世界类型识别。

相关代码详见

相关文章

网友评论

      本文标题:python 识别minecraft截图坐标

      本文链接:https://www.haomeiwen.com/subject/ptsrbktx.html