📹 第七章 ONVIF协议原理解析
📄 一句话概括

ONVIF 的分析接口有两套东西: Rule 是「要检测什么」,AnalyticsModule 是「用什么算法检测」。 这是「目标」和「手段」的分层——换算法不用改客户端,客户端只看规则。

📝 本节和前面几节的关系

上一节讲云台,这一节进「智能」那一块。 07.02.13 和 07.02.14 是一对:这一节讲「分析什么」,下一节讲「在哪台机器上分析」。

一、规则和模块,目标与手段

概念 回答什么 典型值
Rule 要检测什么事件 MotionRule(有运动就报)
AnalyticsModule 用什么算法实现 MotionDetector
RuleOptions 规则的参数范围 MinCells(最小格数)

第一行和第二行是「目标」和「手段」的关系。 一个规则可以被多个模块实现: 「检测运动」既可以用帧差,也可以用背景建模,客户端不需要知道用的是哪种。 这就是分层的价值:换算法不用改客户端,客户端只看规则。 反过来也成立:同一套算法可以支撑多个规则, 比如同一个 MotionDetector 既用于「有人经过」,也用于「画面被遮挡」。 第三行是「可调的旋钮」:MinCells 越小越灵敏,也越容易误报。 调这个值的经验是: 先设小,跑一天看误报率,再往上加—— 反过来(先大后小)会漏掉真正的目标,而漏掉的样本你根本看不见。

二、两个操作的差别

这两个操作看着像一回事,其实一个问「能做什么」、一个问「装了什么」:

操作 回答 返回什么
GetSupportedRules 能配哪些规则 规则名 + 参数字段
GetAnalyticsModules 实际装了哪些模块 模块名 + 类型

第一行是「能力的上限」,第二行是「当前的配置」。 两者可能不一致:一台设备可能支持三种规则,但只启用了一种。 所以客户端不能只查一个——只查 GetSupportedRules 会以为三种都能用,实际只有一种在跑。 第二行那个 Type 值里带 tt: 前缀,说明它是标准化的类型,不是厂家私有的字符串。 标准化带来的好处是:客户端认出 MotionDetection 就知道怎么配它的参数, 不用为每个厂家写一套。

三、分析结果的两条出口

路径 怎么做 适合什么
事件 规则触发 → 发事件 「有没有」这类判断
元数据流 随视频流附带分析结果 「在哪里、多大」这类信息

第一行只告诉你「有人」,不告诉你「人在哪」。 第二行才是「带框的画面」——它在 RTP 流里插一路元数据,里面有目标框的坐标。 所以「画面上画框」这件事,靠事件做不到,必须订阅元数据流(Profile T 才强制要求支持)。 很多人以为「支持 ONVIF 就能画框」,这是误解——Profile S 连元数据流都不要求,只要求视频流。 这个区分在做方案时很关键: 客户说「要画框」,你就得确认设备支持 Profile T 或至少支持元数据, 光看「支持 ONVIF」或「支持 Profile S」是不够的。

四、本机这一块做到哪一步

诚实地说:这台模拟设备只实现了「读规则」和「读模块」,没有实现「写」。

能力 本机 说明
GetSupportedRules 有 返回一条 MotionRule
GetAnalyticsModules 有 返回一个 MotionDetector
AddAnalyticsModule 没有 要真算法才能加
元数据流 没有 要真视频流才能带

后两行是有意不做的:加模块要有真算法(帧差、背景建模), 元数据流要有真视频流——这两样我都没有,硬做出来只能是假的。 所以这一节的 Demo 只到「读」为止,「写」和「画框」只有概念,没有跑通的东西。 这个边界要写清楚:读者按这一节去实现时,得自己补算法那一段。

五、动手 Demo:视频分析,规则和模块是两回事

Demo 把两个操作都问一遍:支持哪些规则、装了哪些模块。 然后看规则的参数名,那才是真正要调的东西。

# ① 支持哪些规则
_a, b, _n = S.call(port, "analytics", "GetSupportedRules")
r = ET.fromstring(b)
rd = r.find(".//{%s}RuleDescription" % S.NS_TAN)
print(rd.find("{%s}Name" % S.NS_TAN).text)          # MotionRule
for it in rd.iter("{%s}SimpleItemDescription" % S.NS_TAN):
    print(" ", it.get("Name"), it.get("Type"))      # MinCells xs:int

# ② 实际装了哪些模块
_a, b2, _n = S.call(port, "analytics", "GetAnalyticsModules")
m = ET.fromstring(b2).find(".//{%s}AnalyticsModule" % S.NS_TAN)
print(m.find("{%s}Name" % S.NS_TAN).text,
      m.find("{%s}Type" % S.NS_TAN).text)

实跑输出:

