news 2026/10/2 8:35:27

yolov13手机使用检测:数据集、模型训练与PyQt5实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
yolov13手机使用检测:数据集、模型训练与PyQt5实现

简介:面向手机使用检测与行为分析研究的YOLOv13-PyQt5完整方案包,适合目标检测初学者、行为研究相关开发人员以及需要可视化演示的学生使用。包内包含标注好的目标检测数据集,提供yolo格式txt标签与voc格式xml标签,已按train、val、test划分并附data.yaml,可直接用于yolov5/v8/v9/v10/v11/v12等主流YOLO系列模型训练;同时打包训练好的模型和PyQt5可视化界面,便于直接观察检测结果、分析手机使用习惯。资源共2000个文件,以1980个txt标注文件为主,辅以18个md说明文档、1个yaml配置和1个pdf资料,压缩包大小约345.16MB。已有35人学习,适合结合附带教程快速上手,完成从数据准备、模型训练到界面展示的完整流程。

1. yolov13手机使用检测:数据集、训练好的模型、PyQt5可视化界面到底是什么

楼上楼下两个人同时开会,楼上在用手机刷短视频,楼下以为对方在认真看报表——这种误判,就是"手机使用检测"要解决的问题。标题里这个带数据集、训练好的模型、PyQt5可视化界面的打包项目,本质是一套完整的解决方案:用目标检测模型识别画面里的人体、手机、手部,再靠界面程序把"谁在什么时间玩了多久手机"记录成可分析的行为报告。它既不是论文里的算法demo,也不是单纯的界面皮肤,而是把标注、训练、推理、可视化四件事串成了一条流水线。

适合谁用也很明确:做行为分析相关毕设的学生、做工作室或自习室监督软件的人、想给家里老人或孩子做手机使用提醒的开发者。你把模型和界面拆出来,换个场景就能迁移到吸烟检测、离岗检测、宠物看护这些同构任务上。后面所有内容都围绕这个打包项目的三块资产展开:数据集怎么构建、模型怎么训练到能用、PyQt5界面怎么把结果变成人看得懂的使用习惯研究数据。

2. 检测模型与数据集:不是随便找个模型就能检测手机,先解决"检测什么"的问题

2.1 为什么手机使用检测选yolo系方案而不是传统检测网络

做手机使用检测,第一步不是写界面,而是选定检测方案。传统做法里Faster R-CNN这类两阶段模型精度出色,但在实时视频流上帧率很难撑住;SSD虽然快,小目标召回率又不够。手机在监控画面里往往只占几十个像素,而且是斜着握在手里的,角度多变、容易被遮挡。yolo系模型(从yolov5训练自己的数据集开始,到v8、v9、v11,再到标题里的yolov13,都是同一套one-stage思路)在速度和精度之间给了更好的平衡。

具体到"yolov13"这个叫法,大概率是社区fork的后续迭代版本,或者某个集成包里的自定义命名。不用纠结版本号本身,因为训练和部署的入口都是ultralytics接口,加载权重、推理、导出onnx的代码几乎一致。这套方案检测三类目标就够了:手机、人手、人脸。人手和人脸的框不是最终目的,它们是辅助逻辑——判断手机是否被"正在使用"需要结合手与手机的相对位置,以及人脸是否正对屏幕。

提示:如果只是在室内固定摄像头场景做检测,不用追求大模型。yolo系n/s级别的权重在CPU上也能跑到15-25帧,足够行为分析使用。

2.2 从零攒手机检测数据集:labelme标注、类别定义与json转txt脚本

数据集是这套方案里最花时间的部分。常见做法是先自己录视频抽帧,或者把公开数据集里的手机、人手、人脸类别抽出来合并。标注工具选labelme或labelImg都行,但注意——网上很多教程一上来就装labelImg,它在某些Python版本下会触发pyqt5缺失或版本冲突,这也是热词里"labelme 无法安装 pyqt5"经常被搜的原因。其实labelme对pyqt5的依赖是显式声明的,装不上通常是pip源里pyqt5版本和Python版本不匹配。

