# NUEDC21-D
<font color="#dd0dd">2021年电赛D题,并非参加比赛的作品,为准备参加2023年电赛时所做</font>
## 题目要求
(网上搜搜)
## 做题思路
### 整体设计
两个摄像头节点,一个处理终端,一个千兆交换机。
摄像头节点拍摄图像通过交换机传给处理终端(节点不对图像做额外处理),处理终端接收并处理图像数据,包括标记激光笔的边框、分别和同时显示节点传来的图像、计算单摆周期、计算单摆线长和角度等等。
图像数据使用局域网内 UDP 协议传输。
### 节点分析
用 USB 摄像头拍摄并发送图像数据。
图像需要编码为二进制字符串后传输,无需特殊处理,但是每个发送的数据包(包含一帧图像)需要有特定的格式,这里采用的格式为 数据包 = 实际数据长度 + 实际数据,为了计算需要,实际数据由 拍摄时间 + 图像数据 组成,需要特别注意的是,“实际数据长度”和“拍摄时间”应该为一定长度的二进制字符串以防止数据包分析时出错,此长度在节点和终端处一致。
节点发送数据时,通过发送到同终端 IP 但不同端口号的方式来分别接收两个节点的数据(方便多线程处理)。
### 终端分析
接收节点的图像数据并做处理。
终端的设计是整个系统最复杂的工作。
终端接收到数据包后,通过特定的格式将图像拍摄时间和图像分离开,使用 opencv 把激光笔的轮廓描绘出来并获取轮廓的中心点坐标,在这之后就是计算工作。
### 计算方法
计算的过程和思路比较复杂,所以分开说明。
#### 周期及长度计算
周期计算的基本思路为:通过图像中激光笔坐标的变化判断出激光笔运动的最高点和最低点(以 X 坐标为准)以及出现的时刻,通过两时刻的时间差可得到单摆运动周期的一半。
长度通过单摆周期公式 $T \approx 2\pi\sqrt{l / g}$ 推导计算。
如何确定最高点及最低点:
取 n 为一个正的奇数常数,记录 n 次拍摄时激光笔的 X 坐标,当已经记录 n 个坐标后,下一个数据成为最新的记录,而舍去最久远的记录(类似于先进先出的队列结构),因为 n 为奇数,所以取第 $m=\lceil n/2 \rceil$ 个数据为基准,若 m 数据点之前和之后的数据中,大于和小于它的数据个数相差一定个数,则断定 m 数据点为最高点或最低点,再具体地说,若 m 数据点之前和之后大于它的数据都比之前和之后小于它的数据多 a 个,就断定 m 数据点为最低点,反之,若 m 数据点之前和之后大于它的数据都比之前和之后小于它的数据少 a 个,就断定 m 数据点为最高点。在判断的过程中,n 和 a 的取值会在一定程度上影响判断的准确性,n 需要根据预估的周期来取定,而 a 一般来说可以取为 $\lfloor n \rfloor + 1$。
#### 角度计算
角度计算分为两步:第一,通过最高点和最低点的位置得到两点间的长度(以像素计),两个节点则得到 $\overline{OA}$ 和 $\overline{OB}$ 的长度 $(l_1, l_2)$,;第二,通过反正切计算角度,即 $\arctan({l_2/l_1})$。
#### 数据滤波
这里使用的滤波算法有:卡尔曼滤波、滑动均值滤波以及频率分布滤波。
卡尔曼滤波使用一维算法,对计算出的周期滤波。
滑动均值滤波取 5 个数据为一组,对计算出的周期和最高点到最低点的距离进行处理。
频率滤波是这里作用最明显的滤波算法,通过分析数据点的分布情况,取出设计数据最可能的分布区间,对区间左侧和区间右侧的值加权平均后得到估计值。
## 其他说明
- 整体的设计没有完全按照题目要求来,而是省去了一些细节部分,如一键启动和终端的声光提醒。
- 最后的结果符合题目的误差要求。