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 秒实验
- 把
GetSupportedRules的响应打印完整,看它有几种参数描述。 - 把
Type那一行的前缀去掉(写成MotionDetection),看客户端还能不能认。 - 查一下 Profile T 对元数据流的要求,想想为什么 S 不要求它。
常见误区
- 以为规则就是算法。 规则是「检测什么」,模块是「怎么检测」, 一个规则可以被多个模块实现。
- 以为支持 ONVIF 就能在画面上画框。 画框靠元数据流,那是 Profile T 的要求,S 不要求。
- 只查
GetSupportedRules。 那只说明「能做」,实际在跑什么要看GetAnalyticsModules。
自测三问(点开对答案)
1. Rule 和 AnalyticsModule 有什么区别? —— **Rule 是「要检测什么事件」,Module 是「用什么算法实现」。** **这是目标与手段的分层。** 2. 为什么「画框」不能靠事件实现? —— **事件只能说「有没有」,说不了「在哪里」。** **框的坐标在元数据流里**,那是 Profile T 才强制要求的。 3. `GetSupportedRules` 和 `GetAnalyticsModules` 各回答什么? —— **前者答「能配哪些规则」,后者答「实际装了哪些模块」。**两者可能不一致。下一节讲分析设备:同样的分析能力,放到另一台机器上跑,代价和收益各是什么。
- ☐ (本节完,下一节 07.02.14 分析设备)