标注时类别名我建议用固定小写英文:phone、hand、face。不要用中文标签,后面转YOLO格式和训练时utf-8编码问题会非常折磨人。每张图上手机可能很小,标注时要把框贴着手机边缘,宁多框一圈别少框,因为模型对边界框的回归本身就有误差。

标注完的labelme文件是json格式,polygon或rectangle标记。YOLO训练需要的是txt格式归一化坐标,所以需要一个转换脚本。这里给一份我常用的转换代码:

import json import os from tqdm import tqdm # 类别映射,顺序固定,之后data.yaml里按这个顺序写 CLASS_MAP = {"phone": 0, "hand": 1, "face": 2} def convert_labelme_json(json_path, out_txt_path, img_w, img_h): with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) lines = [] for shape in data["shapes"]: label = shape["label"] if label not in CLASS_MAP: continue points = shape["points"] # labelme矩形是两点对角坐标 x1, y1 = points[0] x2, y2 = points[1] # 归一化到0~1 cx = ((x1 + x2) / 2) / img_w cy = ((y1 + y2) / 2) / img_h w = abs(x2 - x1) / img_w h = abs(y2 - y1) / img_h # 防止边界溢出,YOLO要求值在(0,1)范围内 cx = min(max(cx, 0.0), 1.0) cy = min(max(cy, 0.0), 1.0) w = min(w, 1.0) h = min(h, 1.0) lines.append(f"{CLASS_MAP[label]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") with open(out_txt_path, "w", encoding="utf-8") as f: f.write("\n".join(lines)) # 批量转换:假定jpg和json同名 img_dir = "dataset/images_annotated" out_dir = "dataset/labels" os.makedirs(out_dir, exist_ok=True) for json_name in tqdm(os.listdir(img_dir)): if not json_name.endswith(".json"): continue img_name = json_name.replace(".json", ".jpg") img_path = os.path.join(img_dir, img_name) if not os.path.exists(img_path): continue # 读取图片尺寸 from PIL import Image img = Image.open(img_path) w, h = img.size convert_labelme_json( os.path.join(img_dir, json_name), os.path.join(out_dir, json_name.replace(".json", ".txt")), w, h ) img.close()

脚本逻辑分四步:读json、按CLASS_MAP过滤类别、把两点对角坐标换成归一化的中心点宽高、写txt。参数上最需要注意的是img_w和img_h,它必须来自原图实际尺寸,如果图片被resize过但json里坐标没同步改,转换结果会全偏。我在第一次转coco2017数据集结构改过来的数据时就吃过这个亏,表格里看起来坐标都正常,训练loss死活不降。

2.3 数据集划分与类别不平衡:不是所有帧都算有效数据

标注完成后,还要解决三个常见问题。

第一是划分。按照train/val 9:1或8:2的比例随机打乱,注意同一段视频抽出来的帧要尽量归到同一个集合里,否则训练集和验证集画面太像,验证指标虚高。做法是抽帧时按视频名分组,以组为单位划分,不要单帧随机分配。

第二是类别不平衡。手机使用检测场景里,face出现的频率远高于phone,因为人脸始终可见,而手机可能只在低头时才入画。如果训练后发现phone这一类精度明显低,优先做两件事:给phone类多补样本,或者在loss里给类别加权重。yolo的cls_loss里可以按instance数量逆向加权,这个参数在ultralytics里通过class_weights传入,虽然默认不开启,但值得一试。

第三是无效样本清理。画面里手插兜但没拿手机、人脸转头但没看屏幕,这些样本如果全标成hand、face,模型会把"存在手"和"存在人"学得很强,却学不到"手机正在被使用"这个关键状态。手机使用检测真正要的是行为,不是静态存在。所以标注时我建议额外加一个规则:手在身体两侧垂着、或者手机在桌面上,这两个case要么不标phone,要么同时加一个context标签让模型学会区分。

