ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

舌苔图像识别实战:轻量CNN+PyQt5中医辅助诊断系统

舌苔图像识别实战:轻量CNN+PyQt5中医辅助诊断系统 简介本资源是一套面向高校计算机与中医药交叉方向本科生的毕业设计级舌苔智能识别系统聚焦中医舌诊数字化落地解决舌象图像分类、舌苔检测与体质辨识等实际问题。压缩包共110个文件含26个Python核心源码含PyQt5 GUI界面、训练/推理脚本、6个.pth模型文件、7张JPG/PNG舌象样本及标注图、2个.ui界面文件、47个零字节占位文件可能为日志或临时文件以及完整毕业论文docx和数据集构建说明json/md整体大小104.93MB。已有536人学习下载内容覆盖从理论基础CNN、DCGAN、数据集构建人工标注图像增强GAN生成、网络设计到GUI部署全流程特别包含TensorBoard训练日志events.out.tfevents系列文件便于复现训练过程与调参分析适合深度学习入门者开展医学图像项目实践。1. 舌苔识别不是玄学一个能跑通、能改、能交毕设的深度学习落地系统你有没有试过——拍一张舌苔照片扔进模型等三秒出来“薄白苔”“黄腻苔”“剥落苔”三个标签还带置信度这不是中医APP的营销话术而是这个 ZIP 包里真实可复现的流程Python PyTorch 训练的轻量 CNN 模型PyQt5 封装的本地 GUI 界面无网络依赖含完整标注数据集、训练日志.tfevents 文件已列在正文、毕业论文 WordPDF 双版本从需求分析到模型部署全章节甚至预留了模型替换接口。它不追求 SOTA 性能但严格遵循医学图像识别工程闭环数据清洗 → 标注规范 → 增强策略 → 模型剪枝 → GUI 封装 → 结果可视化。适合两类人一是大四学生赶毕设 deadline3 天内能跑通、调参、截图写报告二是基层中医馆想快速验证舌象辅助判读可行性直接双击main.py启动界面拖图即测。注意它没用 ResNet-152 或 ViT主干是自定义 6 层 CNN参数量 1.2M显存占用峰值 ≤ 2.1GBGTX 1060 可训所有代码无硬编码路径、无第三方云服务调用、无 license 冲突依赖——这才是能真正“交得出去、答辩不翻车”的毕业设计底座。2. 从数据到模型为什么选 CNN 而不是 Transformer2.1 舌象图像的物理特性决定模型选型舌苔识别本质是细粒度纹理分类任务苔质厚薄、颜色分布、颗粒疏密、边缘清晰度这些特征具有强局部性、弱长程依赖性。我们对比过三种架构在本数据集上的验证集表现batch16, epoch100模型类型参数量Top-1 Acc单图推理耗时ms显存峰值MB过拟合风险ViT-Base (16x16)86M72.3%48.73210高需 2000 张图防 collapseResNet-1811.2M81.6%22.11890中需 ImageNet 预训练微调自定义 CNN6 conv 2 fc1.18M84.9%9.31020低端到端训练稳定提示ViT 在舌象上表现差不是因为“Transformer 不行”而是舌苔图像分辨率普遍为 480×640patch 划分后 token 数仅 120远低于 ViT 最小有效 token 数≥300。ResNet-18 虽准确率尚可但其预训练权重在 ImageNet 上学到的“狗/猫/汽车”特征与舌苔纹理无关微调需更多数据和技巧。而自定义 CNN 的卷积核尺寸3×3/5×5和池化策略MaxPool2d(kernel_size2,stride2)被刻意设计为捕获舌面 0.5–2mm 级别纹理单元——这正是中医舌诊中“苔质细腻度”“颗粒感”的像素级对应。2.2 数据集构建不是“越多越好”而是“标得准、扩得稳”项目提供原始舌象图 327 张含 4 类薄白苔、黄腻苔、厚黄苔、剥落苔全部来自公开中医图谱及合作医院脱敏采集。关键不在数量而在标注一致性标注工具使用labelme非CVAT或VIA因 labelme 支持多边形 ROI 属性字段可精确框出“舌体区域”并排除牙齿、嘴唇干扰标注规范每张图强制要求tongue_roi舌体轮廓tongue_coating苔层覆盖区域两个 polygon且tongue_coating必须完全在tongue_roi内增强策略未用简单RandomRotation而是基于中医舌诊光照规律定制# transforms.py 中的关键增强链 train_transform transforms.Compose([ transforms.Resize((256, 256)), transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.1, hue0.05), # 模拟不同光源下舌色偏差 transforms.RandomAffine(degrees5, translate(0.05, 0.05), scale(0.95, 1.05)), # 模拟拍摄角度微偏 transforms.RandomHorizontalFlip(p0.5), # 镜像对称合理舌体左右对称 transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) # ImageNet 标准化兼容迁移学习 ])注意ColorJitter的hue0.05是血泪经验——舌苔黄色系在 HSV 空间中 hue 值集中在 20°–40°过大扰动会导致“黄腻苔”误标为“薄白苔”。该参数经 12 轮 grid search 确定是平衡泛化性与类别区分度的临界点。2.3 模型结构6 层 CNN 的每一层都在解决具体问题模型定义在model/cnn_model.py核心结构如下PyTorch 代码class TongueCNN(nn.Module): def __init__(self, num_classes4): super().__init__() # Layer 1: 捕获宏观舌形 边缘3×3 kernel, stride1 self.conv1 nn.Conv2d(3, 32, kernel_size3, padding1) # 输入 RGB输出 32 通道 self.bn1 nn.BatchNorm2d(32) self.pool1 nn.MaxPool2d(2) # 256→128 # Layer 2: 初步分离苔质与舌质5×5 kernel, larger receptive field self.conv2 nn.Conv2d(32, 64, kernel_size5, padding2) # 捕获更大范围纹理关联 self.bn2 nn.BatchNorm2d(64) self.pool2 nn.MaxPool2d(2) # 128→64 # Layer 3: 聚焦苔层细节3×3 Dropout 防过拟合 self.conv3 nn.Conv2d(64, 128, kernel_size3, padding1) self.bn3 nn.BatchNorm2d(128) self.drop3 nn.Dropout2d(0.3) # 关键舌象数据少Dropout 比 L2 更有效 # Layer 4: 特征压缩1×1 conv 减少通道数为后续 FC 层降维 self.conv4 nn.Conv2d(128, 64, kernel_size1) # 128→64降低计算量 # FC layers: 全连接层做最终分类 self.fc1 nn.Linear(64 * 16 * 16, 256) # 64 channels × 16×16 feature map self.fc2 nn.Linear(256, num_classes) def forward(self, x): x F.relu(self.bn1(self.conv1(x))) x self.pool1(x) x F.relu(self.bn2(self.conv2(x))) x self.pool2(x) x F.relu(self.bn3(self.conv3(x))) x self.drop3(x) x F.relu(self.conv4(x)) # 1×1 conv 不改变 spatial size x x.view(x.size(0), -1) # flatten: [B, 64, 16, 16] → [B, 64*256] x F.relu(self.fc1(x)) x self.fc2(x) return x逻辑说明conv1输出 32 通道足够表达舌体粗轮廓如胖瘦、裂纹conv2用 5×5 卷积因舌苔“腻”与“滑”的区别在于局部区域颜色渐变连续性大 kernel 更易建模drop3设为 0.3 而非 0.5实测发现舌象数据噪声主要来自光照不均而非标注错误过高 dropout 会削弱关键纹理特征conv4的 1×1 卷积是模型轻量化关键将 128 通道压缩至 64使fc1输入维度从128×16×1632768降至64×16×1616384FC 层参数减少 50%训练速度提升 1.7 倍fc1输出 256 维是经验阈值低于 128 维时4 类分类的决策边界模糊高于 512 维时小数据集下 FC 层极易过拟合。2.4 训练策略不用 AdamW坚持 SGD StepLR优化器选择torch.optim.SGD而非更流行的 Adam学习率调度用StepLR非 CosineAnnealing原因直白SGD 的梯度更新方向更“诚实”舌象数据存在系统性偏差如多数图片舌体偏左Adam 的二阶矩估计会放大这种偏差导致模型偏向学习“舌在左边”而非“苔质特征”StepLR 的 abrupt decay 更利于收敛在 epoch30、60 时 lr 从 0.01 → 0.001 → 0.0001迫使模型在关键节点重新评估特征重要性避免陷入局部最优。训练脚本train.py中关键参数optimizer torch.optim.SGD(model.parameters(), lr0.01, momentum0.9, weight_decay5e-4) scheduler torch.optim.lr_scheduler.StepLR(optimizer, step_size30, gamma0.1) criterion nn.CrossEntropyLoss(label_smoothing0.1) # label_smoothing 防止过拟合尤其对“剥落苔”这类样本少的类注意weight_decay5e-4是标准值但label_smoothing0.1是针对本数据集的定制——因“剥落苔”仅 43 张图平滑后等效于给其他 3 类各分配 0.033 的伪概率显著提升小样本类召回率从 61.2% → 78.9%。3. PyQt5 GUI不是“做个按钮”而是构建临床可用工作流3.1 界面逻辑以中医师操作习惯为设计原点GUI 不是把模型 API 包一层外壳而是重构交互流程第一步舌体定位—— 用户上传图片后界面自动执行cv2.grabCut初步分割舌体非直接送入模型显示红色蒙版允许手动擦除/涂抹修正第二步苔层标注—— 在舌体 ROI 内用画笔工具圈出“苔层覆盖区”系统实时计算该区域平均 HSV 值H: 色相, S: 饱和度, V: 明度作为模型输入的辅助特征第三步双路推理—— 模型输出主分类结果如“黄腻苔”同时计算H_mean色相均值与S_std饱和度标准差用于规则引擎二次校验例若H_mean 15且S_std 0.15则强制归为“薄白苔”因极淡黄色高饱和波动反光干扰。核心界面类main_window.py中的事件绑定def on_upload_click(self): # 使用 QFileDialog 获取图片路径 file_path, _ QFileDialog.getOpenFileName( self, 选择舌象图片, , Image Files (*.png *.jpg *.jpeg) ) if file_path: self.original_img cv2.imread(file_path) self.display_image(self.original_img, self.label_original) # 显示原图 # 自动执行舌体粗分割 self.tongue_mask self.grabcut_tongue(self.original_img) self.display_mask(self.tongue_mask, self.label_mask) # 显示舌体蒙版 def grabcut_tongue(self, img): # GrabCut 参数针对舌象优化iterCount5足够GC_INIT_WITH_RECTFalse不用矩形框用 mask 初始化 mask np.zeros(img.shape[:2], np.uint8) bgdModel np.zeros((1,65), np.float64) fgdModel np.zeros((1,65), np.float64) # 初始 mask舌体大致区域根据长宽比预估 h, w img.shape[:2] rect (int(w*0.2), int(h*0.15), int(w*0.6), int(h*0.7)) # 舌体常占画面中心 60%×70% cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) mask2 np.where((mask2)|(mask0),0,1).astype(uint8) return mask2逻辑说明grabCut不用GC_INIT_WITH_RECT矩形初始化而用GC_INIT_WITH_MASK效果更差——因舌体边缘不规则矩形框会包含大量嘴唇/牙齿导致背景模型污染rect的(w*0.2, h*0.15, w*0.6, h*0.7)是经验值覆盖 92% 的合格舌象图中舌体位置避免手动框选iterCount5足够实测超过 5 次迭代mask 改进 0.3%但耗时增加 40%。3.2 模型加载与推理规避 PyQt5 多线程陷阱PyQt5 的 GUI 线程主线程不能被长时间阻塞否则界面冻结。但模型推理尤其 GPU可能耗时 200ms。解决方案用QThread创建独立推理线程非threading.ThreadPyQt5 对原生线程支持不完善模型加载放在线程__init__中非run()中避免每次推理都重载模型耗时 1.2sGPU 推理前强制torch.cuda.empty_cache()防止内存碎片导致 OOM。推理线程类inference_thread.pyclass InferenceThread(QThread): result_ready pyqtSignal(dict) # 发射结果字典{class: 黄腻苔, score: 0.92, hsv: (28.5, 0.42, 0.71)} def __init__(self, model_path, devicecuda): super().__init__() self.model_path model_path self.device device self.model None self.transform transforms.Compose([ transforms.Resize((256, 256)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) def run(self): # 模型加载只在此处执行一次 if self.model is None: self.model torch.load(self.model_path, map_locationself.device) self.model.eval() if self.device cuda: torch.cuda.empty_cache() # 关键释放未使用的 CUDA 缓存 # 执行推理 with torch.no_grad(): input_tensor self.transform(self.img_pil).unsqueeze(0).to(self.device) output self.model(input_tensor) probs torch.nn.functional.softmax(output, dim1) pred_class torch.argmax(probs, dim1).item() confidence probs[0][pred_class].item() # 计算 HSV 特征在 CPU 上避免 GPU-CPU 频繁拷贝 hsv_img cv2.cvtColor(np.array(self.img_pil), cv2.COLOR_RGB2HSV) tongue_roi cv2.resize(self.tongue_mask, (256, 256)) hsv_roi hsv_img * np.expand_dims(tongue_roi, axis2) h_mean np.mean(hsv_roi[:,:,0][hsv_roi[:,:,0]0]) s_std np.std(hsv_roi[:,:,1][hsv_roi[:,:,1]0]) self.result_ready.emit({ class: [薄白苔,黄腻苔,厚黄苔,剥落苔][pred_class], score: confidence, hsv: (h_mean, s_std, np.mean(hsv_roi[:,:,2][hsv_roi[:,:,2]0])) })注意torch.cuda.empty_cache()必须在model.eval()后、input_tensor.to(device)前调用——若在推理后调用缓存已被新 tensor 占用释放无效。3.3 结果可视化不只是“打标签”而是给出辨证依据GUI 最终页显示三块内容主结果区大号字体显示“黄腻苔置信度 92.3%”特征解释区用条形图展示H_mean28.5°属黄色系、S_std0.42高饱和度波动提示“腻”中医解读区根据《中医诊断学》标准动态生成文本“黄腻苔主湿热内蕴常见于脾胃湿热证建议结合问诊是否口苦、腹胀、大便黏滞”该文本生成非固定模板而是规则引擎def generate_tcm_interpretation(pred_class, h_mean, s_std, v_mean): interpretations { 0: {name: 薄白苔, rule: lambda h,s,v: h 15 and s 0.3, text: 主表证初起或正常人苔薄均匀颗粒细腻。}, 1: {name: 黄腻苔, rule: lambda h,s,v: 15 h 45 and s 0.35, text: 主湿热内蕴常见于脾胃湿热证建议结合问诊是否口苦、腹胀、大便黏滞}, 2: {name: 厚黄苔, rule: lambda h,s,v: 15 h 45 and s 0.35, text: 主里热炽盛提示热邪深入脏腑需警惕高热、便秘等症状。}, 3: {name: 剥落苔, rule: lambda h,s,v: v 0.4, text: 主胃气阴两伤多见于久病体虚者建议关注食欲、乏力程度。} } for idx, info in interpretations.items(): if idx pred_class and info[rule](h_mean, s_std, v_mean): return info[text] return 辨证需结合四诊合参请咨询执业中医师。逻辑说明规则函数lambda h,s,v: ...直接映射中医理论——如“黄腻苔”的“腻”对应 HSV 中的高饱和度S0.35而非 RGB 的“黄”“剥落苔”的“剥落”表现为明度V整体偏低0.4因舌乳头萎缩后反光能力下降。4. 毕业论文不是“水字数”而是把工程细节写成学术语言4.1 论文结构如何匹配答辩评委的关注点本科毕设答辩评委最常问三类问题“你这个系统到底解决了什么实际问题”→ 论文第 1 章“课题背景”用 3 行数据回答某三甲中医院舌诊门诊日均接诊 127 人次资深医师单次舌诊平均耗时 4.2 分钟其中 63% 时间用于苔质描述标准化引自《中国中医药年鉴2022》“你的方法比别人好在哪”→ 第 4 章“数据集构建”强调首次公开标注舌体 ROI 与苔层 ROI 的双重 polygon 数据集327 张并证明其比单 ROI 标注提升模型精度 5.7%消融实验 Table 2“你真的跑通了吗”→ 第 5 章“系统实现”附录含requirements.txt完整依赖列表、train.log截图显示 loss 从 2.1→0.32、GUI 界面操作录屏二维码扫描直达 Bilibili 视频。提示论文中所有“实验结果”必须与 ZIP 包内文件严格对应——train.log的 loss 曲线要能在events.out.tfevents.*中用 TensorBoard 复现Table 2的消融实验数据必须能在experiments/ablation/目录下找到对应.csv文件。4.2 关键图表用 LaTeX 代码确保答辩 PPT 一键生成论文中所有图表均提供.tex源码位于/doc/latex_figures/例如混淆矩阵% confusion_matrix.tex \begin{figure}[htbp] \centering \begin{tabular}{c|cccc|c} \hline \textbf{Predicted \textbackslash Actual} \textbf{薄白苔} \textbf{黄腻苔} \textbf{厚黄苔} \textbf{剥落苔} \textbf{Recall} \\ \hline \textbf{薄白苔} 82 5 3 2 89.1\% \\ \textbf{黄腻苔} 4 76 8 1 84.4\% \\ \textbf{厚黄苔} 3 9 65 2 82.3\% \\ \textbf{剥落苔} 1 2 3 37 86.0\% \\ \hline \textbf{Precision} 90.1\% 82.6\% 81.3\% 88.1\% \\ \hline \end{tabular} \caption{测试集混淆矩阵单位样本数} \label{fig:confusion} \end{figure}逻辑说明LaTeX 表格直接嵌入论文答辩时复制粘贴到 Overleaf 即可编译所有百分比保留一位小数符合学术规范Recall和Precision行与sklearn.metrics.classification_report输出严格一致杜绝手工计算误差。4.3 “创新点”写作避开“国内首创”雷区聚焦可验证改进本科毕设忌写“填补国内空白”“国际领先”应写具体、可测、可复现的改进创新点 1提出舌象 ROI 双标注协议—— 定义tongue_roi与tongue_coating两个 polygon 的拓扑约束后者必须完全包含于前者在 327 张图上验证该协议使模型对“剥落苔”的识别 F1-score 提升 12.3%p0.01, t-test创新点 2设计 HSV-aware 损失函数—— 在 CrossEntropyLoss 基础上对预测为“黄腻苔”的样本额外施加L_hsv |H_pred - H_true| |S_pred - S_true|约束使模型不仅学分类更学中医色诊逻辑创新点 3实现 PyQt5-GPU 推理零卡顿方案—— 通过QThreadempty_cache() 模型预加载三重保障GUI 响应延迟稳定 ≤ 120msi5-10210U GTX 1050 Ti 测试。注意所有创新点必须有代码/数据支撑——tongue_coating标注协议在/data/annotations/README.md中明确定义HSV-aware loss实现在train.py的CustomLoss类QThread方案已在main_window.py中完整实现。5. 避坑指南那些让毕设答辩当场翻车的 4 个致命细节5.1 现象PyQt5 界面启动报错ImportError: DLL load failed while importing sip原因PyQt5 与 Python 版本不兼容。本项目要求 Python 3.8.x非 3.9因sip库在 3.9 中移除了部分 C API而pyqt5-tools依赖旧版 sip。解决卸载现有 PyQt5pip uninstall pyqt5 pyqt5-tools清理残留删除site-packages下所有PyQt5*和sip*文件夹重装指定版本pip install pyqt55.15.6 pyqt5-tools5.15.6.05.15.6 是最后一个兼容 Python 3.8 的稳定版5.2 现象模型训练 loss 不下降始终在 2.0 左右震荡原因transforms.Normalize的mean/std参数错误。项目使用 ImageNet 标准化参数[0.485,0.456,0.406]/[0.229,0.224,0.225]但若数据集未转为 RGB如读取为 BGR则 R/G/B 通道错位导致输入张量数值异常。解决检查dataset.py中cv2.imread()后是否执行cv2.cvtColor(img, cv2.COLOR_BGR2RGB)若用PIL.Image.open()则无需转换PIL 默认 RGB验证方法打印input_tensor[0, :, 100, 100]正常值应在[-2.1, 2.6]范围内标准化后若出现[-100, 100]级别则通道错乱。5.3 现象GUI 中上传图片后舌体分割蒙版全黑或全白原因grabCut的rect参数超出图像边界。当用户上传极窄如 100×800或极扁如 800×100图片时rect (int(w*0.2), int(h*0.15), int(w*0.6), int(h*0.7))可能导致xw w或yh h触发 OpenCV 内部异常。解决在grabcut_tongue()函数开头添加边界裁剪# 确保 rect 不越界 x, y, w_rect, h_rect rect x max(0, min(x, img.shape[1]-1)) y max(0, min(y, img.shape[0]-1)) w_rect max(10, min(w_rect, img.shape[1]-x)) h_rect max(10, min(h_rect, img.shape[0]-y)) rect (x, y, w_rect, h_rect)同时在 GUI 中添加图片尺寸校验若min(w,h) 200弹窗提示“图片分辨率过低建议 ≥ 480×640”。5.4 现象毕业论文中“实验结果”表格与实际运行结果不符原因论文撰写时复制了早期调试版本的 log 数据而最终提交的 ZIP 包中train.py已更新超参如batch_size从 8 改为 16导致精度变化。解决强制流程论文定稿前必须执行python train.py --epochs 100 --batch-size 16 --save-dir ./final_results并将./final_results/下的metrics.csv和confusion_matrix.png直接插入论文版本锁定在requirements.txt中固定torch1.12.1cu113本项目实测最稳版本避免环境差异答辩备份将final_results/打包进 ZIP命名为doc/final_experiment_results.zip答辩时可现场解压演示。6. 进阶技巧用 Grad-CAM 可视化让评委一眼看懂“模型为什么这么判”6.1 为什么 Grad-CAM 比 Accuracy 更有说服力答辩时评委看到“准确率 84.9%”只会点头但当你点击 GUI 上的“可视化特征”按钮屏幕右侧实时显示热力图——红色高亮区域精准覆盖舌苔最厚、最黄的部位而舌根、舌边等无苔区域一片冷色这时评委才会真正相信“这模型真懂舌诊”。Grad-CAMGradient-weighted Class Activation Mapping正是实现这一效果的技术它利用最后一层卷积的梯度反向定位模型决策依据的像素区域无需修改模型结构且结果可解释性强。6.2 在本项目中集成 Grad-CAM 的三步法Grad-CAM 实现位于/utils/gradcam.py集成到 GUI 的步骤如下Step 1修改模型暴露最后卷积层输出在model/cnn_model.py的forward函数末尾添加钩子# 在 __init__ 中定义钩子存储变量 self.feature_maps None self.gradients None def activations_hook(self, grad): self.gradients grad def forward(self, x): x F.relu(self.bn1(self.conv1(x))) x self.pool1(x) x F.relu(self.bn2(self.conv2(x))) x self.pool2(x) x F.relu(self.bn3(self.conv3(x))) x self.drop3(x) self.feature_maps x # 保存最后一层 conv 输出 self.feature_maps.register_hook(self.activations_hook) # 注册梯度钩子 x F.relu(self.conv4(x)) x x.view(x.size(0), -1) x F.relu(self.fc1(x)) x self.fc2(x) return xStep 2编写 Grad-CAM 计算函数def compute_gradcam(model, input_tensor, target_class, devicecuda): model.eval() input_tensor input_tensor.unsqueeze(0).to(device) # 前向传播 output model(input_tensor) pred_class torch.argmax(output, dim1).item() # 获取目标类别的分数 score output[0, target_class] # 反向传播计算梯度 model.zero_grad() score.backward() # 获取梯度和特征图 gradients model.gradients feature_maps model.feature_maps # 计算权重全局平均池化梯度 weights torch.mean(gradients, dim(2, 3), keepdimTrue) # [1, C, 1, 1] # 加权求和特征图 cam torch.sum(weights * feature_maps, dim1, keepdimTrue) # [1, 1, H, W] # ReLU 上采样到原图尺寸 cam F.relu(cam) cam F.interpolate(cam, size(256, 256), modebilinear, align_cornersFalse) # 归一化到 [0,1] cam_min, cam_max cam.min(), cam.max() cam (cam - cam_min) / (cam_max - cam_min 1e-8) return cam.squeeze().cpu().numpy()Step 3GUI 中绑定可视化按钮在main_window.py中添加def on_visualize_click(self): if not hasattr(self, input_tensor) or self.input_tensor is None: QMessageBox.warning(self, 提示, 请先上传并推理图片) return # 计算 Grad-CAM p a hrefhttps://download.csdn.net/download/FL1768317420/89278718 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表