Python+OpenCV+Flask实现本地摄像头MJPEG网络视频流

news2026/5/7 3:49:20
1. 项目概述将本地摄像头变成网络视频流最近在折腾一个智能家居的小项目需要把家里一台旧笔记本的摄像头信号通过网络推送到其他设备上显示。一开始想找现成的软件要么太臃肿要么收费要么配置复杂得让人头疼。后来在GitHub上翻到了这个叫mehmetkahya0/local-web-camera的项目眼前一亮。它本质上是一个用Python写的轻量级Web服务器核心功能就一个把你的本地摄像头无论是笔记本内置的还是外接的USB摄像头的画面通过网页实时播放出来。听起来很简单对吧但真正用起来你会发现它解决了一个非常具体的痛点快速、零配置地实现摄像头画面的网络共享。你不需要安装庞大的监控软件不需要折腾复杂的RTSP/RTMP服务器配置更不用去申请什么公网IP或做内网穿透当然如果你需要从外网访问那是另一回事。只需要几行命令打开浏览器输入本机IP和端口就能看到实时画面。这对于需要临时搭建一个视频监控点、进行远程调试、或者像我一样做智能家居原型验证的场景简直是神器。这个项目的价值在于它的“轻”和“直接”。它没有管理后台没有移动端APP没有云存储就是一个纯粹的、高效的视频流中继。代码仓库的星星数不算特别多但这类工具往往在特定的小众场景下能发挥巨大作用。接下来我就结合自己的实际使用和代码分析带你彻底搞懂它并分享如何把它用得更好、更稳。2. 核心原理与技术栈拆解2.1 整体架构从摄像头到浏览器这个项目的架构非常清晰是一个典型的客户端-服务器模型只不过“客户端”是我们的摄像头硬件和浏览器“服务器”是这个Python脚本。整个数据流可以这样理解采集层Python脚本利用OpenCV(cv2) 库打开本地摄像头设备以一定的帧率如30fps循环抓取图像帧。每一帧都是一个多维数组通常是Height x Width x Channels比如480x640x3的BGR图像。处理与编码层抓取到的原始图像帧BGR格式被转换为JPEG格式。这一步是关键因为原始视频流数据量巨大无法直接在网络上高效传输。转换成JPEG是一种有损压缩能极大减少单帧图片的数据量。项目里使用的是cv2.imencode(‘.jpg’, frame, [cv2.IMWRITE_JPEG_QUALITY, 85])这里的85是JPEG压缩质量参数可以在文件大小和图像质量间权衡。传输层编码后的JPEG字节流被嵌入到一个特殊的HTTP响应体中。服务器端使用Flask或Bottle这样的轻量级Web框架定义一个路由比如/video_feed。当浏览器通过这个路由发起请求时服务器并不是返回一个静态文件而是返回一个multipart/x-mixed-replace类型的响应。这个MIME类型允许服务器在同一个HTTP连接中持续不断地用新的JPEG图像数据替换旧的从而实现“流式”传输。展示层浏览器接收到这种特殊的流后img标签的src属性指向/video_feed。浏览器会持续解析这个流将不断到来的JPEG图片一帧一帧地渲染出来形成动态视频效果。所以你看到的网页视频并不是真正的视频流如H.264编码的MP4而是一系列快速刷新的JPEG图片。这种方式被称为MJPEG (Motion JPEG)。它的优点是实现极其简单兼容性极好任何能显示图片的浏览器都支持延迟相对较低。缺点则是压缩效率不如现代视频编码H.264/265在同等画质下带宽占用更高。2.2 关键技术组件解析OpenCV (cv2)计算机视觉的“瑞士军刀”。在这里它主要扮演两个角色视频捕获cv2.VideoCapture(0)这句代码是起点。参数0通常代表系统默认的第一个摄像头。它抽象了不同操作系统Windows的DirectShow、Linux的V4L2、macOS的AVFoundation的底层摄像头接口提供了统一的调用方式。图像编码cv2.imencode将内存中的图像数组高效地编码成JPEG字节流比用PIL库等其他方式通常更快因为它与cv2.imread/cv2.imwrite共享底层优化。Flask / Bottle极简的Python Web框架。选择它们而非Django等重型框架完全符合项目的“轻量”定位。它们只需要几十行代码就能拉起一个HTTP服务器处理路由定义和请求响应。在这个项目里框架的核心任务就是提供静态网页一个包含img src“/video_feed”的HTML页面。实现/video_feed这个动态路由并按照MJPEG的格式要求生成响应。MJPEG over HTTP这是整个项目的通信基石。multipart/x-mixed-replace响应头告诉浏览器“准备好我会在这个连接里不断给你发新的部分parts每个部分都替换前一个。” 每个部分即一帧图片以固定的边界符boundary分隔并包含自己的头部Content-Type: image/jpeg和主体JPEG数据。浏览器会持续解析实现视频播放。线程与生成器这是一个重要的性能优化点。如果视频捕获cv2.VideoCapture.read()和HTTP响应写在同一个线程里那么响应发送速度就会受限于摄像头抓帧的速度容易造成阻塞。常见的优化方式是使用一个全局帧缓冲区和一个独立的捕获线程。捕获线程不断将最新的帧放入缓冲区而/video_feed路由的处理函数一个生成器则不断地从缓冲区中取出最新的帧编码并yield给HTTP响应。这样即使某次网络发送稍慢也不会拖慢摄像头的抓取。3. 从零开始部署与深度配置3.1 基础环境搭建假设你有一台安装了Python的电脑Windows, macOS, Linux均可和一个可用的摄像头。首先克隆项目代码如果作者提供了或者根据原理自己创建一个简单的脚本。这里我以创建一个最简版本为例# 创建一个项目目录 mkdir local-web-camera cd local-web-camera # 创建虚拟环境推荐避免包冲突 python -m venv venv # Windows 激活: venv\Scripts\activate # Linux/macOS 激活: source venv/bin/activate # 安装核心依赖 pip install opencv-python flask接下来创建主程序文件app.pyfrom flask import Flask, Response, render_template_string import cv2 import threading import time app Flask(__name__) # 全局变量用于存储最新帧和锁 latest_frame None frame_lock threading.Lock() def capture_frames(): 独立的摄像头捕获线程 global latest_frame # 尝试打开摄像头参数0通常是默认摄像头 cap cv2.VideoCapture(0) # 可以设置分辨率例如cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) if not cap.isOpened(): print(“错误无法打开摄像头”) return while True: success, frame cap.read() if not success: break with frame_lock: # 可选在这里对帧进行处理如缩放、画框等 # frame cv2.resize(frame, (640, 480)) latest_frame frame.copy() # 使用copy避免引用问题 time.sleep(0.033) # 粗略控制帧率 ~30fps cap.release() def generate_frames(): 视频流生成器函数 global latest_frame while True: with frame_lock: if latest_frame is None: continue frame latest_frame # 将帧编码为JPEG格式 ret, buffer cv2.imencode(‘.jpg’, frame, [cv2.IMWRITE_JPEG_QUALITY, 85]) if not ret: continue # 转换为字节流并按照MJPEG格式封装 frame_bytes buffer.tobytes() yield (b‘--frame\r\n’ b‘Content-Type: image/jpeg\r\n\r\n’ frame_bytes b‘\r\n’) app.route(‘/video_feed’) def video_feed(): 视频流路由 return Response(generate_frames(), mimetype‘multipart/x-mixed-replace; boundaryframe’) app.route(‘/’) def index(): 主页显示视频 html “““ !DOCTYPE html html head title本地网络摄像头/title stylebody { margin: 0; background: #222; } img { width: 100%%; height: auto; display: block; }/style /head body img src“/video_feed” /body /html ””” return render_template_string(html) if __name__ ‘__main__’: # 启动摄像头捕获线程 threading.Thread(targetcapture_frames, daemonTrue).start() # 启动Flask服务器host‘0.0.0.0’允许同一网络下的其他设备访问 app.run(host‘0.0.0.0’, port5000, debugFalse, threadedTrue)3.2 关键参数调优与解释运行python app.py后在电脑浏览器打开http://127.0.0.1:5000就能看到画面。但要让它在不同场景下表现更好需要理解几个关键参数摄像头索引与参数设置cv2.VideoCapture(0)这里的0是设备索引。如果你有多个摄像头可能需要尝试1,2。cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)和cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)强烈建议设置。如果不设置OpenCV可能会使用摄像头驱动提供的默认分辨率有时会非常高如1920x1080导致编码和传输压力巨大延迟飙升。设置为640x480或800x600是网络流常用的平衡点。cap.set(cv2.CAP_PROP_FPS, 30)尝试设置帧率。但注意这个设置是“请求”而非“保证”具体取决于摄像头硬件和驱动支持。图像编码质量cv2.IMWRITE_JPEG_QUALITY, 85JPEG质量参数范围1-100。85是一个很好的折衷值。调低此值如70可以显著减小每帧图片的大小降低带宽占用但画面细节会损失可能出现块状模糊。在带宽有限的Wi-Fi或移动网络下观看时可以考虑降低到75。Flask服务器参数host‘0.0.0.0’这是允许其他设备访问的关键。127.0.0.1或localhost只允许本机访问。设置为0.0.0.0后同一局域网内的手机、平板、另一台电脑都可以通过你的电脑IP地址如http://192.168.1.100:5000访问视频流。threadedTrue让Flask使用多线程处理请求。这对于视频流应用很重要因为/video_feed是一个长连接如果单线程服务器就无法同时处理其他请求比如访问主页。debugFalse在生产运行时务必关闭。Debug模式会启用调试器和代码重载存在安全风险且性能较低。帧率控制代码中使用了time.sleep(0.033)来粗略控制捕获线程的循环速度目标约30fps。更精确的做法是使用cap.get(cv2.CAP_PROP_FPS)获取摄像头实际能力或者根据实际耗时动态调整。帧率并非越高越好。25-30fps对于大多数监控和查看场景已经足够流畅。更高的帧率意味着更大的数据量和CPU编码压力。4. 高级功能扩展与实战技巧基础功能跑通后我们可以基于这个框架添加一些非常实用的功能。4.1 功能一多摄像头支持与切换如果你有多个USB摄像头可以很容易地扩展支持。思路是创建多个VideoCapture实例和对应的全局帧缓冲区。# 在全局变量部分 camera_frames {} # 例如 {‘cam0’: frame_data, ‘cam1’: frame_data} camera_locks {} # 为每个摄像头配备单独的锁 active_camera_id ‘cam0’ # 当前活动的摄像头 # 修改捕获线程函数使其能根据摄像头ID工作 def capture_frames(camera_id, device_index): cap cv2.VideoCapture(device_index) # ... 设置分辨率 ... while True: success, frame cap.read() if success: with camera_locks[camera_id]: camera_frames[camera_id] frame.copy() time.sleep(0.033) # 在启动时为每个摄像头启动一个线程 threading.Thread(targetcapture_frames, args(‘cam0’, 0), daemonTrue).start() threading.Thread(targetcapture_frames, args(‘cam1’, 1), daemonTrue).start() # 修改视频流生成器根据请求参数选择摄像头 app.route(‘/video_feed’) def video_feed(): camera_id request.args.get(‘camera’, ‘cam0’) # 从URL参数获取如 ?cameracam1 def generate(): while True: with camera_locks.get(camera_id, threading.Lock()): frame camera_frames.get(camera_id) if frame is not None: ret, buffer cv2.imencode(‘.jpg’, frame) if ret: yield (b‘--frame\r\nContent-Type: image/jpeg\r\n\r\n‘ buffer.tobytes() b‘\r\n’) return Response(generate(), mimetype‘multipart/x-mixed-replace; boundaryframe’) # 在主页HTML中添加切换按钮 html_with_buttons “““ img src“/video_feed?camera“ active_camera_id ““ div button onclick“window.location.href‘/?cameracam0’“摄像头1/button button onclick“window.location.href‘/?cameracam1’“摄像头2/button /div ”””4.2 功能二简单的移动侦测与快照利用OpenCV的背景减除器可以实现简单的移动侦测并在检测到运动时保存快照。from datetime import datetime import os # 在捕获线程中增加运动检测 def capture_frames_with_motion(): global latest_frame cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 创建背景减除器 fgbg cv2.createBackgroundSubtractorMOG2(history500, varThreshold16, detectShadowsFalse) snapshot_dir ‘snapshots‘ os.makedirs(snapshot_dir, exist_okTrue) last_snapshot_time 0 snapshot_cooldown 5 # 两次快照最小间隔秒 while True: success, frame cap.read() if not success: break # 应用背景减除 fgmask fgbg.apply(frame) # 阈值化去除噪声 _, thresh cv2.threshold(fgmask, 244, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, _ cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) motion_detected False for contour in contours: if cv2.contourArea(contour) 500: # 忽略小面积变化噪声 motion_detected True # 可选在帧上画出运动区域 x, y, w, h cv2.boundingRect(contour) cv2.rectangle(frame, (x, y), (xw, yh), (0, 255, 0), 2) break # 找到一个大的运动区域就认为有运动 with frame_lock: latest_frame frame.copy() # 如果检测到运动且冷却时间已过保存快照 if motion_detected: current_time time.time() if current_time - last_snapshot_time snapshot_cooldown: timestamp datetime.now().strftime(“%Y%m%d_%H%M%S”) filename os.path.join(snapshot_dir, f“motion_{timestamp}.jpg”) cv2.imwrite(filename, frame) print(f“运动检测已保存快照{filename}”) last_snapshot_time current_time time.sleep(0.033) cap.release()注意这种基于帧差法的运动检测在室内光线变化时容易误报。更稳定的方案可能需要考虑更复杂的算法或使用PIR传感器等硬件辅助。这里的代码主要提供一种思路。4.3 功能三集成简单的身份验证如果你不希望任何人都能访问你的摄像头流可以添加一个最基本的HTTP基础认证。from flask_httpauth import HTTPBasicAuth from werkzeug.security import generate_password_hash, check_password_hash auth HTTPBasicAuth() users { “admin”: generate_password_hash(“your_strong_password_here”) } auth.verify_password def verify_password(username, password): if username in users and check_password_hash(users.get(username), password): return username app.route(‘/’) auth.login_required def index(): # ... 原有的HTML返回代码 ... app.route(‘/video_feed’) auth.login_required def video_feed(): # ... 原有的视频流生成代码 ...这样首次访问页面时浏览器会弹出一个登录框需要输入正确的用户名和密码才能看到视频流。请注意HTTP基础认证的密码是明文传输除非使用HTTPS因此不适合在公网等不安全环境中使用。对于公网访问务必考虑HTTPS和更安全的认证方式。5. 性能优化与生产环境部署当你想让这个服务更稳定、更高效地运行时需要考虑以下几点。5.1 性能瓶颈分析与优化CPU占用最大的瓶颈通常是JPEG编码。cv2.imencode是CPU操作高分辨率高帧率下压力很大。优化降低分辨率是立竿见影的方法。从1080p降到720p或480p编码消耗呈平方级下降。其次降低帧率。人眼对帧率的敏感度低于分辨率从30fps降到15fps数据量减半CPU压力大减。进阶可以考虑使用硬件加速编码如Intel Quick Sync Video, NVIDIA NVENC但这需要更底层的库如cv2.VideoWriter配合特定的编码器参数并且严重依赖硬件和驱动实现复杂度高与MJPEG的简单性初衷相悖。对于此项目调整分辨率和帧率是最实用的优化手段。网络带宽MJPEG流在640x48030fps质量85的情况下带宽大约在1.5-3 Mbps之间波动。如果通过家庭路由器在局域网内观看这完全不是问题。但如果通过互联网上行带宽通常有限观看就可能卡顿。优化除了降低分辨率、帧率、JPEG质量外几乎没有其他办法。这也是MJPEG的固有缺点。如果公网访问是硬需求应考虑改用压缩效率更高的H.264编码但这意味着整个架构要从“图片流”升级为“视频流”需要引入如ffmpeg、GStreamer或libx264等工具复杂度大大增加。延迟延迟由多个环节构成摄像头感光、数据读取、编码、网络传输、浏览器解码渲染。优化使用有线网络网线代替Wi-Fi可以显著减少网络抖动和延迟。在代码中减少不必要的处理如复杂的运动检测算法和缓冲。确保time.sleep的时间尽可能精确避免捕获线程空等。5.2 使用生产级WSGI服务器Flask自带的开发服务器app.run()性能弱不支持并发不适合生产环境。部署时应该使用诸如Gunicorn(Linux/macOS) 或Waitress(跨平台) 这样的WSGI服务器。# 安装Gunicorn pip install gunicorn # 启动服务假设你的应用对象在 app.py 中名为 app # -w 4: 启动4个工作进程根据CPU核心数调整 # -b 0.0.0.0:5000: 绑定地址和端口 # --threads 2: 每个工作进程的线程数处理I/O密集型任务有益 gunicorn -w 4 -b 0.0.0.0:5000 --threads 2 app:app使用Gunicorn后服务稳定性、并发处理能力都会大幅提升。你可以配合supervisor或systemd来管理进程实现开机自启和崩溃重启。5.3 实现公网访问内网穿透如果你需要在外出时查看家里的摄像头就需要内网穿透。再次强调请务必在添加了身份验证最好是HTTPS后再考虑公网暴露否则你的摄像头流将完全暴露在互联网上。有几种常见方案路由器端口转发这是最传统的方式。在你的家庭路由器上将WAN口的某个端口如50000转发到运行此服务的电脑的IP地址的5000端口。然后你通过http://你的公网IP:50000访问。前提是你的宽带拥有公网IP动态或静态且需要知道如何配置路由器并注意网络安全。使用内网穿透工具如frp,ngrok,花生壳等。这些工具会在公网有一个服务器做中转。你需要在本地运行一个客户端与公网服务器建立隧道。这样你访问公网服务器提供的域名或地址流量就会被转发到你的本地服务。这种方式通常能解决没有公网IP的问题但免费服务可能有带宽和连接数限制。云服务器反向代理如果你有一台云服务器可以在上面配置Nginx反向代理通过HTTPS将请求代理到你家庭网络中的服务同样需要借助frp等工具建立隧道。这是最安全、可控性最高的方案但成本也最高。重要安全提醒无论采用哪种方式将服务暴露到公网必须启用强密码认证并强烈建议启用HTTPS可以使用Let‘s Encrypt获取免费证书。否则你的隐私将毫无保障。6. 常见问题排查与调试心得在实际使用中你可能会遇到以下问题。这里是我的排查清单和经验。6.1 摄像头无法打开或无画面问题现象可能原因排查步骤控制台报错[ WARN:0] global ...或无法打开摄像头1. 摄像头索引错误。2. 摄像头被其他程序占用。3. 权限不足Linux常见。4. 驱动问题。1. 尝试将VideoCapture(0)改为1,2等。2. 关闭所有可能使用摄像头的软件微信、Zoom、其他监控软件。3. 在Linux下尝试使用sudo运行或将用户加入video组 (sudo usermod -aG video $USER)。4. 检查设备管理器Windows或ls /dev/video*(Linux) 确认设备存在。网页打开img标签显示裂图或一直加载1. Flask服务器未正确返回MJPEG流。2. 浏览器兼容性问题罕见。3. 防火墙/安全软件阻止了端口。1. 打开浏览器开发者工具F12的“网络”(Network)标签查看/video_feed请求。状态码应为200响应头Content-Type应为multipart/x-mixed-replace; boundaryframe。如果返回404检查路由定义如果返回500查看Flask控制台错误信息。2. 换用Chrome、Firefox等现代浏览器。3. 暂时关闭防火墙或添加规则允许5000端口入站。实操心得在Linux下一个常见坑是cv2.VideoCapture有时会静默失败cap.isOpened()返回True但cap.read()永远返回(False, None)。可以尝试指定后端cv2.VideoCapture(0, cv2.CAP_V4L2)(for V4L2) 或cv2.CAP_DSHOW(for Windows)。6.2 视频流卡顿、延迟高问题现象可能原因排查与优化画面更新慢像幻灯片1. 帧率设置过低或捕获线程sleep时间过长。2. JPEG编码耗时太长分辨率/质量太高。3. 网络带宽不足尤其是Wi-Fi。1. 减少time.sleep的值或移除它以最大速度抓帧注意CPU占用。2.首要措施降低分辨率。将set(CAP_PROP_FRAME_WIDTH/HEIGHT)设为640x480或更低。3. 降低JPEG质量参数如从85降到75。4. 将电脑和观看设备连接到5GHz Wi-Fi或使用网线。延迟好几秒钟1. 缓冲区堆积。可能是生成器yield速度慢于捕获速度导致帧堆积在缓冲区。2. 网络路由问题公网访问时。1. 检查代码中是否有全局帧缓冲区。确保生成器每次只取最新的一帧而不是处理队列中的所有历史帧。可以使用一个双缓冲或直接覆盖最新帧的机制。2. 对于公网访问延迟是固有的。优化本地编码和选择更低延迟的内网穿透方案可能有所改善。调试技巧在生成器函数generate_frames内部加入简单的帧计数和时间戳打印可以直观看出帧的生产和消费速度是否匹配。例如每秒打印一次已发送的帧数。6.3 内存泄漏与进程管理长时间运行后Python进程内存持续增长。可能原因OpenCV或Flask有未释放的资源全局变量或缓存不当积累。排查使用psutil库定期打印内存使用。重点检查在循环中是否不断创建新的对象如新的cv2.VideoCapture实例、大的列表等。解决确保cv2.VideoCapture.release()在程序退出时被调用可以使用atexit注册或在异常处理中调用。对于长时间运行的服务使用Gunicorn等WSGI服务器并设置合理的max_requests和max_requests_jitter参数让工作进程在处理一定数量的请求后优雅重启释放可能积累的内存碎片。定期重启服务。这是最简单粗暴但有效的方法可以写一个定时任务cron每天重启一次服务。6.4 在多摄像头或高并发场景下的稳定性当有多个浏览器同时观看或者同时处理多个摄像头时服务可能变慢或崩溃。瓶颈分析每个/video_feed请求都是一个独立的长连接会独立调用生成器函数。如果生成器函数里包含cv2.imencode这样的CPU密集型操作并发数一高CPU就会打满。优化思路共享编码结果这是最有效的优化。让一个独立的“编码线程”负责将最新的原始帧编码成JPEG字节流并将结果存入一个全局变量。所有/video_feed请求的生成器都直接yield这个共享的JPEG字节流。这样无论有多少个客户端编码只做一次。但要注意线程安全加锁。使用消息队列更复杂的架构是使用Redis等作为消息队列。捕获线程将帧发布到频道每个需要视频流的客户端Flask worker订阅这个频道。这能更好地解耦和分布式部署但引入了新的组件和复杂度。横向扩展对于超大规模需求可能需要将视频采集、编码、流媒体服务拆分成独立的微服务但这已经完全超出这个轻量级项目的范畴了。个人体会mehmetkahya0/local-web-camera这个项目或这个思路的精髓在于“够用就好”。它用最小的代价解决了“本地摄像头网络化”这个核心需求。在绝大多数个人或小规模场景下按照本文的优化建议降分辨率、用生产服务器、注意安全它都能稳定可靠地工作。当你需要更低延迟、更高并发、更省带宽时才是考虑转向Nginx-rtmp-module、Mediamtx、或者商业流媒体服务器的时候。这个项目是一个完美的起点和原型工具它让你理解了视频流的基础并能够快速验证想法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2590281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…