3. 用yolo训练自己的数据集:目录结构、训练命令与模型验证

3.1 训练前的目录结构:images和labels必须严格对齐

标题里的zip包如果直接解压训练,你第一眼要检查的就是目录结构。yolo系训练(不管yolov13还是更早版本)读取数据的方式固定:一个data.yaml指定训练集、验证集路径和类别名,然后训练脚本按images和labels两个平行目录去找对应文件。结构一般是:

dataset/ images/ train/ 0001.jpg 0002.jpg val/ 0003.jpg labels/ train/ 0001.txt 0002.txt val/ 0003.txt

data.yaml写法如下:

# data.yaml path: dataset train: images/train val: images/val nc: 3 names: ["phone", "hand", "face"]

几个容易踩坑的点:train和val写的是相对path的子路径,不要写绝对路径,否则换机器训练要改一堆配置。nc必须和CLASS_MAP的长度一致,names顺序必须和转换脚本里的CLASS_MAP键顺序一致。很多"训练出来loss正常但预测类别全错"的案件,最后查出来是names顺序和标注txt里的索引对不上。

images和labels的"对齐"还有一层含义:每张图片必须有同名txt,哪怕txt是空文件。如果某张图没有任何目标,但少了一个txt,训练时会报警告甚至把这张图跳过,数量多了会明显影响epoch的收敛判断。我习惯在转换脚本最后扫一遍images目录,给缺失的txt写一个空文件。

3.2 训练命令与关键参数:从yolov5到yolov13共用的调参经验

训练本身不需要写复杂脚本,ultralytics库一行命令的事。标题里的yolov13既然走的是ultralytics接口,命令基本长这样:

yolo train model=yolo11n.pt data=data.yaml \ epochs=100 imgsz=640 batch=16 device=0 \ project=runs/name=phone_use

参数说明:

  • model:预训练权重路径。yolo11n.pt是官方COCO预训练权重,迁移到手机检测上收敛速度快很多;不要从随机初始化开始训,6000张数据也能训,但前期loss下降会慢到让人怀疑人生。
  • imgsz:输入尺寸。640是默认值,手机是中小目标,不建议降到320,降到320会丢小手机框。
  • batch:看显存定。16G显存跑yolo11s可以开到32,跑l版本就只能16。如果显存溢出,优先降batch而不是降imgsz,因为imgsz影响检测精度更明显。
  • device:0是GPU,CPU训练能跑但非常煎熬,不建议。
  • project和name:产物输出路径,runs/phone_use,weights就在这下面。

这里顺带回答一个热门问题——yolov13训练和yolov5训练自己的数据集在流程上有区别吗?答案是没有本质区别,yolov5时代还要手动改yaml文件、py文件,ultralytics统一后只需一个配置文件和一个命令。所以网上搜到的老教程里那套"数据集放哪、怎么改nc"的流程,放到现在的v13上完全适用,只是命令更精简了。

训练过程中的监控点有两个:一个是训练集loss是否持续下降,另一个是验证集mAP50和mAP50-95的曲线。如果mAP50已经到0.9但mAP50-95只有0.5,说明框的定位精度不够,这时候不要急着加数据,先检查标注框边缘是否贴合、有没有大量框比目标大半圈的情况。手机检测对IoU要求高,因为后面界面里要根据手和手机框的IoU判断"是否手持",框偏了这层逻辑就全错。

3.3 训练产物怎么用:best.pt、混淆矩阵与导出onnx

训练跑完,产物都在runs/phone_use/weights/下面。优先使用best.pt而不是last.pt,last.pt是最后一个epoch的权重,可能过拟合;best.pt是验证集指标最优的保存点。压缩包里说的"训练好的模型",实际就是指这个best.pt。

