欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

找色不是比 RGB:用 HSV + inRange 让游戏颜色识别抗干扰

找色不是比 RGB:用 HSV + inRange 让游戏颜色识别抗干扰

图色脚本里"找色"和"找图"一样基础:判断屏幕上某个点、某块区域是不是某种颜色,从而知道游戏处在什么状态(红血/蓝血、可交互高亮、技能冷却灰)。传统做法是读一个像素的 RGB,跟目标值做相等或容差比较

问题来了:同一块红按钮,亮度一变、或者被半透明遮罩盖一下,RGB 就全变了,脚本立刻误判。这篇讲如何用 OpenCV 的 cv2.cvtColor 转 HSV + cv2.inRange,把"找色"做成只认色相、容忍亮度变化的稳方案。


一、为什么直接比 RGB 会翻车

RGB 把颜色拆成"红多少、绿多少、蓝多少"三个亮度通道。亮度(光照、gamma、叠加层)会同时改变三个通道,所以同一个"红色",亮一点暗一点,RGB 数值能差出一大截。

举个场景:游戏里"可点击"的按钮是高亮黄。白天和夜晚场景的光照不同,或者按钮上飘过一条半透明公告,(255,220,0) 可能变成 (230,180,30),纯 RGB 容差稍微设小就漏检,设大又容易把背景金黄色也误判成按钮。

解法:把"色相(Hue)"和"亮度(Lightness)"分开。人眼判断"这是不是红色",靠的是色相,而不是它亮不亮——HSV 正好把这两者拆开。


二、HSV 是什么,为什么适合找色

通道含义OpenCV 取值
H (Hue)色相,颜色种类(红/绿/蓝)0~179
S (Saturation)饱和度,颜色纯不纯0~255
V (Value)明度,亮不亮0~255

关键点:色相 H 几乎不受亮度影响。所以找色时,我们只对 H 给很窄的容差,对 S/V 给较宽的容差,就能在"亮度多变"的画面里稳定认出同一种颜色。

新手必踩坑:OpenCV 读进来的是 BGR 不是 RGB!转 HSV 必须用 cv2.COLOR_BGR2HSV,写成 RGB2HSV 颜色会错乱。另外 OpenCV 的 H 范围是 0~179(不是 0~360),网上很多教程按 0~360 写,照搬会找错色。

三、核心函数:cv2.inRange

函数签名:

mask = cv2.inRange(src, lowerb, upperb)
参数含义
srcHSV 图像(注意:必须先用 cvtColor 转好)
lowerb下限数组,如 np.array([0,100,100])
upperb上限数组,如 np.array([10,255,255])

返回值:一张单通道二值掩膜——落在范围内的像素是 255(白),其余是 0(黑)。再用 cv2.countNonZero 数一下白点数量,就知道"这种颜色出现了多少"。


四、场景实战:在画面里找"红色按钮"

import cv2
import numpy as np

# 1) 读图(OpenCV 是 BGR!)
img = cv2.imread('game.png')

# 2) 转 HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 3) 定义"红色"范围:H 给窄区间(0~10),S/V 给宽容差
lower = np.array([0, 100, 100])
upper = np.array([10, 255, 255])
mask = cv2.inRange(hsv, lower, upper)

# 4) 统计命中像素数
count = cv2.countNonZero(mask)
print('红色像素数:', count)

if count > 200:          # 阈值按按钮大小自定
    print('画面里出现了红色按钮')
为什么比 RGB 稳:只要目标还是"红色"(H 在 0~10),无论它偏亮偏暗(V 在 100~255)、饱和度高或略低(S 在 100~255),都会被 inRange 命中。亮度变化不再导致漏检,这正是图色脚本最需要的鲁棒性。

五、两个进阶技巧

  1. 红色跨 0 度处理:红色在 HSV 里分布在 H≈0 两侧(如 H=170~179 与 0~10)。用一段 inRange 会漏掉另一半,正确做法是做两段掩膜再按位或mask = mask1 | mask2
  2. 收窄搜索区 + 形态学去噪:先用 ROI 裁出可能区域再 inRange,命中后用 cv2.morphologyEx 开运算去掉零星噪点(见专栏 L10),避免把几个孤立杂色误判成"按钮"。
# 红色跨 0 度的正确写法
lower1 = np.array([0, 100, 100]);   upper1 = np.array([10, 255, 255])
lower2 = np.array([170, 100, 100]); upper2 = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower1, upper1) | cv2.inRange(hsv, lower2, upper2)

本讲要点

  • 找色别直接比 RGB,亮度一变就误判
  • cv2.cvtColor(..., COLOR_BGR2HSV) 转 HSV,只对 H 给窄容差、S/V 给宽容差
  • cv2.inRange 返回二值掩膜,配合 cv2.countNonZero 统计命中数量。
  • 记住 OpenCV 是 BGR、H 范围 0~179、红色要分两段

下一篇我们用一张"升级路线图"把模板匹配、找色、预处理串起来,对比大漠插件与 OpenCV 在图色脚本里各自的适用边界。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功