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

带噪声及随机颜色的游戏箭头轮廓检测技术求助

随机颜色箭头的检测与排序方案

针对游戏中颜色随机的箭头检测(需按从左到右输出方向序列),放弃依赖颜色的方法,改用形状特征作为核心识别依据,以下是具体实现步骤:

核心思路

颜色随机意味着颜色过滤完全失效,转而利用箭头的边缘轮廓、形状特征完成检测与方向判断,最后通过轮廓的横向坐标排序得到顺序。


步骤1:预处理图像(突出轮廓)

通过灰度化、边缘检测、形态学操作消除噪声并强化箭头轮廓:

  • 灰度化:cv.cvtColor(img, cv.COLOR_BGR2GRAY) 消除颜色信息,聚焦形状
  • 边缘检测:cv.Canny(gray, 50, 150) 提取箭头的边缘(阈值可根据截图亮度调整)
  • 闭运算补全缺口:cv.morphologyEx(edges, cv.MORPH_CLOSE, cv.getStructuringElement(cv.MORPH_RECT, (3,3))) 填补边缘的小断裂,让轮廓更完整

步骤2:提取并筛选有效箭头轮廓

从预处理后的图像中提取轮廓,过滤掉噪声或无关物体:

  • 提取外部轮廓:contours, _ = cv.findContours(edges.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
  • 面积过滤:跳过面积过小的轮廓(比如cv.contourArea(cnt) < 100),只保留箭头大小的目标

步骤3:识别箭头方向

有两种可靠的方向判断方法,可根据箭头形状选择:

方法A:基于最小外接矩形的几何判断

适合形状规则、长宽比差异明显的箭头:

  1. 计算轮廓的最小外接矩形:rect = cv.minAreaRect(cnt),得到(中心坐标, (宽, 高), 旋转角度)
  2. 根据宽高比区分横向/纵向箭头:
    • 横向箭头(左/右):宽 > 高×1.2,再通过轮廓的左右端点形态判断尖端方向
    • 纵向箭头(上/下):高 > 宽×1.2,再通过轮廓的上下端点形态判断尖端方向

方法B:基于Hu矩的形状匹配(更准确)

适合形状固定但角度可能有微小变化的箭头:

  1. 提前制作标准箭头模板:从游戏中截取左、上、下、右四种箭头的清晰图像,提取它们的轮廓并计算Hu矩(cv.HuMoments(cv.moments(template_cnt)).flatten())
  2. 对检测到的每个轮廓计算Hu矩,与四个模板的Hu矩做距离比对(用cv.norm()计算欧氏距离),距离最小的模板对应箭头方向

步骤4:按从左到右排序

计算每个箭头轮廓的横向中心坐标(比如外接矩形的中心x值rect[0][0]),将箭头按x坐标从小到大排序,提取方向序列即可得到目标结果。


简化代码示例(Python)

import cv2 as cv
import numpy as np

# 加载游戏截图(替换为你的图像路径)
img = cv.imread("game_arrows.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 预处理
edges = cv.Canny(gray, 60, 180)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
edges_closed = cv.morphologyEx(edges, cv.MORPH_CLOSE, kernel)

# 提取轮廓
contours, _ = cv.findContours(edges_closed.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

arrow_info = []
for cnt in contours:
    area = cv.contourArea(cnt)
    if area < 120:  # 过滤噪声,阈值根据实际截图调整
        continue
    
    # 计算外接矩形
    rect = cv.minAreaRect(cnt)
    x_center = rect[0][0]
    width, height = rect[1]
    direction = ""
    
    # 判断方向(简化逻辑,可根据实际箭头形状优化)
    if width > height * 1.3:
        # 横向箭头:判断左/右(示例逻辑,需根据你的箭头调整)
        left_y = cnt[cnt[:, :, 0].argmin()][0][1]
        right_y = cnt[cnt[:, :, 0].argmax()][0][1]
        direction = "right" if abs(right_y - np.mean(cnt[:, :, 1])) < 5 else "left"
    else:
        # 纵向箭头:判断上/下
        top_x = cnt[cnt[:, :, 1].argmin()][0][0]
        bottom_x = cnt[cnt[:, :, 1].argmax()][0][0]
        direction = "up" if abs(top_x - np.mean(cnt[:, :, 0])) < 5 else "down"
    
    arrow_info.append((x_center, direction))

# 按x坐标排序,提取方向序列
arrow_info.sort(key=lambda x: x[0])
result = [item[1] for item in arrow_info]
print("检测到的箭头顺序:", result)

注意事项

  • 阈值调整:Canny的边缘阈值、面积过滤阈值需要根据游戏截图的实际分辨率、亮度手动微调
  • 形状匹配优化:如果箭头有固定的顶点数(比如5个),可以用cv.approxPolyDP提取近似多边形,通过顶点数进一步筛选箭头
  • 抗干扰:如果场景中有其他类似形状的物体,可增加轮廓的凸包检测,箭头的凸包特征与其他物体有明显差异

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 00:18:24