拿到best.pt先别急部署,先看两样东西:混淆矩阵和验证集的预测效果图。混淆矩阵在runs/phone_use/confusion_matrix.png,重点看phone这一行的对角值。如果phone容易被预测成hand,说明两类特征太像——画面里手机经常被手挡住一半,模型只能看到手。此时可以考虑合并成一个大类"phone_in_hand",或者增加遮挡样本,而不是继续调参。

界面程序要跑实时检测,pt格式在CPU上效率一般,建议导出成onnx再上生产:

yolo export model=runs/phone_use/weights/best.pt format=onnx imgsz=640

导出后得到best.onnx,PyQt5界面里用onnxruntime加载它做推理,比torch直接用省内存、启动快。导出命令里imgsz要和训练时一致,否则输入尺寸变了输出张量解析会出问题。

注意:onnx导出后一定要检查输出维度,yolo系输出是1xNx(5+nc)的二维矩阵,N是预测框数量,不是三维。常见翻车是用老代码按三维解析onnx输出,结果NMS出来全是空框。

4. PyQt5可视化界面:检测线程、绘制框与使用习惯统计

4.1 架构先定:QThread跑检测,主线程管界面,别让画面冻结

PyQt5可视化界面的核心不是"有什么控件",而是"检测放在哪个线程"。新手最容易犯的错误是在界面主循环里一帧帧调模型推理,结果是一边拖动窗口一边卡死。PyQt5的事件循环和模型推理的for循环互相抢时间,界面会假死。

正确架构是三段式:QThread子线程读视频帧并推理、通过Signal把检测结果emit到主线程、主线程里QLabel更新画面并绘制框。下面给一个最小可跑的骨架,以手机检测为例:

# detector_thread.py import cv2 import numpy as np import onnxruntime as ort from PyQt5.QtCore import QThread, pyqtSignal class DetectThread(QThread): # 信号:原始帧、框坐标、类别、置信度 frame_ready = pyqtSignal(np.ndarray, list, list, list) def __init__(self, onnx_path, source=0): super().__init__() self.session = ort.InferenceSession(onnx_path, providers=["CPUExecutionProvider"]) self.cap = cv2.VideoCapture(source) # source可以是摄像头或视频文件路径 self.running = True self.input_w = 640 self.input_h = 640 def preprocess(self, frame): # 等比例缩放,填充灰色边,避免拉伸变形 img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w = img.shape[:2] scale = min(self.input_w / w, self.input_h / h) new_w, new_h = int(w * scale), int(h * scale) resized = cv2.resize(img, (new_w, new_h)) canvas = np.full((self.input_h, self.input_w, 3), 114, dtype=np.uint8) canvas[:new_h, :new_w] = resized # 归一化并转NCHW x = canvas.astype(np.float32) / 255.0 x = np.transpose(x, (2, 0, 1))[None, ...] return x, scale, new_w, new_h def run(self): while self.running: ret, frame = self.cap.read() if not ret: break x, scale, nw, nh = self.preprocess(frame) outputs = self.session.run(None, {self.session.get_inputs()[0].name: x}) # outputs[0] shape: (1, 5+nc, 8400),需要转置用 boxes, scores, class_ids = self.postprocess(outputs[0], scale) self.frame_ready.emit(frame.copy(), boxes, scores, class_ids) def stop(self): self.running = False self.wait()

后处理NMS那段代码长度较大,生产代码里我一般复用ultralytics的ops模块,这里不展开,但逻辑说明两点:一是onnx输出的中心点坐标要按letterbox的scale回映射到原图尺寸,二是置信度阈值先设0.4、NMS的IoU阈值设0.5,这两参数直接影响画框数量,放低了满屏框,放高了漏检。

这份骨架在PyQt5界面设计里属于标准写法。pycharm里调试时如果遇到numpy数组跨线程emit崩溃,多半是环境变量没设置,在app启动前加上os.environ["QT_QPA_PLATFORM"] = "xcb"或根据系统改对应值,Linux下这种问题最常见。