--------------------------------------------------------------------
视频分析,规则和模块是两回事
--------------------------------------------------------------------
**ONVIF 的分析接口有两套东西,名字很像,作用不同:**
  **`Rule`(规则)是「要检测什么」,`AnalyticsModule`(模块)是「用什么算法检测」。**

**两者的分工:**

  概念                  回答什么                      典型值
  ----------------------------------------------------------------------------------
  **Rule**              **要检测什么事件**            `MotionRule`(有运动就报)
  **AnalyticsModule**   **用什么算法实现**            `MotionDetector`
  **RuleOptions**       规则的参数范围                `MinCells`(最小格数)

  **第一行和第二行是「目标」和「手段」的关系。**
  **一个规则可以被多个模块实现**:
  **「检测运动」既可以用帧差,也可以用背景建模,  客户端不需要知道用的是哪种。**
  **这就是分层的价值**:  **换算法不用改客户端,客户端只看规则。**

**`GetSupportedRules`:这台设备能配哪些规则**

  规则名                参数                    含义
  ------------------------------------------------------------------------
  MotionRule            MinCells                **最小触发格数**

  **第二列那些参数名是「可调的旋钮」**:  **`MinCells` 越小越灵敏,也越容易误报。**
  **调这个值的经验是**:
  **先设小,跑一天看误报率,再往上加**——  **反过来(先大后小)会漏掉真正的目标。**

**`GetAnalyticsModules`:这台设备实际装了哪些模块**

  模块名                    类型
  ------------------------------------------------------------------
  MotionDetector            tt:MotionDetection

  **那个 `Type` 里的 `tt:` 前缀说明它属于 ONVIF 的类型命名空间**——
  **也就是说「运动检测」这个模块类型是标准化的,  不是厂家私有的。**
  **标准化带来的好处是**:  **客户端认出 `MotionDetection` 就知道怎么配它的参数**,
  **不用为每个厂家写一套。**

**分析结果怎么出来?两条路:**

  路径                  怎么做                            适合
  ----------------------------------------------------------------------------------------
  **事件**              规则触发 → 发事件(07.02.11)     **「有没有」这类判断**
  **元数据流**          随视频流附带分析结果              **「在哪里、多大」这类信息**

  **第一行只告诉你「有人」,不告诉你「人在哪」。**
  **第二行才是「带框的画面」**——  **它在 RTP 流里插一路元数据,里面有目标框的坐标。**
  **所以「画面上画框」这件事,靠事件做不到**,  **必须订阅元数据流(Profile T 才强制要求支持)。**
  **很多人以为「支持 ONVIF 就能画框」,这是误解。**

规则的参数是「SimpleItemDescription」,只有名字和类型,没有值—— 因为它是「声明有哪些可调项」,不是「当前值是多少」。 要拿当前值得另外调 GetRules,这台模拟设备没实现那个操作。 所以这一节只能说清「有哪些旋钮」,说不了「旋钮现在在哪」。 Type 那个值是 xs:int, 这是 XML Schema 的内置类型,不是 ONVIF 自定义的—— 所以 MinCells 这个参数的可选值受 XSD 约束,客户端可以据此生成输入框的校验规则。 模块那一行的 Type 是 tt:MotionDetection, 注意它带命名空间前缀——这说明它是「标准类型」,值本身就是一个 QName。 解析时不能当成普通字符串比较,因为不同厂家可能写 tt:MotionDetection 也可能写完整 URI。

30 秒实验

  1. 把 GetSupportedRules 的响应打印完整,看它有几种参数描述。
  2. 把 Type 那一行的前缀去掉(写成 MotionDetection),看客户端还能不能认。
  3. 查一下 Profile T 对元数据流的要求,想想为什么 S 不要求它。

常见误区

  1. 以为规则就是算法。 规则是「检测什么」,模块是「怎么检测」, 一个规则可以被多个模块实现。
  2. 以为支持 ONVIF 就能在画面上画框。 画框靠元数据流,那是 Profile T 的要求,S 不要求。
  3. 只查 GetSupportedRules。 那只说明「能做」,实际在跑什么要看 GetAnalyticsModules。
自测三问(点开对答案) 1. Rule 和 AnalyticsModule 有什么区别? —— **Rule 是「要检测什么事件」,Module 是「用什么算法实现」。** **这是目标与手段的分层。** 2. 为什么「画框」不能靠事件实现? —— **事件只能说「有没有」,说不了「在哪里」。** **框的坐标在元数据流里**,那是 Profile T 才强制要求的。 3. `GetSupportedRules` 和 `GetAnalyticsModules` 各回答什么? —— **前者答「能配哪些规则」,后者答「实际装了哪些模块」。**两者可能不一致。

下一节讲分析设备:同样的分析能力,放到另一台机器上跑,代价和收益各是什么。

相关笔记