You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效检测屏幕区域内变为指定颜色的像素 支持三角形区域吗

像素区域检测优化与三角形检测区实现方案

你当前代码的性能瓶颈非常明显:每次循环都抓取全屏像素,再用getpixel()单点读取,哪怕只检测一个点速度都不会快,更不要说检测区域像素。

核心结论

  • 所有系统原生的屏幕捕获接口都只支持输出矩形图像,不存在直接传入三角形顶点完成抓图的API,不可能跳过外接矩形抓图这一步。
  • 三角形检测区域完全可以实现:抓完三角形的最小外接矩形图像后,只对三角形范围内的像素做颜色匹配,跳过区域外的像素,确实能减少待检测像素总量、提升运行速度。
  • 直接把三角形顶点传给抓图函数不可行,必须自己实现区域内像素的筛选逻辑。

具体实现步骤

  • 先缩小抓图范围
    拿到三角形三个顶点的坐标后,先计算三个点x坐标的最小值、最大值,y坐标的最小值、最大值,将这四个值组成(x_min, y_min, x_max, y_max)的bbox参数传给抓图函数,只抓取这一小块矩形区域的屏幕内容,这一步比全屏抓图的性能提升最明显,通常能减少90%以上的无效数据。
  • 替换低效的逐点读取方式
    不要用getpixel()逐点读像素,抓图后直接将图像转为numpy数组,通过向量化操作批量比对颜色,速度比逐点调用API快10~100倍。
  • 实现三角形区域像素筛选
    用叉乘判断法快速判定像素点是否在三角形内部,只对内部点做颜色校验,跳过三角形外的所有点。这个判断全是整数运算,开销极低。

参考实现代码

import PIL.ImageGrab
import mouse
import numpy as np

# 配置参数
TARGET_COLOR = (253, 146, 134)
# 三角形三个顶点坐标,按实际需求修改
TRIANGLE_POINTS = np.array([
    [400, 400],
    [600, 420],
    [510, 600]
])

# 预计算三角形最小外接矩形
x_min, y_min = TRIANGLE_POINTS.min(axis=0)
x_max, y_max = TRIANGLE_POINTS.max(axis=0)
BBOX = (x_min, y_min, x_max, y_max)
# 把三角形顶点坐标转换为相对于抓图区域的局部坐标
LOCAL_TRI = TRIANGLE_POINTS - [x_min, y_min]

def point_in_triangle(p, tri):
    """叉乘判断点p是否在三角形tri内部,纯整数运算速度极快
    若需要包含三角形边线上的点,将判断中的<、>替换为<=、>=即可
    """
    a, b, c = tri
    ab = b - a
    ap = p - a
    bc = c - b
    bp = p - b
    ca = a - c
    cp = p - c
    
    cross1 = ab[0]*ap[1] - ab[1]*ap[0]
    cross2 = bc[0]*bp[1] - bc[1]*bp[0]
    cross3 = ca[0]*cp[1] - ca[1]*cp[0]
    
    # 三个叉乘同号则点在三角形内部
    has_neg = (cross1 < 0) or (cross2 < 0) or (cross3 < 0)
    has_pos = (cross1 > 0) or (cross2 > 0) or (cross3 > 0)
    return not (has_neg and has_pos)

# 预生成三角形区域掩码,三角形位置固定时仅需计算一次,大幅降低循环内开销
h = y_max - y_min
w = x_max - x_min
mask = np.zeros((h, w), dtype=bool)
for y in range(h):
    for x in range(w):
        mask[y, x] = point_in_triangle(np.array([x, y]), LOCAL_TRI)

while True:
    # 仅抓取最小外接矩形区域
    img = PIL.ImageGrab.grab(bbox=BBOX)
    # 转numpy数组做批量颜色比对
    img_arr = np.array(img)
    # 批量匹配所有等于目标色的像素
    color_match = np.all(img_arr == TARGET_COLOR, axis=-1)
    # 仅保留三角形区域内的匹配结果
    target_match = color_match & mask
    # 拿到所有匹配点的局部坐标,转换回全屏坐标
    match_points = np.argwhere(target_match)[:, ::-1] + [x_min, y_min]
    
    if len(match_points) > 0:
        # 检测到目标色像素后执行点击,可根据实际需求修改逻辑
        mouse.click()

额外提速建议

  • 如果对速度要求极高,可以把PIL.ImageGrab换成mss库的抓图接口,抓屏效率比PIL高3~5倍,其余逻辑完全通用。
  • 如果不需要拿到所有匹配点的坐标,只是判断区域内是否存在目标色,可以在匹配到第一个符合要求的点时直接终止判断,不用遍历完所有像素。
  • 三角形检测不是必须的,任何不规则形状的检测区都可以用同样的“先抓最小外接矩形+生成区域mask筛选”的逻辑实现,核心是尽可能减少无效抓图和无效计算。

内容的提问来源于stack exchange,提问作者PaperWarrior105

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:39:42