4.2 主界面代码骨架:QLabel画框、表格记录、状态联动

主窗口不需要花哨。我常用的控件组合是:一个QLabel显示视频、一个QTableWidget记录每次"拿起手机"的起止时间、一个QTextBrowser显示统计报告。以下是主线程接收检测信号并画框的部分:

# main_window.py from PyQt5.QtWidgets import QMainWindow, QLabel, QTableWidget from PyQt5.QtGui import QImage, QPainter, QPen, QColor from detector_thread import DetectThread class MainWindow(QMainWindow): def __init__(self): super().__init__() self.video_label = QLabel(self) self.table = QTableWidget(self) self.thread = DetectThread("best.onnx", source=0) self.thread.frame_ready.connect(self.update_frame) def update_frame(self, frame, boxes, scores, class_ids): # 在副本上画框,避免改到原始帧 disp = frame.copy() for box, score, cls in zip(boxes, scores, class_ids): x1, y1, x2, y2 = [int(v) for v in box] color = (0, 255, 0) if cls == 0 else (0, 0, 255) # phone绿,其他红 cv2.rectangle(disp, (x1, y1), (x2, y2), color, 2) cv2.putText(disp, f"{score:.2f}", (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 1) # 转成QImage显示 rgb = cv2.cvtColor(disp, cv2.COLOR_BGR2RGB) h, w, ch = rgb.shape qimg = QImage(rgb.data, w, h, ch*w, QImage.Format_RGB888).copy() self.video_label.setPixmap(QPixmap.fromImage(qimg))

这里有个关键细节:frame传到主线程后必须copy,否则QImage引用的是子线程内存地址,主线程重绘时子线程可能已经写了新数据,画面会出现撕裂或绿条。这个血泪经验是当初在PyQt5显示html和视频流同时刷新时踩到的。另一个参数是QImage的bytesPerLine必须等于ch*w,很多教程写成w,三通道时显示颜色错乱,排查半天。

行为记录逻辑这样接:当phone框出现且与hand框的IoU大于0.3,判定为"正在使用手机",在表格里记一条开始时间;连续N帧(比如10帧)都没检测到该状态,就记结束时间。这样表格里就有了"使用时段"的数据,后续统计全靠它。

4.3 从检测框到使用习惯研究:时长、频次、时段分布

标题里"行为分析和使用习惯研究"这个落点,靠的是把检测结果变成指标,而不是停留在画框。三个最基础的指标:

一是使用总时长。每次"phone+hand+face"三个框同时存在且面积比例合理,算一次有效使用,累加所有session时长。二是使用频次。一天内触发"拿起手机"事件的次数,这个数比时长更敏感,因为很多人是几分钟看一眼手机,单次时长短但频次高。三是时段分布。按小时统计使用时长,画出柱状图,能直接看出晚上20点到23点是高峰。

这些指标在PyQt5里用QChart或matplotlib都能画。我建议导出HTML报告而不是截图——用QTextBrowser加载一个自生成的HTML文件,里面嵌图表和表格,叫"日报"或"周报"。这样用户能保存、能打印,也更像一套研究工具而不是demo。

5. 手机检测与PyQt5可视化避坑:安装失败、线程崩溃、坐标错乱排查记录

5.1 现象:labelme或labelImg装不上,提示pyqt5缺失或版本冲突

原因:labelme在Python3.10以上版本容易与pyqt5的wheels不匹配,pycharm环境里更容易复现,因为pycharm可能已经装过不同版本的Qt绑定库,出现PyQt5和PySide6共存冲突。

解决:先统一环境。建一个干净的conda虚拟环境指定Python3.9,然后按顺序装:pip install pyqt5==5.15.9再装labelme,或者直接用pip install labelme[pyqt5]一条命令带出依赖。装完后在终端跑labelme,能弹窗说明pyqt5正常。若提示找不到Qt platform插件,多半是PyQt5安装不完整,重装一次比手动改环境变量省心。如果项目里同时有PySide2,卸载掉一个,两套Qt绑定在同一进程里必冲突。

