2021全国电子设计大赛 D题 基于互联网的摄像测量系统 源码解析

→ 2021全国电子设计大赛

→ D题 基于互联网的摄像测量系统

→ 源码分析

1. 场地

在这里插入图片描述

  • 测试视频

2021电赛D题基于互联网的摄像测量系统

作为业余选手,搞个省一也还行。终于不是铜牌了。

还没写完

2021 全国电子设计大赛

在这里插入图片描述

D题:基于互联网的摄像测量系统

1. 题目:

设计并制作一个基于互联网的摄像测量系统。系统构成如图 1 所示。图中边
长为 1 米的正方形区域三个顶点分别为 A、B 和 O。系统有两个独立的摄像节点,分别放置在 A 和 B。两个摄像节点拍摄尽量沿 AO、BO 方向正交,并通过一个百兆/千兆以太网交换机与连接在该交换机的一个终端节点实现网络互联。交换机必须为互联网通用交换机,使用的网口可以任意指定。在 O 点上方悬挂一个用柔性透明细线吊起的激光笔,透明细线长度为 l。激光笔常亮向下指示,静止下垂时的指示光点与 O 点重合。拉动激光笔偏离静止点的距离小于 10cm,松开后时激光笔自由摆动,应保证激光笔指示光点的轨迹经 O 点往复直线运动,轨迹与 OA 边的夹角为 θ。利用该系统实现对长度 l 和角度 θ 的测量。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 吐槽

一个激光笔摆动,识别然后算周期,在计算摆长吗。。。

原本不想做这个题的,第一想的是F题。车对我们来说确实很熟悉【之前用openmv做过越野车、激光雷达+ SLAM 做过智能车】。。。但是但是经过指导老师的讨论,我们只有四个参赛队伍,因为已经有两个队伍选了F题,我们只好勉强选择了D题。

3. 器材

器材 作用
一个架子 悬挂激光笔
一个激光笔长度10cm 单摆物体,光用来瞄准
一个JetSonNano 作为终端节点主机
两个树莓派4B 作为摄像头节点主机
一个卷尺 量摆线的长度
三个显示器 显示图像
三个HDMI 连接主机与显示器
一个交换机 系统组成局域网
三根网线 连接主机与交换机
一个量角器 测量摆线轨迹夹角
一个笔 记录
一个1X1的白板 固定设备位置,需要量角
两个摄像头 记录实时的视频
两个摄像头支架 你猜
一个矩阵键 实现一键启动功能
一个蜂鸣器 声音提示
一个LED 灯光提示
若干长的鱼线 挂激光笔
两个敲代码的电脑 写代码,一个软件、一个硬件
三天的粮食 其实是一个礼拜的,吃不完兜着走
一个沙发、一个床 硬件睡床、软件睡沙发

4. 过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


代码:

1. 硬件:【我只提思路、不管实现】

硬件源码

2. 软件:【Ctrl+C、V】

python OpenCV 实现全程

需要的技术点:

  1. Python3 读取本地、网络摄像头流

  2. QtPy 的使用

    import sys
    
    from PyQt5.QtWidgets import *
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("2021")
            MainWindow.resize(400, 400)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.l = QtWidgets.QLabel(self.centralwidget)
            self.l.setGeometry(QtCore.QRect(0, 10, 200, 200))
            self.l.setText("长度:")
            font = QtGui.QFont()
            font.setPointSize(30)
            self.l.setFont(font)
            self.l.setAlignment(QtCore.Qt.AlignCenter)
            self.l.setObjectName("label")
            self.l.setVisible(True)
            MainWindow.setCentralWidget(self.centralwidget)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
            self.retranslateUi(MainWindow)
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        mainWindow = QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(mainWindow)
        mainWindow.show()
        sys.exit(app.exec_())
    

    在这里插入图片描述

  3. Python3 多线程

  4. Opencv 帧差法物体追踪

    import cv2
    
    firstframe = None
    if __name__ == '__main__':
        cap = cv2.VideoCapture(0)
        while 1:
            ret, frame = cap.read()
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 灰度
            gray = cv2.GaussianBlur(gray, (21, 21), 0)  # 高斯滤波
            if firstframe is None:  # 记录上次的状态,实现侦差
                firstframe = gray
                continue
            # 获取帧差
            frameDelta = cv2.absdiff(firstframe, gray)  # 计算当前帧与背景之差的绝对值
            firstframe = gray  # 重新赋值
            thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]  # 二值化
            thresh = cv2.dilate(thresh, None, iterations=2)  # 膨胀
            cv2.imshow((u"1"), frame)
            cv2.imshow((u"2"), gray)
            cv2.imshow((u"3"), thresh)
            if ord('q') == cv2.waitKey(10):
                cap.release()
                cv2.destroyAllWindows()
                exit(0)
    
    

在这里插入图片描述

  1. 若干次卡尔曼滤波

    def KalmanFilter(z, n_iter=20, init=0):
        # 这里是假设A=1,H=1的情况
        # intial parameters
        sz = (n_iter,)  # size of array
        # Q = 1e-5 # process variance
        Q = 1e-6  # process variance
        # allocate space for arrays
        xhat = numpy.zeros(sz)  # a posteri estimate of x
        P = numpy.zeros(sz)  # a posteri error estimate
        xhatminus = numpy.zeros(sz)  # a priori estimate of x
        Pminus = numpy.zeros(sz)  # a priori error estimate
        K = numpy.zeros(sz)  # gain or blending factor
        R = 0.1 ** 2  # estimate of measurement variance, change to see effect
        # intial guesses
        xhat[0] = init
        P[0] = 1.0
        A = 1
        H = 1
        for k in range(1, n_iter):
            # time update
            xhatminus[k] = A * xhat[k - 1]  # X(k|k-1) = AX(k-1|k-1) + BU(k) + W(k),A=1,BU(k) = 0
            Pminus[k] = A * P[k - 1] + Q  # P(k|k-1) = AP(k-1|k-1)A' + Q(k) ,A=1
            # measurement update
            K[k] = Pminus[k] / (Pminus[k] + R)  # Kg(k)=P(k|k-1)H'/[HP(k|k-1)H' + R],H=1
            xhat[k] = xhatminus[k] + K[k] * (z[k] - H * xhatminus[k])  # X(k|k) = X(k|k-1) + Kg(k)[Z(k) - HX(k|k-1)], H=1
            P[k] = (1 - K[k] * H) * Pminus[k]  # P(k|k) = (1 - Kg(k)H)P(k|k-1), H=1
        return xhat
    
  2. 实际测量数据的校验
    下面是实际遇到暂时无法解决的,直接 if else 处理

    if lm > 140 and l >= 135:
        l = 147
    if lm >= 137.5 and lm <= 142.5 and l >= 130 and l <= 135:
        l = 142
    if l * 2 <= lm:
        l = lm
    else:
        l = (l + lm) / 2
    if l <= 52:
        l = 52
    if l >= 148:
        l = 148
    
  3. 串口通信

  4. Python Pexpect 实现所有节点一键关机

最终终端节点显示:

在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_44009311/article/details/121781479