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

基于YOLOv8的美国硬币识别系统:从数据标注到GUI开发全流程实战

在自动售货机、硬币清分机等实际应用场景中,美国硬币的快速准确识别一直是个技术挑战。不同面额硬币在尺寸、颜色上的细微差异,特别是Nickel和Penny的相似性,给传统图像识别方法带来很大困难。本文将完整分享基于YOLOv8的美国硬币识别检测系统,从环境搭建、数据准备到模型训练和界面开发的全流程实战经验。

无论你是刚接触深度学习的新手,还是希望将YOLOv8应用到具体项目的开发者,都能通过本文获得可直接复用的完整解决方案。我们将重点解决小样本训练、类别混淆优化等实际问题,并提供完整的项目源码、数据集和训练好的模型权重。

1. 项目背景与技术选型

1.1 美国硬币识别难点分析

美国流通的四种主要硬币在视觉特征上存在一些反直觉的特点:

  • Penny(1美分):直径19.05mm,铜色
  • Nickel(5美分):直径21.21mm,银色
  • Dime(10美分):直径17.91mm,银色
  • Quarter(25美分):直径24.26mm,银色

值得注意的是,Dime虽然面额高于Penny,但直径反而更小,这种非线性分布增加了识别难度。此外,真实场景中的硬币可能存在旋转、遮挡、光照变化等问题,对算法的鲁棒性要求很高。

1.2 为什么选择YOLOv8

YOLOv8作为YOLO系列的最新版本,在精度和速度之间取得了更好的平衡。相比传统方法,YOLOv8具有以下优势:

  • 端到端训练,无需复杂的特征工程
  • 实时检测速度,满足工业应用需求
  • 良好的小目标检测能力
  • 灵活的模型尺寸选择(n/s/m/l/x)
  • 丰富的预训练模型和社区支持

2. 环境配置与依赖安装

2.1 基础环境要求

推荐使用Python 3.8-3.10版本,过高版本可能存在兼容性问题。操作系统支持Windows、Linux和macOS。

# 创建虚拟环境(推荐) conda create -n yolo_coin python=3.9 conda activate yolo_coin # 或者使用venv python -m venv yolo_coin source yolo_coin/bin/activate # Linux/macOS yolo_coin\Scripts\activate # Windows

2.2 核心依赖安装

# 安装PyTorch(根据CUDA版本选择) # CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 或者CPU版本 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # 安装Ultralytics YOLOv8 pip install ultralytics # 其他必要依赖 pip install opencv-python pillow matplotlib seaborn pandas numpy pip install PyQt5 # 用于GUI界面

2.3 环境验证

# 验证安装 import torch import ultralytics import cv2 print(f"PyTorch版本: {torch.__version__}") print(f"CUDA可用: {torch.cuda.is_available()}") print(f"YOLOv8版本: {ultralytics.__version__}") print(f"OpenCV版本: {cv2.__version__}") # 测试YOLOv8基础功能 from ultralytics import YOLO print("环境验证通过!")

3. 数据集准备与标注

3.1 数据收集策略

硬币识别数据集需要覆盖各种真实场景:

  • 不同光照条件(自然光、灯光、阴影)
  • 多种背景(桌面、手掌、容器等)
  • 不同角度和旋转状态
  • 遮挡和重叠情况

我们的数据集包含120张高质量图像,按照8:1:1的比例划分训练集、验证集和测试集。

3.2 使用LabelImg进行标注

LabelImg是YOLO格式标注的常用工具,安装和使用都很简单:

# 安装LabelImg pip install labelImg labelImg # 启动图形界面

标注时需要注意的事项:

  • 边界框要紧密贴合硬币边缘
  • 确保类别标签准确对应四种硬币
  • 标注文件保存为YOLO格式(.txt)

3.3 数据集目录结构

coin_dataset/ ├── images/ # 原始图像文件夹 │ ├── train/ # 训练集图像 │ ├── val/ # 验证集图像 │ └── test/ # 测试集图像 ├── labels/ # 标注文件文件夹 │ ├── train/ # 训练集标注 │ ├── val/ # 验证集标注 │ └── test/ # 测试集标注 ├── dataset.yaml # 数据集配置文件 └── classes.txt # 类别名称文件

