1 3.1. Utils
霞飛 edited this page 2023-04-20 17:32:10 +08:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

3.1. Utils

这里介绍 module/base/utils.py 下的函数。

random_normal_distribution_int(a, b, n=3)

在区间 [a, b) 内产生符合正态分布的随机数原理是取多个随机数的平均值来模拟正态分布Alas 中绝大部分随机数由这个函数产生。n 值是随机数的数量,值越大分布越集中。

import matplotlib.pyplot as plt
data = [random_normal_distribution_int(0, 100) for _ in range (1000)]
plt.hist(data, bins=50, edgecolor="black", alpha=0.7)
random_normal_distribution_int

random_rectangle_point(area)

在区域内产生符合二维正态分布的随机点,通常在点击操作中使用。下图展示在 BATTLE_PREPARATION 上产生的随机点。(背景图片由 Photoshop 添加)

fig = plt.figure(figsize=(11,4))
plt.axis([-10, 210, -10, 70])
data = np.array([random_rectangle_point((0, 0, 200, 60)) for _ in range (500)])
x, y = data.T
plt.scatter(x,y,s=2, alpha=0.5)
random_rectangle_point

random_rectangle_vector(vector, box, random_range=(0, 0, 0, 0), padding=15)

在区域按二维正态分布放置一个向量,通常在滑动操作中使用。

box 是放置向量的区域, random_range 是给滑动向量加的随机值,padding 是到边缘的最小距离。

random_line_segments(p1, p2, n, random_range=(0, 0, 0, 0))

在两点之间插入中间值,通常在滑动操作中使用。

Area operations

区域操作的函数有: area_offsetarea_padpoint_in_areaarea_in_areaarea_cross_area

locationnode 相互转换:node2locationlocation2node

关于 Alas 中的命名

point,是含 2 个元素的 tuple(x, y)。指屏幕上的一个点。原点是屏幕左上角x 方向沿屏幕水平向右递增y 方向沿屏幕竖直向下递增。

area,是含 4 个元素的 tuple四个元素的值是(upper_left_x, upper_left_y, bottom_right_x, bottom_right_y)。指屏幕上的矩形区域。

location,是含 2 个元素的 tuple(x, y)。指游戏海域中的网格坐标,(0, 0) 是海图最左上角的格子,也就是 A1。

node 是 str比如 E3指游戏海域中的网格坐标。node 相比 location 更容易阅读,所以在逻辑编写和日志中一般使用 node运行时使用 location。

crop(image, area)

裁切图片,image 需要是 numpy 数组,相当于 pillow 库中的 crop。当裁切区域超出图片大小时显示为黑色这点与 pillow 一致。以下两种裁切方式效果相同。裁切大量图片时,操作 numpy 数组会比较快。

image = self.device.image.crop(area)
image = crop(np.array(self.device.image), area)

get_color(image, area)

计算区域的平均颜色。

color_similarity(color1, color2)

计算两个颜色之间的差值。这里使用了 PhotoShop 中魔棒的容差的算法。先计算 RGB 的差值,容差等于最大正差值减最小负差值。使用容差而非 RGB 的简单相减,是为了方便在 PS 中查看图片颜色,同时也更符合人眼对颜色的感知。

Tolerance = Max(Positive(difference_rgb)) + Max(- Negative(difference_rgb))

color_similar(color1, color2, threshold=10)

判断颜色是否相似,判断容差是否小于阈值。

color_similar_1d(image, color, threshold=10)

在一维数组上判断颜色是否相似。

color_similarity_2d(image, color)

计算二维数组上的颜色差值。注意,返回的 numpy 数组中255 代表完全相等,数值越小颜色相差越大。在计算二维图片的颜色差值时,使用了 opencv 计算,速度是使用 numpy 的 3 倍以上。这个函数也是一个常用函数,一般用来进行简单的颜色计数。

>>> image
color_similarity_2d
>>> Image.fromarray(color_similarity_2d(image, (255, 77, 82)))
color_similarity_2d_2
>>> np.sum(color_similarity_2d(image, (255, 77, 82)) > 221) > 100
True

extract_letters(image, letter=(255, 255, 255), threshold=128)

将含文字的图片转换为白底黑字的图片threshold 越小,背景越白。除了 cnocr 的预训练的模型外Alas 中的 ocr 模型都是使用浅色背景和深色字体训练的。所以需要使用 extract_letters 进行预处理。Ocr 类已经封装了这一步,你不需要进行额外的操作,只需要输入字体的颜色即可。

>>> image
extract_letters
>>> Image.fromarray(extract_letters(image, letter=(173, 247, 74), threshold=128))
extract_letters_2

extract_white_letters(image, threshold=128)

extract_letters 基本相同,但针对白色字体,若颜色不是黑白灰,输出的颜色会更浅。

red_overlay_transparency(color1, color2, red=247)

假设 color_2 是由 color_1 叠加一个半透明的红色色块得到的,即 color_2 = color_1 * (1 - alpha) + (red, 0, 0) * alpha然后计算红色色块的不透明度Alas 根据不透明度是否超过阈值来判断空袭、伏击和索敌的动画. 当颜色较深时40 以下)结果不准确。

Air raid 空袭

red_overlay_transparency_1
red_overlay_transparency(
    MAP_AIR_RAID.color, get_color(self.device.image, MAP_AIR_RAID.area)
)
0.0
0.5289717702159051
0.5291491967723716
0.5146182778247053
0.5292370071164753
0.0023695248896050164

Ambush 伏击

red_overlay_transparency_2
red_overlay_transparency(
    MAP_AMBUSH.color, get_color(self.device.image, MAP_AMBUSH.area)
)
0.0
-0.16425414634481073
0.44761270077818777
0.4374642521684831
0.4481979863753585
0.444644697332672
0.06879890918910499
0.05134165622907348
0.05226963663451904
-0.007069039078106552
0.0006615745474228571

Enemy searching 索敌

red_overlay_transparency_3
red_overlay_transparency(
    MAP_ENEMY_SEARCHING.color, get_color(self.device.image, MAP_ENEMY_SEARCHING.area
)
0.0
-0.17394681611846782
-0.1864791203625967
0.7091334931036758
0.7207363797991225
0.7653337334792214
0.40077538826295694
0.045037725366474775
-0.12609578098579324

color_bar_percentage(image, area, prev_color, reverse=False, starter=0, threshold=30)

计算进度条的百分比,可以计算纯色的、渐变色的、甚至是不连续的有遮挡的进度条。用于检测地图通关百分比,演习时敌我的血条,强化角色时的装填属性等。有一定的误差,满进度时,可能返回 0.99 或 0.98。执行耗时较长, 约 10ms取决于长度和复杂度。

color_bar_percentage
>>> self._calculate_hp(image, area=DEFENDER_HP_AREA.area, reverse=False)
0.7603833865814696