5.2 现象:界面运行几秒后卡死,窗口拖动时白屏

原因:典型的检测推理写在主线程。onnxruntime的session.run在CPU上单帧要50-100毫秒,主线程被占住后Qt事件循环无法处理重绘消息,表现为"画面卡在最后一帧、窗口无响应"。

解决:检测挪到QThread,主线程只负责收信号和重绘。注意QThread里不要直接操作任何QWidget,连self.video_label.setText都不行,必须通过信号把数据传回主线程。另外QThread的stop不要用terminate,要设置running标志位并wait超时,强制杀掉线程会导致onnxruntime的session句柄泄漏,第二次启动检测时直接崩溃。

5.3 现象:训练和推理都正常,但画出来的框偏半个身位

原因:letterbox预处理与原图坐标没有正确反算。检测模型输入是640x640的填充图,输出坐标是填充图坐标系,直接映射到原始视频帧就会整体偏移。填充的灰色区域越大偏移越明显,在竖屏手机画面上尤其明显。

解决:记录预处理时的scale和pad偏移量,后处理时先减pad再除scale。上面4.1代码里用scale和new_w、new_h就是为了这个。一个校验方法:拿一张标注过的原图,把检测结果画上去,如果框中心和标注中心误差超过5%,重点查letterbox的pad方向,OpenCV的resize配合copyMakeBorder时左上右下填充量要分别记录。

5.4 现象:推理速度很快,但识别结果全是"hand",手机框一个都没有

原因:训练集类别不平衡的典型表现。标注时手部特征太明显,手机特征被手部遮挡淹没;或者验证集里大量画面是手拿手机靠近镜头,训练时模型学会了用手代替手机。

解决:先看混淆矩阵确认。确认hand确实吃掉phone后,针对phone类重新采集样本:手机平放桌面、手机在裤兜、手机在通话耳边等边缘case都要补。如果没时间补数据,退而求其次在业务逻辑上绕开——界面判定"使用手机"时要求hand和phone同时出现,这样即使phone漏检,也不会把单纯抬手误判成用手机。这类问题属于数据问题,不是模型结构问题,调超参数没有用。

5.5 现象:程序启动时报"cuda error: out of memory",或首次推理极慢

原因:onnxruntime的CPU provider加载时默认优化级别较高,首次推理要做图优化,耗时可能几十秒;cuda out of memory则是因为同时加载了torch的权重和onnx两个模型。

解决:界面程序里只保留一种推理引擎,能用onnx就不加载torch。onnxruntime设置optimization_level=ORT_ENABLE_ALL并让session的线程数等于CPU物理核心数,首次推理会显著加快。带GPU的机器上,优先用CUDAExecutionProvider,但要注意显存小的显卡上CUDA和CPU两个provider串行加载也可能OOM,指定单provider即可。启动时加一段print日志输出实际用的provider,排查"为什么我的程序比别人的慢一倍"这类问题最快。

6. 进阶技巧:把检测结果做成时段热力图,并用真实使用日志验证精度

检测模型跑通、界面能画框之后,这个项目就从"监控工具"进化成"研究工具"了。一个很实用的进阶做法是生成"全天使用热力图"——横轴是24小时,纵轴是星期几,格子里填充颜色深浅代表该时段手机使用时长。热力图比柱状图直观的地方在于它能一眼看出周末和周三的晚高峰差异,这恰好是使用习惯研究里最有价值的信息。

生成方式不复杂:把4.3里记录的session数据存成csv,列名用start_time、end_time、duration_sec。用pandas按小时分桶累加,得到二维矩阵,再用matplotlib的imshow画出来,最后嵌入到QTextBrowser加载的HTML报告里。PyQt5显示html这件事本身不难,把html字符串直接塞给QTextBrowser的setHtml即可,注意带<!DOCTYPE html>完整结构,只传片段会导致样式丢失。