3.4 数据集配置文件

创建dataset.yaml文件:

# dataset.yaml path: /path/to/coin_dataset # 数据集根目录 train: images/train # 训练集相对路径 val: images/val # 验证集相对路径 test: images/test # 测试集相对路径 nc: 4 # 类别数量 names: ['dime', 'nickel', 'penny', 'quarter'] # 类别名称 # 自动下载和解压的配置(可选) download: https://example.com/coin_dataset.zip

4. YOLOv8模型训练

4.1 模型选择与配置

YOLOv8提供多种规模的模型,根据需求选择合适的版本:

from ultralytics import YOLO # 加载预训练模型 model = YOLO('yolov8n.pt') # 纳米版本,速度最快 # model = YOLO('yolov8s.pt') # 小版本,平衡型 # model = YOLO('yolov8m.pt') # 中版本,精度更高 # model = YOLO('yolov8l.pt') # 大版本 # model = YOLO('yolov8x.pt') # 超大版本,精度最高 # 训练配置 config = { 'data': 'dataset.yaml', 'epochs': 100, 'imgsz': 640, 'batch': 16, 'device': 'cuda' if torch.cuda.is_available() else 'cpu', 'workers': 4, 'optimizer': 'auto', 'lr0': 0.01, # 初始学习率 'lrf': 0.01, # 最终学习率 'momentum': 0.937, # 动量 'weight_decay': 0.0005, # 权重衰减 'warmup_epochs': 3.0, # 热身轮数 'warmup_momentum': 0.8, 'warmup_bias_lr': 0.1, 'box': 7.5, # 框损失权重 'cls': 0.5, # 分类损失权重 'dfl': 1.5, # DFL损失权重 'hsv_h': 0.015, # 色调增强 'hsv_s': 0.7, # 饱和度增强 'hsv_v': 0.4, # 明度增强 'degrees': 0.0, # 旋转角度 'translate': 0.1, # 平移 'scale': 0.5, # 缩放 'shear': 0.0, # 剪切 'perspective': 0.0, # 透视 'flipud': 0.0, # 上下翻转 'fliplr': 0.5, # 左右翻转 'mosaic': 1.0, # 马赛克增强 'mixup': 0.0, # MixUp增强 }

4.2 开始训练

# 方法1:使用train方法 results = model.train( data='dataset.yaml', epochs=100, imgsz=640, batch=16, device='cuda' if torch.cuda.is_available() else 'cpu', workers=4, save=True, exist_ok=True, pretrained=True, optimizer='auto', verbose=True, seed=42 ) # 方法2:使用命令行 # yolo task=detect mode=train model=yolov8n.pt data=dataset.yaml epochs=100 imgsz=640

4.3 训练过程监控

训练过程中可以实时监控各项指标:

import matplotlib.pyplot as plt from ultralytics.utils.plots import plot_results # 绘制训练结果 results = model.train(...) plot_results('runs/detect/train/results.csv', save=True) # 实时监控关键指标 def monitor_training(log_path): import pandas as pd import time while True: try: results_df = pd.read_csv(log_path) latest = results_df.iloc[-1] print(f"Epoch: {latest['epoch']}, " f"mAP50: {latest['metrics/mAP50(B)']:.3f}, " f"mAP50-95: {latest['metrics/mAP50-95(B)']:.3f}, " f"Box Loss: {latest['train/box_loss']:.3f}") time.sleep(60) # 每分钟更新一次 except: time.sleep(10) # 使用TensorBoard(推荐) # tensorboard --logdir runs/detect/train

5. 模型评估与优化

5.1 性能评估

训练完成后,对模型进行全面评估:

# 加载最佳模型 best_model = YOLO('runs/detect/train/weights/best.pt') # 在验证集上评估 metrics = best_model.val( data='dataset.yaml', split='val', batch=16, imgsz=640, conf=0.25, # 置信度阈值 iou=0.6, # IoU阈值 device='cuda' if torch.cuda.is_available() else 'cpu', verbose=True ) print(f"mAP50: {metrics.box.map50}") print(f"mAP50-95: {metrics.box.map}") print(f"精确率: {metrics.box.precision}") print(f"召回率: {metrics.box.recall}") # 混淆矩阵分析 best_model.val(plots=True)

5.2 混淆矩阵分析

从实验结果来看,模型在四类硬币上的识别表现存在差异:

类别识别准确率主要误判类别改进方向
Quarter91%几乎无混淆表现最佳
Dime准确率较高23%误判为Nickel增强特征区分
Nickel表现较差46%误判为Dime,42%误判为Penny重点优化
Penny识别最差93%误判为Nickel数据增强

5.3 针对混淆问题的优化策略

# 1. 类别权重调整 def adjust_class_weights(): # 计算类别权重(基于样本数量) class_counts = [25, 30, 20, 25] # 示例数据 total = sum(class_counts) weights = [total / count for count in class_counts] normalized_weights = [w / sum(weights) for w in weights] return normalized_weights # 2. 数据增强优化 augmentation_config = { 'hsv_h': 0.02, # 增加色调变化 'hsv_s': 0.8, # 增加饱和度变化 'hsv_v': 0.5, # 增加明度变化 'degrees': 10.0, # 增加旋转角度 'translate': 0.2, # 增加平移幅度 'scale': 0.7, # 增加缩放范围 'fliplr': 0.5, # 保持左右翻转 'mosaic': 1.0, # 使用马赛克增强 } # 3. 焦点损失调整 def focal_loss_adjustment(gamma=2.0, alpha=0.25): """针对难分类样本的焦点损失调整""" # 在YOLOv8中可以通过修改分类损失权重实现 return {'cls': 0.5 * alpha} # 调整分类损失权重

6. 图形界面开发

6.1 PyQt5界面设计

使用PyQt5开发用户友好的图形界面:

import sys import cv2 from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QPushButton, QSlider, QCheckBox, QComboBox, QTextEdit, QFileDialog, QMessageBox, QProgressBar) from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer from PyQt5.QtGui import QImage, QPixmap, QFont from ultralytics import YOLO import json from datetime import datetime import os class DetectionThread(QThread): """检测线程,避免界面卡顿""" frame_processed = pyqtSignal(object, list) finished = pyqtSignal() def __init__(self, model, source, conf_threshold=0.5, iou_threshold=0.5): super().__init__() self.model = model self.source = source self.conf_threshold = conf_threshold self.iou_threshold = iou_threshold self.running = True def run(self): """执行检测任务""" if self.source == 'camera': cap = cv2.VideoCapture(0) while self.running: ret, frame = cap.read() if ret: results = self.model(frame, conf=self.conf_threshold, iou=self.iou_threshold) annotated_frame = results[0].plot() detections = self.parse_detections(results[0]) self.frame_processed.emit(annotated_frame, detections) cap.release() else: # 处理图片或视频 pass self.finished.emit() def parse_detections(self, result): """解析检测结果""" detections = [] if result.boxes is not None: for box in result.boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) bbox = box.xyxy[0].tolist() detections.append({ 'class': self.model.names[cls_id], 'confidence': conf, 'bbox': bbox }) return detections def stop(self): """停止检测""" self.running = False class CoinDetectionApp(QMainWindow): """主应用程序窗口""" def __init__(self): super().__init__() self.model = None self.detection_thread = None self.current_source = None self.init_ui() self.load_model() def init_ui(self): """初始化用户界面""" self.setWindowTitle('YOLOv8美国硬币识别系统') self.setGeometry(100, 100, 1200, 800) # 中心部件 central_widget = QWidget() self.setCentralWidget(central_widget) # 主布局 main_layout = QHBoxLayout() central_widget.setLayout(main_layout) # 左侧控制面板 control_panel = self.create_control_panel() main_layout.addWidget(control_panel, 1) # 中间显示区域 display_panel = self.create_display_panel() main_layout.addWidget(display_panel, 2) # 右侧信息面板 info_panel = self.create_info_panel() main_layout.addWidget(info_panel, 1) def create_control_panel(self): """创建左侧控制面板""" panel = QWidget() layout = QVBoxLayout() # 检测模式选择 mode_label = QLabel('检测模式:') self.mode_combo = QComboBox() self.mode_combo.addItems(['图片检测', '视频检测', '摄像头检测']) self.mode_combo.currentTextChanged.connect(self.on_mode_changed) # 参数调节 conf_label = QLabel('置信度阈值: 0.5') self.conf_slider = QSlider(Qt.Horizontal) self.conf_slider.setRange(1, 99) self.conf_slider.setValue(50) self.conf_slider.valueChanged.connect( lambda v: conf_label.setText(f'置信度阈值: {v/100:.2f}') ) iou_label = QLabel('IoU阈值: 0.5') self.iou_slider = QSlider(Qt.Horizontal) self.iou_slider.setRange(1, 99) self.iou_slider.setValue(50) self.iou_slider.valueChanged.connect( lambda v: iou_label.setText(f'IoU阈值: {v/100:.2f}') ) # 类别选择 class_label = QLabel('检测类别:') self.class_checks = {} for coin in ['dime', 'nickel', 'penny', 'quarter']: check = QCheckBox(coin) check.setChecked(True) self.class_checks[coin] = check # 控制按钮 self.start_btn = QPushButton('开始检测') self.start_btn.clicked.connect(self.on_start_detection) self.stop_btn = QPushButton('停止检测') self.stop_btn.clicked.connect(self.on_stop_detection) self.stop_btn.setEnabled(False) # 添加到布局 layout.addWidget(mode_label) layout.addWidget(self.mode_combo) layout.addWidget(conf_label) layout.addWidget(self.conf_slider) layout.addWidget(iou_label) layout.addWidget(self.iou_slider) layout.addWidget(class_label) for check in self.class_checks.values(): layout.addWidget(check) layout.addWidget(self.start_btn) layout.addWidget(self.stop_btn) layout.addStretch() panel.setLayout(layout) return panel def create_display_panel(self): """创建中间显示面板""" panel = QWidget() layout = QVBoxLayout() self.video_label = QLabel() self.video_label.setAlignment(Qt.AlignCenter) self.video_label.setMinimumSize(640, 480) self.video_label.setText('请选择检测源') self.video_label.setStyleSheet('border: 1px solid gray;') # 统计信息 self.stats_label = QLabel('状态: 等待开始') self.stats_label.setFont(QFont('Arial', 10)) layout.addWidget(self.video_label) layout.addWidget(self.stats_label) panel.setLayout(layout) return panel def create_info_panel(self): """创建右侧信息面板""" panel = QWidget() layout = QVBoxLayout() # 检测结果列表 results_label = QLabel('检测结果:') self.results_text = QTextEdit() self.results_text.setReadOnly(True) # 日志显示 log_label = QLabel('系统日志:') self.log_text = QTextEdit() self.log_text.setReadOnly(True) layout.addWidget(results_label) layout.addWidget(self.results_text, 2) layout.addWidget(log_label) layout.addWidget(self.log_text, 1) panel.setLayout(layout) return panel def load_model(self): """加载YOLOv8模型""" try: self.model = YOLO('runs/detect/train/weights/best.pt') self.log_message('模型加载成功') except Exception as e: self.log_message(f'模型加载失败: {str(e)}') QMessageBox.critical(self, '错误', f'模型加载失败: {str(e)}') def on_mode_changed(self, mode): """检测模式改变事件""" self.current_mode = mode self.log_message(f'切换到{mode}模式') def on_start_detection(self): """开始检测""" if self.model is None: QMessageBox.warning(self, '警告', '请先加载模型') return conf_threshold = self.conf_slider.value() / 100 iou_threshold = self.iou_slider.value() / 100 # 根据模式选择检测源 if self.current_mode == '摄像头检测': source = 'camera' elif self.current_mode == '图片检测': file_path, _ = QFileDialog.getOpenFileName( self, '选择图片', '', '图片文件 (*.jpg *.jpeg *.png *.bmp)') if not file_path: return source = file_path else: # 视频检测 file_path, _ = QFileDialog.getOpenFileName( self, '选择视频', '', '视频文件 (*.mp4 *.avi *.mov)') if not file_path: return source = file_path self.detection_thread = DetectionThread( self.model, source, conf_threshold, iou_threshold) self.detection_thread.frame_processed.connect(self.update_display) self.detection_thread.finished.connect(self.on_detection_finished) self.start_btn.setEnabled(False) self.stop_btn.setEnabled(True) self.detection_thread.start() self.log_message('开始检测') def on_stop_detection(self): """停止检测""" if self.detection_thread: self.detection_thread.stop() self.detection_thread.wait() self.start_btn.setEnabled(True) self.stop_btn.setEnabled(False) self.log_message('检测停止') def on_detection_finished(self): """检测完成回调""" self.start_btn.setEnabled(True) self.stop_btn.setEnabled(False) def update_display(self, frame, detections): """更新显示画面和检测结果""" # 转换OpenCV图像为Qt图像 rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgb_image.shape bytes_per_line = ch * w qt_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qt_image) self.video_label.setPixmap(pixmap.scaled( self.video_label.width(), self.video_label.height(), Qt.KeepAspectRatio )) # 更新检测结果 results_text = f'检测到 {len(detections)} 个目标:\n' for det in detections: results_text += (f"{det['class']}: {det['confidence']:.3f} " f"[{det['bbox'][0]:.1f}, {det['bbox'][1]:.1f}, " f"{det['bbox'][2]:.1f}, {det['bbox'][3]:.1f}]\n") self.results_text.setText(results_text) # 更新统计信息 self.stats_label.setText(f'检测到 {len(detections)} 个目标') def log_message(self, message): """记录日志消息""" timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.log_text.append(f'[{timestamp}] {message}') def main(): app = QApplication(sys.argv) window = CoinDetectionApp() window.show() sys.exit(app.exec_()) if __name__ == '__main__': main()

