光束与Pygame中触发的光束与掩码的重叠 [AI车辆模型视觉]

我尝试在Pygame中实现光束与预定义轨道掩码的碰撞检测。我的最终目标是赋予AI车辆模型视觉能力,使其能够看到它行驶的轨道:

AI车辆模型视觉

这是我当前的代码,我向掩码发射光束并尝试找到重叠部分:

import mathimport sysimport pygame as pgRED = (255, 0, 0)GREEN = (0, 255, 0)BLUE = (0, 0, 255)pg.init()beam_surface = pg.Surface((500, 500), pg.SRCALPHA)def draw_beam(surface, angle, pos):    # 计算光束的终点    x_dest = 250 + 500 * math.cos(math.radians(angle))    y_dest = 250 + 500 * math.sin(math.radians(angle))    beam_surface.fill((0, 0, 0, 0))    # 根据计算的终点在光束表面上绘制单个光束    pg.draw.line(beam_surface, BLUE, (250, 250), (x_dest, y_dest))    beam_mask = pg.mask.from_surface(beam_surface)    # 查找“全局掩码”与当前光束掩码之间的重叠    hit = mask.overlap(beam_mask, (pos[0] - 250, pos[1] - 250))    if hit is not None:        pg.draw.line(surface, BLUE, mouse_pos, hit)        pg.draw.circle(surface, GREEN, hit, 3)surface = pg.display.set_mode((500, 500))mask_surface = pg.image.load("../assets/mask.png")mask = pg.mask.from_surface(mask_surface)clock = pg.time.Clock()while True:    for e in pg.event.get():        if e.type == pg.QUIT:            pg.quit()            sys.exit()    mouse_pos = pg.mouse.get_pos()    surface.fill((0, 0, 0))    surface.blit(mask_surface, mask_surface.get_rect())    for angle in range(0, 120, 30):        draw_beam(surface, angle, mouse_pos)    pg.display.update()    clock.tick(30)

让我们描述一下代码片段中发生的事情。我逐一向beam_surface绘制光束,从中制作掩码,并查找与由一个矩形和一个圆圈定义的背景掩码(gif中的黑色部分)的重叠。如果存在“命中点”(两个掩码之间的重叠点),我会用一条连接命中点和鼠标位置的线来绘制它。

对于角度<0,90>,它工作正常

小于90度的碰撞角度

但对于角度范围<90,360>,它不工作

所有碰撞角度

Pygame的overlap()文档说明如下:

从左上角开始,它检查第一行的位0到W – 1(从(0, 0)到(W – 1, 0)),然后继续检查下一行(从(0, 1)到(W – 1, 1))。一旦整个列块被检查完,它会继续检查下一个(从W到2 * W – 1)。

这意味着这种方法只在光束大致从左上角击中掩码时才有效。你对如何使其在所有情况下都工作有何建议?这通常是解决此问题的好方法吗?


回答:

你的方法在光束轴的x和y分量指向正方向时工作正常,但如果指向负方向则失败。正如你指出的,这是由pygame.mask.Mask.overlap的工作方式引起的:

从左上角开始,它检查第一行的位0到W – 1(从(0, 0)到(W – 1, 0)),然后继续检查下一行(从(0, 1)到(W – 1, 1))。一旦整个列块被检查完,它会继续检查下一个(从W到2 * W – 1)。

为了使算法工作,你必须确保光束始终指向正方向。因此,如果光束指向负x方向,则垂直翻转掩码和光束;如果光束指向负y方向,则水平翻转光束。

使用pygame.transform.flip()创建4个掩码。不翻转,水平翻转,垂直翻转以及垂直和水平翻转:

mask = pg.mask.from_surface(mask_surface)mask_fx = pg.mask.from_surface(pg.transform.flip(mask_surface, True, False))mask_fy = pg.mask.from_surface(pg.transform.flip(mask_surface, False, True))mask_fx_fy = pg.mask.from_surface(pg.transform.flip(mask_surface, True, True))flipped_masks = [[mask, mask_fy], [mask_fx, mask_fx_fy]]

确定光束的方向:

c = math.cos(math.radians(angle))s = math.sin(math.radians(angle))

根据光束的方向获取翻转的掩码:

flip_x = c < 0flip_y = s < 0filpped_mask = flipped_masks[flip_x][flip_y]

计算翻转的目标点:

x_dest = 250 + 500 * abs(c)y_dest = 250 + 500 * abs(s)

计算翻转的偏移量:

offset_x = 250 - pos[0] if flip_x else pos[0] - 250offset_y = 250 - pos[1] if flip_y else pos[1] - 250

获取翻转的光束与掩码的最接近交点,并取消翻转交点:

hit = filpped_mask.overlap(beam_mask, (offset_x, offset_y))if hit is not None and (hit[0] != pos[0] or hit[1] != pos[1]):    hx = 500 - hit[0] if flip_x else hit[0]    hy = 500 - hit[1] if flip_y else hit[1]    hit_pos = (hx, hy)    pg.draw.line(surface, BLUE, mouse_pos, hit_pos)    pg.draw.circle(surface, GREEN, hit_pos, 3)

查看示例: repl.it/@Rabbid76/PyGame-PyGame-SurfaceLineMaskIntersect-2

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注