验证精度这件事我建议做成"人工日志对比法":让受试者在当天手写记录每次拿起手机的时刻,晚上拿记录和系统统计结果对拍。核心指标看两个——漏检率和误检占比,而不是mAP。mAP是模型层面的指标,用户不关心;用户关心的是"我说我只玩了三次手机,你统计出六次"这种体验。这个方法能帮你暴露一个模型指标看不出来的问题:检测框在抖动,导致同一次使用被切成了多个短session。解决办法是在行为判定里加最小session时长阈值,比如单次使用低于10秒的不计入使用频次,防止页面滑动时的瞬时手影干扰。

最后说一个我自己的习惯:做这类行为分析项目,一定要在界面第一屏加一个"系统时间校准"按钮。检测到的使用时长依赖视频帧时间戳,如果摄像头和系统时间不一致,所有时段分布图都是错的。我做过一次连续三天的记录,热力图每天的高峰时段漂移一小时,排查半天发现是摄像头内置时钟快了55分钟。从那以后我把设备时钟同步作为启动检测的第一步。希望这些从数据到界面的经验帮你在做yolov13手机使用检测项目时少走几步弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 8:33:24

C#与西门子S7-200 Smart以太网通讯源码解析:从报文构造到稳定采集

简介&#xff1a;这份资源是面向工业自动化开发者与上位机编程学习者的西门子S7-200Smart通讯C#源码项目&#xff0c;围绕PLC与上位机之间的数据交互展开&#xff0c;适合已具备一定C#基础、希望掌握PLC通讯原理与读写实现的中级开发者参考。压缩包共74个文件&#xff0c;约1.4…

作者头像 李华
网站建设 2026/10/2 8:32:10

CNN图像风格迁移毕设实战:VGG16与PyTorch从训练到部署

简介&#xff1a;一套面向毕业设计场景的CNN图像风格迁移完整项目&#xff0c;基于PyTorch实现&#xff0c;提供Python源码、预训练模型与操作说明&#xff0c;适用于计算机、人工智能、自动化等专业学生进行毕设或课程设计参考。包内共93个文件&#xff0c;涵盖9个Python脚本&…

作者头像 李华
网站建设 2026/10/2 8:31:53

佛山短途货运物流运输,4.2米厢式车同城配送,工厂物料仓到仓准时达

随着广东制造业与家居产业的持续发展&#xff0c;佛山作为全国知名的家具产业集群核心&#xff0c;短途货运物流运输的需求正在持续攀升。一方面&#xff0c;工厂物料调拨、门店补货、仓对仓转运、终端配送的频次不断增加&#xff0c;企业对于配送时效、货物安全、服务透明度的…

作者头像 李华
网站建设 2026/10/2 8:31:34

彻底清除Synares木马:伪装Synaptics.exe病毒手动清理实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 8:31:03

实测分享:AI Agent回归的裁判费从28美元降到3毛4,判得还更准了

实测分享&#xff1a;AI Agent回归的裁判费从28美元降到3毛4&#xff0c;判得还更准了背景我们团队给业务系统上了个测试Agent&#xff0c;最头疼的不是让它跑&#xff0c;而是跑完之后"判分"。规则断言只能查确定性的东西&#xff08;返回码、字段存在性&#xff09…

作者头像 李华
网站建设 2026/10/2 8:30:46

矿用新型材料生产商哪家好?飞翼股份源头厂家实力参考

矿用新型材料生产商哪家好?飞翼股份源头厂家实力参考 一、矿用充填材料选购的4大踩坑难题作为矿山开采核心配套材料&#xff0c;矿用充填材料的选择直接关系到生产安全、资源回收率与运营成本&#xff0c;不少矿企在采购时都曾遇到各类棘手问题&#xff0c;最常见的踩坑场景主…

作者头像 李华