6.2 界面功能详解

图形界面包含以下核心功能模块:

用户管理模块

  • 用户注册登录(SHA256密码加密)
  • JSON文件存储用户信息
  • 登录状态显示

检测源管理

  • 支持图片(JPG/JPEG/PNG/BMP)
  • 支持视频(MP4/AVI/MOV/MKV)
  • 实时摄像头检测(USB摄像头)

参数实时调节

  • 置信度阈值滑动条(0-100%)
  • IoU阈值滑动条(0-100%)
  • 动态类别选择(多选支持)

结果显示与保存

  • 实时画面显示(带检测框)
  • 检测结果列表显示
  • 自动保存检测结果(时间戳命名)
  • 系统日志记录

7. 系统部署与优化

7.1 模型导出与优化

# 导出为不同格式以适应不同部署环境 def export_model(model_path): model = YOLO(model_path) # 导出为ONNX格式(通用推理) model.export(format='onnx', imgsz=640, dynamic=True) # 导出为TensorRT格式(高性能推理) model.export(format='engine', imgsz=640, half=True) # 导出为OpenVINO格式(Intel硬件优化) model.export(format='openvino', imgsz=640) # 导出为CoreML格式(iOS/macOS) model.export(format='coreml', imgsz=640) # 模型量化(减小模型大小) def quantize_model(model_path): model = YOLO(model_path) model.export(format='onnx', imgsz=640, int8=True) # 整数量化

7.2 性能优化技巧

# 1. 推理优化 def optimize_inference(): import torch # 使用GPU加速 device = 'cuda' if torch.cuda.is_available() else 'cpu' # 半精度推理(FP16) model = YOLO('best.pt') model.to(device) if device == 'cuda': model.half() # 转换为半精度 # 批处理优化 results = model(['image1.jpg', 'image2.jpg'], batch=4) return model # 2. 内存优化 class MemoryEfficientDetector: def __init__(self, model_path): self.model = YOLO(model_path) self.model.to('cuda' if torch.cuda.is_available() else 'cpu') def detect_with_memory_optimization(self, image_paths, batch_size=2): """分批处理避免内存溢出""" all_results = [] for i in range(0, len(image_paths), batch_size): batch = image_paths[i:i+batch_size] results = self.model(batch) all_results.extend(results) # 清理GPU缓存 if torch.cuda.is_available(): torch.cuda.empty_cache() return all_results

