您的位置: 首页 - 站长

jsp网站购物车怎么做CQ网站建设

当前位置: 首页 > news >正文

jsp网站购物车怎么做,CQ网站建设,做卫生用品的网站,百度资源搜索平台1.项目介绍 本文档是对于“车流量检测平台”的应用技术进行汇总#xff0c;适用于此系统所有开发#xff0c;测试以及使用人员#xff0c;其中包括设计背景#xff0c;应用场景#xff0c;系统架构#xff0c;技术分析#xff0c;系统调度#xff0c;环境依赖#xf… 1.项目介绍 本文档是对于“车流量检测平台”的应用技术进行汇总适用于此系统所有开发测试以及使用人员其中包括设计背景应用场景系统架构技术分析系统调度环境依赖以及运行指导其中技术分析为主要部分包括UI设计视频输入输出图像预处理数据提取处理及预测等。 2.设计背景 政治角度 随着城市化进程的加快和交通拥堵问题的日益严重政府对于智能交通系统的建设与管理给予了高度重视。基于视频的车流量检测平台作为智能交通系统的重要组成部分其开发与应用有助于提升城市治理水平满足政府对交通状况实时监测与管理的需求。 经济角度 随着信息技术的快速发展视频处理技术、计算机视觉和深度学习等领域取得了显著进步为基于视频的车流量检测平台的开发提供了技术支撑。同时随着汽车保有量的不断增加交通管理领域对于智能化、自动化的需求也日益旺盛推动了基于视频的车流量检测平台的研发与应用。 社会角度 公众对于出行效率、交通安全和环境质量的关注度不断提高对于智能交通系统的期待也日益增强。基于视频的车流量检测平台能够实时监测交通状况为公众提供更加便捷、安全的出行环境同时也有助于减少交通拥堵和环境污染提升城市生活质量。 此外传统的车流量检测方法主要依赖于传感器设备如地磁传感器、红外线传感器等。这些传感器需要在道路上布设成本较高且安装维护困难。而基于计算机视觉的车流量检测系统则可以通过分析道路上的摄像头图像来实现具有成本低、安装方便、实时性强等优势。因此设计一种高效、准确且易于实现的汽车流量检测系统显得尤为重要。 3.场景应用 随着城市化进程的加快和交通工具的普及车辆数量的快速增长给城市交通管理带来了巨大的挑战。因此交通流量检测成为了交通管理的重要组成部分。它能够提供实时的交通状况信息帮助交通管理部门制定合理的交通策略优化交通流量提高道路利用效率减少交通拥堵和事故发生的可能性。 基于视频的车流量检测平台可广泛应用于城市道路、高速公路、桥梁隧道等交通场景中。通过高清摄像头实时拍摄车辆图像利用图像处理算法对图像进行分析和处理提取出车辆的位置、数量和运动轨迹等信息。这些信息可用于交通管理部门对道路交通情况的监测和分析也可用于交通规划和设计、交通预测和智能交通系统等领域。 解决的社会痛点

  1. 交通拥堵问题 基于视频的车流量检测平台能够实时监测交通流量和车辆速度等信息为交通管理部门提供实时、准确的数据支持。通过数据分析可以及时发现交通拥堵点采取相应的交通控制措施优化交通流动减少交通拥堵现象。
  2. 交通安全问题 通过对车辆运动轨迹的监测和分析平台可以及时发现异常行驶行为如超速、逆行等为交通管理部门提供预警信息有助于减少交通事故的发生。
  3. 环境质量问题 平台还可以监测城市环境质量如空气质量、噪声等。通过对这些数据的分析可以及时发现环境质量不佳的区域采取相应措施减少污染源提高城市环境质量。
  4. 公共服务效率问题 在公共交通领域基于视频的车流量检测平台可以实时监测公交、地铁等公共交通的运行情况为公众提供更加精准的出行信息提高公共服务的效率和质量。 4.系统架构 4.1用户界面层 使用QT框架开发图形用户界面GUI展示实时视频流、预处理视频流流量统计数据、当天车流信息以及未来车流信息等。用户可以通过此界面进行参数设置、启动/停止检测等操作。 4.2视频处理层 接入摄像头或视频流利用OpenCV库进行视频捕获和预处理。实现车辆检测算法包括提取物体掩码、运动目标检测、车辆识别等步骤。将检测到的车辆信息传递给下一层。 4.3数据处理与存储层 接收视频处理层传递的车辆信息并进行进一步的分析和处理包括提取真实汽车掩码以及Opencv格式的图片与Qt支持的图片进行格式转化。将可用数据提取出来并进一步的过滤并且利用梯度下降法拟合数据的函数模型。 4.5数据存储层 将处理后的数据存储在数据库中包括车辆流量统计数据、时间戳。实现数据查询预测和报表生成功能供用户层调用和展示。 5.技术分析 1视频处理流程图 5.1UI设计 2 UI设计图 客户端界面利用QT5搭建而成这些窗口分别是源视频识别并标记显示窗口计算机图像学处理后的窗口未来数据预期窗口用来显示未来某天二十四小时的车流量当天的车流量情况展示窗口最后一个是日历可以选择日期还有对于视频流的播放控制有两个按钮控制。 使用Qlabel控件在其之上利用绘图事件分别将标记后的视频流和预处理视频流播放出来。 折线统计图用于展示以前某天或未来某天24小时的车流量变化情况条形统计图用于实时展示当天的车流情况。 中间两个窗口分别显示实时监控的视频图像以及汽车轮廓和视频流处理过程。 利用QToolButton控件设置两个按钮来控制视频流的播放。 两个QEditLine 控件用于输入机器学习的频率和次数。 那个大的按钮是主动学习的控制开关点击触发后变为红色开始学习并再右上角的编辑框显示学习进度。 使用日历控件可以先择事件如果选择过去的某天就将过去的某天二十四小时的车流量情况图像化的显示如果选择未来某天就将这天预测的数据显示出来。 5.2视频流的输入输出 在C中使用OpenCV库处理视频流时cv::VideoCapture 类是一个非常重要的组件它用于捕获视频流可以从摄像头、视频文件或IP摄像头流中读取帧。 使用实例 cv::VideoCapture cap(0); // 检查摄像头是否成功打开 if (!cap.isOpened()) { std::cerr Error opening video stream or file std::endl; return -1; } cv::namedWindow(Video, cv::WINDOW_AUTOSIZE); while (true) { // 读取一帧图像 cap frame; // 检查是否成功读取帧    if (frame.empty()) { std::cout Cant receive frame (stream end?). Exiting … std::endl; break; } cv::imshow(”Video”,res); } 5.3图像预处理 3 最终呈现图 5.3.1获取前景掩码 图片前景掩码通常简称为前景掩码在图像处理中是一个重要的概念主要用于从图片中分离出前景元素。掩码是一个二值图像其中前景元素被标记为白色或其他高亮颜色而背景元素则被标记为黑色或其他暗色。通过这种方式掩码可以帮助我们在后续的图像处理过程中只处理或操作前景元素而忽略背景元素。基于颜色或亮度的差异如果前景和背景在颜色或亮度上有明显的差异可以使用阈值操作或色彩分割等方法来生成掩码。一旦生成了前景掩码就可以将其应用于各种图像处理任务如前景元素的提取、背景的替换、图像合成等。 4 汽车前景掩码图 接口解释 setShadowThreshold() 这个方法是用来设置阴影检测阈值的。阴影阈值决定了算法如何区分前景对象和其可能产生的阴影。通过调整这个阈值你可以影响算法对阴影的敏感度。 apply() apply()方法是BackgroundSubtractorMOG2类的主要方法用于执行背景减除。当你调用这个方法时它会处理传入的图像并返回一个新的图像其中前景对象即移动的对象被高亮显示通常是白色而背景则被抑制通常是黑色。 5.3.2形态学开运算 二值图像中一类主要处理是对提取的目标图形进行形态分析。形态学处理中最基本的是腐蚀和膨胀。腐蚀和膨胀是两个互为对偶的运算。腐蚀的作用是将目标图像收缩而膨胀是将图像扩大。结构元素是指具有某种确定形状的基本结构元素例如一定大小的矩形、圆形等。结构元素具有原点。 5.3.2.1 形态学 形态学操作是根据图像形状进行的简单操作。一般情况下对二值化图像/灰度图像进行操作。它需要输入两个操作一个是原始图像另一个被称为结构化元素或核它是用来决定操作的性质的。两个基本的形态学操作是腐蚀和膨胀它们的变体构成了开运算、闭运算和梯度等。 5 腐蚀/膨胀对比图 5.3.2.2 腐蚀 腐蚀的效果是把图片变瘦其原理是在原图的小区域内取局部最小值。因为是二值化图只有 0 和 255所以小区域内有一个是 0 该像素点就为 0 5.3.2.3 膨胀 膨胀与腐蚀相反取的是局部最大值效果是把图片变胖。 5.3.2.4 开/闭运算 开运算先腐蚀后膨胀可用以消除黑色背景中的白点杂质。 闭运算先膨胀后腐蚀可用以消除白色前景中的黑点杂质。 6 形态学闭运算处理图 接口 腐蚀Erosion void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchorPoint(-1,-1), intiterations1,IntborderTypeBORDER_CONSTANT, const ScalarborderValuemorphologyDefaultBorderValue()); 参数解释 src输入图像通常是二值图像。 dst输出图像与输入图像具有相同的尺寸和类型。 kernel用于腐蚀的结构元素定义了邻域的形状和大小。 anchor结构元素的锚点位置。默认值是(-1, -1)表示锚点位于结构元素的中心。 iterations腐蚀操作的迭代次数。 borderType像素外推法的类型。 borderValue使用边界类型BORDER_CONSTANT时的边界值。 膨胀Dilation void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchorPoint(-1,-1),
    int iterations1,int borderTypeBORDER_CONSTANT, const Scalar borderValuemorphologyDefaultBorderValue()); 参数解释 src输入图像通常是二值图像。 dst输出图像与输入图像具有相同的尺寸和类型。 kernel用于膨胀的结构元素定义了邻域的形状和大小。 anchor结构元素的锚点位置。默认值是(-1, -1)表示锚点位于结构元素的中心。 iterations膨胀操作的迭代次数。 borderType像素外推法的类型。 borderValue使用边界类型BORDER_CONSTANT时的边界值。 5.3.3高斯滤波 高斯滤波(Gauss Filter)是线性滤波中的一种。在OpenCV图像滤波处理中高斯滤波用于平滑图像或者说是图像模糊处理因此高斯滤波是低通的。其广泛的应用在图像处理的减噪过程中尤其是被高斯噪声所污染的图像上。 高斯滤波的基本思想是: 图像上的每一个像素点的值都由其本身和邻域内其他像素点的值经过加权平均后得到。其具体操作是用一个核(又称为卷积核、掩模、矩阵)扫描图像中每一个像素点将邻域内各个像素值与对应位置的权值相称并求和。从数学的角度来看高斯滤波的过程是图像与高斯正态分布做卷积操作。 注意: 高斯滤波是将二维高斯正态分布放在图像矩阵上做卷积运算。考虑的是邻域内像素值的空间距离关系因此对彩色图像处理时应分通道进行操作也就是说操作的图像原矩阵时用单通道数据最后合并为彩色图像。 5.3.3.1 一维高斯函数 可以看到G(x)的跟sigma的取值有极大的关系。sigma取值越大图像越平缓sigma取值越小图像越尖锐。 7 一维高斯函数 5.3.3.2 二维高斯函数 二维高斯是构建高斯滤波器的基础。可以看到G(x,y)在x轴y轴上的分布是一个突起的帽子的形状。这里的sigma可以看作两个值一个是x轴上的分量sigmaX另一个是y轴上的分量sigmaY。对图像处理可以直接使用sigma并对图像的行列操作也可以用sigmaX对图像的行操作再用sigmaY对图像的列操作。它们是等价的。当sigmaX和sigmaY取值越大整个形状趋近于扁平当sigmaX和sigmaY取值越小整个形状越突起。 高斯滤波原理就是将上图的二维正态分布应用在二维的矩阵上G(x,y)的值就是矩阵上的权值将得到的权值进行归一化将权值的范围约束在[0,1]之间并且所有的值的总和为1。可以看到权值的分布是以中间高四周低来分布的。并且距离中心越远其对中心点的影响就越小权值也就越小。 因此可以总结 1在核大小固定的情况下sigma值越大权值分布越平缓。因此邻域各个点的值对输出值的影响越大最终结果造成图像越模糊。 2在核大小固定的情况下sigma值越小权值分布越突起。因此邻域各个点的值对输出值的影响越小图像变化也越小。假如中心点权值为1其他点权值为0那么最终结果是图像没有任何变化。 3sigma固定时核越大图像越模糊。 4sigma固定时核越小图像变化越小。 9 采用高斯滤波后的图 接口解释 void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY0, int borderTypeBORDER_DEFAULT); 参数解释 src输入图像可以是多通道图像。 dst输出图像与输入图像具有相同的尺寸和类型。 ksize高斯核的大小。它必须是正奇数。 sigmaX表示高斯核函数在X方向的标准差。 sigmaY表示高斯核函数在Y方向的标准差。如果sigmaY设置为0那么它会被设置为与sigmaX相同的值。两个sigma值决定了高斯核的形状。 borderType像素外推法的类型决定了当高斯核应用到图像边界时如何处理边界外的像素。默认值是BORDER_DEFAULT。 5.4数据处理 5.4.1 数据预处理 原图通过一系列图形学处理后已经可以提取出想要的数据了接下来就是数据数据除杂和过滤的过程。 5.4.1.1提取汽车掩码 寻找所有汽车掩码前景的连通图如果连通图的长宽以及面积都复合实验阈值那么此掩码就是汽车的掩码。 10 计算汽车前景掩码流程图 核心算法 findContours(dst, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);     for (size_t i 0; i contours.size(); i)     {         Rect2d re c2d(boundingRect(contours[i]));         if (re.width90 re.width440 re.height140 re.height440)         {             box3.push_back(re);             rectangle(frame, re, cv::Scalar(0, 255, 0), 2);         }     } 5.4.1.2 数据过滤 依次和前一次的连通图组逐个进行比较如果出现重叠面积大于等于当前面积的百分之十则认为此汽车已经计数否则依次向更久的连通组比较直到遍历完所有历史数据。最终用所有车减去历史出现的车等于新出现的车。 11 统计汽车数量流程图 核心算法 int Run::findsum() {     int sum 0;     for (size_t i 0; i box3.size(); i)     {         bool bo false;         for (size_t j 0; j box2.size(); j)         {             if (overlapArea(box3[i], box2[j]) / box3[i].area() 0.1)             {                 bo true;                 break;             }             else             {                 for (size_t k 0; k box1.size(); k)                 {                     if (overlapArea(box3[i], box1[k]) / box3[i].area() 0.1)                     {                         bo true;                         break;                     }                 }             }         }         if (bo)sum;     }     return sum; } 5.4.2 流量检测 如图所示利用连续三帧图像来确定是否有新出现的车辆这三帧中总共出现了七辆车。 流量检测过程图 12-1 第一帧有四辆车 12-2 第二帧有两辆车其中新出现了一辆 12-3 第三帧有四辆车其中新出现了量辆 5.4.3 结果统计 利用当帧图像中汽车的总数量-前一帧汽车的数量当前帧新出现的汽车数量。 而其中计算是否为之前已经出现过的车利用了面积重叠法。 13 判断是否为已经扫描过的车辆示意图 核心算法 double Run::overlapArea(Rect2d rect1, Rect2d rect2) {     int overlapLeft std::max(rect1. x, rect2.x);     int overlapRight std::min(rect1.xrect1.width, rect2.xrect2.width);     int overlapTop std::max(rect1.y, rect2.y);     int overlapBottom std::min(rect1.yrect1.height, rect2.yrect2.height);     // 如果重叠区域的左右或上下边界无效即没有重叠则返回0     if (overlapLeft overlapRight || overlapTop overlapBottom)     {         return 0;     }     // 计算重叠区域的宽度和高度     int overlapWidth overlapRight - overlapLeft;     int overlapHeight overlapBottom - overlapTop;     // 计算重叠面积     return overlapWidth * overlapHeight; } 5.4.4 数据存储 数据存储利用关系型数据SQLite。SQLite是一个功能强大且易于使用的数据库系统特别适用于那些需要轻量级、嵌入式和跨平台数据库解决方案的场景。这个表tim字段是一个INTEGER类型可转为long long用于存储UNIX时间戳。num字段是一个整型用于存储车辆数量。可以从数据库中拿到历史数据也可以将新扫描的数据存放到数据库中。 建表语句 CREATE TABKE car_table ( tim INTEGER PRIMARY KEY, num INT NOT NULL);
    5.4.5 流量预测 我们首先想到简单线性回归分析但是通过观察发现车流量变化的函数曲线接近于正弦曲线因此采用梯度下降拟合曲线。 使用梯度下降法来拟合y a * sin(b * X c) d形式的模型是一个迭代的过程其中我们逐步调整模型的参数a, b, c, d以最小化预测值和实际值之间的误差。 5.4.5.1梯度下降 14梯度下降求极值示意图 5.4.5.1.1算法简介 梯度下降法Gradient Descent是一种优化算法常用于机器学习和深度学习的训练过程中特别是用于求解损失函数的最小值。该算法的基本思想是通过迭代的方式调整模型参数以使得损失函数逐渐减小从而逼近最小值。 梯度下降法的工作原理如下 1.选择初始参数首先需要为模型的参数选择一个初始值。这些参数可以是随机选择的也可以是基于某种启发式方法选择的。 2.计算梯度在每一次迭代中计算损失函数关于模型参数的梯度。梯度表示了损失函数在各个方向上的变化率因此指向了损失函数减小最快的方向。 3.更新参数根据计算得到的梯度按照一定的学习率learning rate来更新模型的参数。学习率是一个超参数它决定了每次参数更新的步长。过大的学习率可能导致算法不稳定而过小的学习率则可能导致算法收敛速度过慢。 4.重复迭代重复执行步骤2和步骤3直到满足某种停止条件如损失函数值小于某个阈值或者达到预设的最大迭代次数。 1.为什么按负梯度下降 《数学分析》中负梯度方向是函数下降最快的方向即x[2,3],如果梯度为[1,2],则x往[1,2]方向调整能令函数f(x)下降最快的方向所谓最快即调整同样的步长该方向能令函数下降最快按负梯度下降保证了调整方向的正确性。 2.为什么要设置学习率 目的是为了保证按梯度方向调整一定能下降。梯度方向能下降是瞬时的如果调整步长过大则不一定能保证函数能下降但只要调整步长足够小函数就能下降前提是梯度不为0。所以我们在调整时加入学习率lr以控制步长 3、学习率的设置与自适应学习率 要保证能下降学习率就不能过大但学习率很小每次迭代调整都很小就需要迭代很多次。为此我们可以设定一个较中肯的学习率(例如lr 0.1)。如果更智能一些在程序中把学习率改为自适应学习率: 函数能下降我们把学习率调大些如果函数本次迭代不能下降我们就把学习率调小些。 5.4.5.1.2初始化参数 A -100.0; // 振幅初始估计 B 2.0 * std::acos(-1.0) / (76802); // 频率初始估计假设周期为12h C 0.0; // 相位初始估计 D 150.0; // 偏移量初始估计 5.4.5.1.3正弦函数拟合模型 double myData::sine_model(long long x, double A, double B, double C, double D) { return A * std::sin(B * x C) D; } 5.4.5.1.4计算误差平方和 double myData:: compute_error(const std::vectorlong long x_data, const std::vectorint y_data, double A, double B, double C, double D) {     double error 0.0;     for (size_t i 0; i x_data.size(); i)     {         double y_pred sine_model(x_data[i], A, B, C, D);         error std::pow(y_data[i] - y_pred, 2);     }     return error; } 5.4.5.1.5梯度下降法优化参数 void myData::gradient_descent(const std::vectorlong long x_data, const std::vectorint y_data,double A, double B, double C, double D,double learning_rate, int iterations) { for (int iter 0; iter iterations; iter) {    double dA 0.0, dD 0.0;    double dB 0.0, dC 0.0;    //double error compute_error(x_data, y_data, A, B, C, D);    // 计算梯度    for (size_t i 0; i x_data.size(); i)    {       long long x x_data[i];       double y y_data[i];       //qDebug()x———y;       double y_pred sine_model(x,A,B,C,D);           dA  (y - y_pred) * std::sin(B * x C);       dB  (y - y_pred) * A * x * std::cos(B * x C);       dC  (y - y_pred) * A * std::cos(B * x C);       dD  (y - y_pred);    }    // 更新参数    A - learning_rate * dA / x_data.size();    B - learning_rate * dB / x_data.size();    C - learning_rate * dC / x_data.size();    D- learning_rate * dD / x_data.size();   // 输出迭代信息可选   if (iter % 100 0)   {     qDebug() Iteration iter : A A , B B , C C , D D ;   } } } 5.4.5.2线性回归 线性回归是一种统计学上分析数据的方法用来确定两种或两种以上变量之间关系的强度和方向。它通常用于预测一个因变量或响应变量基于一个或多个自变量或预测变量的变化。这种方法得名于它使用一个或多个独立变量或特征的线性组合来预测因变量或目标变量。 通过将时间转化为时间戳X汽车流量Y之后就可以进行线性回归分析YK*Xb; 通过最小二乘法计算线性回归的系数 pairdouble,doublecalculateLinearRegression(vectordouble x, vectordouble y)  {     int n x.size();       // 计算x和y的均值       double mean_x accumulate(x.begin(), x.end(), 0.0) / n;       double mean_y accumulate(y.begin(), y.end(), 0.0) / n;       // 计算x和y的乘积之和以及x的平方和       double sum_xy 0.0;       double sum_x2 0.0;       for (int i 0; i n; i) {           sum_xy x[i] * y[i];           sum_x2 pow(x[i], 2);       }         // 计算斜率m和截距b   double m (n * sum_xy - accumulate(x.begin(), x.end(), 0.0) * accumulate(y.begin(), y.end(), 0.0)) /(n * sum_x2 - pow(accumulate(x.begin(), x.end(), 0.0), 2));       double b mean_y - m * mean_x;         return {m, b};   }  
    5.4.6 图像格式转换 将 OpenCV 的图像格式转换为 Qt 的图像格式。函数检查输入的 cv::Mat 对象的类型。OpenCV 支持多种图像类型但此函数主要处理三种类型CV_8UC1单通道8位无符号整数通常用于灰度图像、CV_8UC3三通道8位无符号整数通常用于彩色图像和 CV_8UC4四通道8位无符号整数通常用于带有 alpha 通道的彩色图像。 QImage Run:: getQImage(const cv::Mat mat) {     if (mat.type() CV_8UC1)     {         QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);         image.setColorCount(256);         for (int i 0; i 256; i)         {             image.setColor(i, qRgb(i, i, i));         }         uchar* pSrc mat.data;         for (int row 0; row mat.rows; row)         {             uchar* pDest image.scanLine(row);             memcpy(pDest, pSrc, mat.cols);             pSrc mat.step;         }         return image; } else if (mat.type() CV_8UC3) {     const uchar* pSrc (const uchar)mat.data;         QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);         return image.rgbSwapped();     }     else if (mat.type() CV_8UC4) {     const uchar pSrc (const uchar*)mat.data;         QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);         return image.copy();     }         return QImage(); }
    6.系统调度 6.1事件循环机制 QT事件循环是Qt框架中处理事件的核心机制它确保了应用程序能够响应并处理各种异步事件事件循环通过一个事件队列来管理和调度事件。当队列中有事件时事件循环会从队列中依次取出事件并处理直到队列为空或者事件循环被中断。 6.2信号槽机制 QT信号槽是Qt框架中一种独特且强大的对象间通信机制。信号signal是对象发出的一种特定事件而槽slot则是用于响应这些信号的特定函数或方法。当某个对象发出信号时与之相关联的槽函数会被自动调用从而实现了对象间的通信和协作。 信号和槽的连接可以是一对一、多对一、一对多或者多对多这使得对象间的通信非常灵活。同时信号和槽机制还具有解耦和灵活性的优点因为对象之间通过信号和槽进行通信彼此之间不需要显式的引用从而实现了松耦合的设计。此外这种机制还具有可扩展性因为可以动态地连接和断开信号和槽使得系统更容易扩展和维护。 在程序开始就新建一个线程用于专门处理图像并计数这样异步的设计将鼠标事件绘图事件以及视频处理异步解耦这种设计方式不仅提高了程序运行速度而且使得人机交互更加灵活。 7.模块依赖 SqLiteQT-5.15.2OpenCV-4.5.2 8.运行指导 在Windows下直接解压压缩包,双击exe文件即可执行启动之初会加载一段时间这是机器学习的过程由于没有外接摄像头因此只在可执行程序目录下放了一段模拟视频视频较短视频播放结束程序就停止运行。