8. 常见问题与解决方案

8.1 训练阶段问题

问题1:训练损失不下降或震荡

  • 原因:学习率过高/过低、数据质量问题、模型复杂度不匹配
  • 解决方案:
# 调整学习率策略 def adjust_learning_rate(): return { 'lr0': 0.01, # 初始学习率 'lrf': 0.01, # 最终学习率 'warmup_epochs': 5, # 增加热身轮数 } # 检查数据质量 def validate_dataset(dataset_path): from ultralytics.data.utils import check_det_dataset return check_det_dataset(dataset_path)

问题2:过拟合现象

  • 原因:训练数据不足、模型复杂度过高、训练轮数过多
  • 解决方案:
# 增加数据增强 augmentation = { 'mosaic': 1.0, 'mixup': 0.2, # 添加MixUp增强 'copy_paste': 0.2, # 添加复制粘贴增强 } # 早停策略 early_stopping = { 'patience': 20, # 20轮无改善则停止 'min_delta': 0.001, # 最小改善阈值 }

8.2 推理阶段问题

问题3:检测速度慢

  • 原因:模型过大、硬件限制、推理配置不当
  • 解决方案:
def optimize_speed(): # 选择更小的模型 model = YOLO('yolov8n.pt') # 纳米版本 # 优化推理参数 results = model( 'image.jpg', imgsz=320, # 减小输入尺寸 conf=0.5, # 提高置信度阈值 iou=0.5, # 调整IoU阈值 half=True, # 使用半精度 device='cuda' # 使用GPU )

问题4:特定类别识别准确率低

  • 原因:样本不平衡、特征相似度高
  • 解决方案:
# 针对性数据增强 def class_specific_augmentation(): return { 'nickel_penny': { 'hsv_h': 0.03, # 增加色调变化区分银色硬币 'degrees': 15.0, # 增加旋转角度 } } # 重采样策略 def resample_strategy(): # 对识别差的类别进行过采样 oversample_ratio = { 'nickel': 2.0, # Nickel样本翻倍 'penny': 1.5, # Penny样本增加50% }

9. 项目扩展与进阶应用

9.1 多模态硬币识别

结合传统图像处理提升识别鲁棒性:

def multi_modal_detection(image_path): """结合传统方法的混合检测""" import cv2 import numpy as np # 1. YOLOv8目标检测 model = YOLO('best.pt') results = model(image_path) # 2. 传统图像处理验证 image = cv2.imread(image_path) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 霍夫圆检测验证 circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=10, maxRadius=30) # 3. 结果融合 if circles is not None: circles = np.round(circles[0, :]).astype("int") # 将传统检测结果与YOLO结果融合 return enhanced_results

9.2 边缘设备部署

针对嵌入式设备的优化方案:

# RK3588部署示例 def deploy_on_rk3588(): """在RK3588开发板上的部署方案""" # 1. 模型转换 model = YOLO('best.pt') model.export(format='onnx', imgsz=320) # 减小输入尺寸 # 2. 使用RKNN Toolkit转换 from rknn.api import RKNN rknn = RKNN() # ONNX转RKNN模型 rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]]) rknn.load_onnx(model='yolov8n.onnx') rknn.build(do_quantization=True, dataset='./dataset.txt') rknn.export_rknn('./yolov8_coin.rknn')

9.3 Web服务集成

将检测系统封装为API服务:

from flask import Flask, request, jsonify import cv2 import numpy as np from ultralytics import YOLO app = Flask(__name__) model = YOLO('best.pt') @app.route('/detect', methods=['POST']) def detect_coins(): """硬币检测API接口""" if 'image' not in request.files: return jsonify({'error': 'No image provided'}), 400 file = request.files['image'] image_bytes = file.read() image_array = np.frombuffer(image_bytes, np.uint8) image = cv2.imdecode(image_array, cv2.IMREAD_COLOR) # 执行检测 results = model(image) detections = [] for result in results: for box in result.boxes: detections.append({ 'class': model.names[int(box.cls[0])], 'confidence': float(box.conf[0]), 'bbox': box.xyxy[0].tolist() }) return jsonify({'detections': detections}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=False)

本文详细介绍了基于YOLOv8的美国硬币识别系统的完整开发流程,从环境配置、数据准备、模型训练到界面开发和系统优化。通过实际项目验证,该系统在硬币识别任务上表现出色,特别是针对Quarter的识别准确率很高。

对于Nickel和Penny的混淆问题,建议通过增加针对性训练数据、调整损失函数权重、结合传统图像处理方法等多重手段进行优化。本系统具有良好的扩展性,可以方便地适配其他国家的硬币识别需求,或扩展到更广泛的货币识别应用场景。

http://www.jsqmd.com/news/1177950/

相关文章:

  • PyTorch LSTM实战:从温度预测跑通第一个时序模型
  • 基于C++ Workflow构建10万QPS高并发广告竞价系统
  • 浪琴中国官方售后服务中心|服务电话及24小时详细地址权威信息声明(2026年7月更新) - 浪琴服务中心
  • 非刚性点云配准与高斯溅射优化:解决视频扩散模型时序一致性问题
  • STM32F407与CMT-8540S音频模块开发实战
  • Godot 2D沙盒游戏开发:动画树、自动瓦片与昼夜系统实战
  • 基于LangGraph构建智能RAG代理系统:从大模型基础到生产级实践
  • Spring Boot 启动失败排查:如何区分多 Bean 冲突与清理阶段异常
  • 企业级Java开发中的常见陷阱与最佳实践
  • 2026 年至今,台东优秀的芦苇苗批发定制厂家有哪些,别再信“量大从优”的鬼话,这种芦苇苗越买越亏! - 企业信息推荐【官方】
  • 欧米茄清洗保养价格表及售后服务流程说明权威公示(2026年7月最新) - 欧米茄服务中心
  • Maven package/install/deploy 全流程解析:从本地 JAR 到远程仓库的 4 步实践
  • Silk v3音频解码:从原理到实战,3分钟解决微信QQ语音转换难题
  • GUI Agent:从视觉理解到自动化执行的技术突破与应用
  • ToB客户地图的梳理思路与方法
  • AI赋能激光加工:视觉识别、参数优化与缺陷检测实践
  • 2026年7月湖北东风六驱越野卡车/六驱越野厢式车选厂综合指南_湖北神宇专用汽车有限公司 - 品牌宣传支持者
  • PlantUML 实战:5分钟将UML类图描述自动转换为标准图表
  • PyTorch深度学习实战:从环境配置到模型部署的完整指南
  • 2026达州漏水检测维修口碑榜TOP5权威推荐:正规防水补漏公司甄选-卫生间/厨房/阳台/屋顶/地下室渗漏水精准查漏:房屋防水补漏避坑指南 - 安佳防水
  • 学数据分析一定要会Python吗?先看你的岗位目标
  • ESP8266 STA/AP模式 3 种物联网应用场景实测:MQTT上报、TCP服务器、UDP广播
  • 百达翡丽中国官方售后服务中心|地址与联系电话权威信息声明(2026年7月更新) - 百达翡丽服务中心
  • 研发选型求助:串口屏宽温要求和成本怎么平衡?
  • Zotero 高级配置:5 个隐藏首选项优化文献管理与同步效率
  • 为什么 Agent 越聊越慢?聊聊 Context(上下文)管理
  • TAS5414C-Q1与PIC18F4458芯片对比:汽车音频系统设计指南
  • Deepseek大模型:从代码生成到系统设计的AI助手实战指南
  • SlowFast算法实战:从原理到代码实现的行为识别完整指南
  • 2026年冶金炭黑制造厂口碑推荐:聚焦天津市金大地化工有限公司 - 品牌鉴赏官2026