羽毛球剪辑算法集锦
目录good-badminton 推荐看起来还行racquet-sports-analyzerhuji推理脚本羽球时刻 推荐Badminton-Highlight-Extractiongood-badminton 推荐看起来还行https://github.com/qwpyyx/Good-Badmintonracquet-sports-analyzerBot-Derpy/racquet-sports-analyzerhujihttps://github.com/hhoao/huji https://github.com/hhoao/huji-algorithmconda create -p E:\soft\envs\py312 python3.12 -y conda activate E:\soft\envs\py312 pip install -r requirements.txt推理脚本python main.py --video-path C:\Users\ChanJing-01\Videos\yumao\yumao.mp4 --sport badmintonimport argparse import importlib.util import json import os import sys from pathlib import Path from typing import Any import os import re import sys import shutil from datetime import datetime # 修复 auto_clipper 的排序问题 def patch_auto_clipper(): try: from src.main.core import auto_clipper # 保存原始方法 original_handle_video auto_clipper.AutoClipper.handle_video def patched_handle_video(self, *args, **kwargs): result original_handle_video(self, *args, **kwargs) # 修复 all_ball_video_list 排序 if hasattr(self, all_ball_video_list): def extract_number(filepath): filename os.path.basename(filepath) name_without_ext os.path.splitext(filename)[0] numbers re.findall(r\d, name_without_ext) return int(numbers[0]) if numbers else 0 self.all_ball_video_list.sort(keyextract_number) return result # 替换方法 auto_clipper.AutoClipper.handle_video patched_handle_video print(✅ AutoClipper 排序修复已应用) except Exception as e: print(f⚠️ 无法应用修复: {e}) def _venv_python() - str | None: venv_dir Path(__file__).resolve().parent / .venv if sys.platform win32: candidate venv_dir / Scripts / python.exe else: candidate venv_dir / bin / python return str(candidate) if candidate.is_file() else None def _check_runtime_deps() - None: if importlib.util.find_spec(ruamel.yaml) is None: print(未找到 Python 依赖请先安装并激活虚拟环境, filesys.stderr) if sys.platform win32: print( .\\setup.ps1, filesys.stderr) print( .venv\\Scripts\\activate, filesys.stderr) else: print( ./setup.sh, filesys.stderr) print( source .venv/bin/activate, filesys.stderr) venv_python _venv_python() if venv_python: print(f 或直接: {venv_python} main.py ..., filesys.stderr) sys.exit(1) _check_runtime_deps() from src import CONFIG_PATH from src.main.config.config import Config, load_config from src.main.constant.autoclip_constant import BadmintonAutoClipConfig, MatchType from src.main.constant.common_constant import JobType from src.main.core.badminton_auto_clipper import BadmintonAutoClipper from src.main.core.pingpong_auto_clipper import PingPongAutoClipper from src.main.logger import LOG from src.main.service.large_model_service import LargeModelService from src.main.utils import path_utils def _build_parser() - argparse.ArgumentParser: parser argparse.ArgumentParser(description乒乓球、羽毛球比赛视频自动剪辑, formatter_classargparse.RawDescriptionHelpFormatter, epilog 示例: python main.py --video-path videos/demo.mp4 --sport ping_pong python main.py --video-path videos/demo.mp4 --sport badminton --match-type doubles python main.py --video-path videos/demo.mp4 --sport badminton --export-rounds python main.py --serve python main.py --train python main.py , ) parser.add_argument(--config, defaultCONFIG_PATH, helpf配置目录含 application.yml默认 {CONFIG_PATH}, ) parser.add_argument(--video-path, -v, metavarPATH, defaultrC:\Users\ChanJing-01\Videos\yumao\yumao1.mp4, help本地视频文件路径) parser.add_argument(--sport, defaultbadminton, choices[ping_pong, badminton], help运动类型clip 模式必填, ) parser.add_argument(--match-type, choices[singles, doubles], defaultsingles, help羽毛球比赛类型默认 singles, ) parser.add_argument(--output-dir, -o, metavarDIR, help剪辑输出目录) parser.add_argument(--serve, actionstore_true, help启动 Kafka HTTP 服务) parser.add_argument(--train, actionstore_true, help训练模型) # 新增回合导出相关参数 parser.add_argument(--export-rounds, actionstore_true, defaultTrue, help将每个回合单独导出为独立视频文件) parser.add_argument(--rounds-dir, metavarDIR, help回合视频导出目录默认在输出目录下创建 rounds_时间戳 子目录) parser.add_argument(--export-format, choices[mp4, avi, mov], defaultmp4, help导出视频格式默认 mp4) # 新增低回合阈值参数 parser.add_argument(--low-rounds-threshold, typeint, default5, help低回合阈值默认5个回合少于该值将被分类到低回合文件夹) # 新增视频优化参数 parser.add_argument(--optimize-video, actionstore_true, defaultTrue, help优化导出视频确保播放流畅默认开启) parser.add_argument(--target-fps, typefloat, defaultNone, help目标帧率不指定则保持原始帧率) parser.add_argument(--video-quality, choices[low, medium, high], defaulthigh, help视频质量默认 high) return parser def _resolve_mode(args: argparse.Namespace) - str: modes [bool(args.video_path), args.serve, args.train] if sum(modes) 1: LOG.error(不能同时指定 --video-path、--serve、--train) sys.exit(1) if args.video_path: return clip if args.serve: return serve if args.train: return train return config def _build_auto_clip_config(args: argparse.Namespace) - dict[str, Any] | None: if args.sport ! badminton: return None match_type (MatchType.DOUBLES_MATCH if args.match_type doubles else MatchType.SINGLES_MATCH) return json.loads(BadmintonAutoClipConfig(match_typematch_type).model_dump_json()) def optimize_video_export(input_path: str, output_path: str, target_fps: float None, quality: str high) - bool: try: import cv2 cap cv2.VideoCapture(input_path) if not cap.isOpened(): LOG.error(f无法打开视频: {input_path}) return False # 获取原始参数 original_fps cap.get(cv2.CAP_PROP_FPS) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 验证参数 if width 0 or height 0: LOG.error(f无效的视频尺寸: {width}x{height}) cap.release() return False # 确定最终帧率 fps target_fps if target_fps and target_fps 0 else original_fps if fps 0 or fps 120: fps 30 # 默认30fps # 根据质量设置编码参数 quality_settings {low: {fourcc: cv2.VideoWriter_fourcc(*mp4v), fps: min(fps, 25), scale: 0.5 # 缩放比例 }, medium: {fourcc: cv2.VideoWriter_fourcc(*mp4v), fps: fps, scale: 0.75}, high: {fourcc: cv2.VideoWriter_fourcc(*mp4v), fps: fps, scale: 1.0}} settings quality_settings.get(quality, quality_settings[high]) # 应用缩放 if settings[scale] ! 1.0: width int(width * settings[scale]) height int(height * settings[scale]) # 确保宽高为偶数编码要求 width width if width % 2 0 else width 1 height height if height % 2 0 else height 1 LOG.info(f导出参数: {width}x{height}, {settings[fps]:.2f}fps, {total_frames}帧, 质量:{quality}) # 创建写入器 out cv2.VideoWriter(str(output_path), settings[fourcc], settings[fps], (width, height)) if not out.isOpened(): LOG.error(无法创建视频写入器) cap.release() return False # 逐帧处理 frame_count 0 success_count 0 while True: ret, frame cap.read() if not ret: break # 如果需要缩放 if settings[scale] ! 1.0: frame cv2.resize(frame, (width, height), interpolationcv2.INTER_LINEAR) # 写入帧 out.write(frame) frame_count 1 success_count 1 # 每100帧显示进度 if frame_count % 100 0: LOG.debug(f处理进度: {frame_count}/{total_frames}) cap.release() out.release() # 验证输出 if success_count 0: LOG.error(没有帧被写入) return False # 验证输出文件是否存在且有效 if os.path.exists(output_path) and os.path.getsize(output_path) 0: LOG.info(f✅ 成功导出 {success_count} 帧到: {output_path}) return True else: LOG.error(f输出文件无效: {output_path}) return False except ImportError: LOG.warning(OpenCV未安装请运行: pip install opencv-python) # 回退到简单复制 try: shutil.copy2(input_path, output_path) LOG.info(f使用简单复制: {output_path}) return True except Exception as e: LOG.error(f简单复制失败: {e}) return False except Exception as e: LOG.error(f视频优化失败: {e}) # 尝试简单复制作为备选 try: shutil.copy2(input_path, output_path) LOG.info(f优化失败使用简单复制: {output_path}) return True except: return False def _export_metadata(export_dir: Path, video_path: str, exported_files: list, result, export_format: str, low_rounds: bool False, total_rounds: int 0, optimize_info: dict None) - Path | None: metadata_file export_dir / rounds_metadata.json try: metadata {source_video: video_path, export_time: datetime.now().isoformat(), total_rounds: len(exported_files), format: export_format, rounds: []} # 如果是低回合视频添加标记 if low_rounds: metadata[is_low_rounds] True metadata[low_rounds_threshold] 5 metadata[actual_rounds] total_rounds metadata[reason] f少于5个回合实际{total_rounds}个 # 添加优化信息 if optimize_info: metadata[optimization] optimize_info # 尝试获取每个回合的时间信息 for i, file_path in enumerate(exported_files, 1): round_info {round_number: i, file_name: Path(file_path).name, file_path: file_path} # 如果有时间信息可以添加 if hasattr(result, round_timestamps) and result.round_timestamps: if i len(result.round_timestamps): round_info[timestamp] result.round_timestamps[i - 1] metadata[rounds].append(round_info) with open(metadata_file, w, encodingutf-8) as f: json.dump(metadata, f, ensure_asciiFalse, indent2) LOG.info(f 元数据已导出: {metadata_file}) return metadata_file except Exception as e: LOG.warning(f导出元数据失败: {e}) return None def export_rounds_videos(result, video_path: str, output_dir: str, export_format: str mp4, low_rounds_threshold: int 5, optimize_video: bool True, target_fps: float None, video_quality: str high) - dict: exported_info {total_rounds: 0, exported_files: [], export_dir: output_dir, success: False, low_rounds_dir: None, low_rounds_files: [], low_rounds_count: 0, is_low_rounds: False, metadata_file: None, low_metadata_file: None, optimization_info: {optimized: optimize_video, target_fps: target_fps, quality: video_quality}} # 尝试获取回合视频列表 - 检查多个可能的属性名 round_videos [] possible_attrs [ball_video_list, round_video_list, all_ball_video_list, segment_video_list] for attr in possible_attrs: if hasattr(result, attr): video_list getattr(result, attr) if video_list and isinstance(video_list, list): round_videos video_list LOG.info(f找到回合视频列表: {attr}, 共 {len(round_videos)} 个) break if not round_videos: LOG.warning(未找到回合视频列表请检查剪辑结果对象) # 尝试从 result 的 dict 中获取 if hasattr(result, __dict__): for key, value in result.__dict__.items(): if isinstance(value, list) and value and any(str(v).endswith((.mp4, .avi, .mov)) for v in value): round_videos value LOG.info(f从 {key} 找到回合视频列表) break if not round_videos: LOG.error(无法找到回合视频请确保剪辑过程生成了独立的回合视频文件) return exported_info # 创建导出目录 export_dir Path(output_dir) export_dir.mkdir(parentsTrue, exist_okTrue) # 创建回合子目录 base_name Path(video_path).stem timestamp datetime.now().strftime(%Y%m%d_%H%M%S) # 先统计总回合数 total_rounds len(round_videos) LOG.info(f检测到总回合数: {total_rounds}) # 判断是否少于阈值 is_low_rounds total_rounds low_rounds_threshold if is_low_rounds: LOG.warning(f⚠️ 视频只有 {total_rounds} 个回合少于{low_rounds_threshold}个将导出到低回合文件夹) rounds_subdir export_dir / f{base_name}_low_rounds_{timestamp} else: LOG.info(f✅ 视频有 {total_rounds} 个回合正常) rounds_subdir export_dir / f{base_name}_rounds_{timestamp} rounds_subdir.mkdir(parentsTrue, exist_okTrue) # 导出每个回合 exported_files [] export_stats {total_frames: 0, total_size: 0, avg_fps: 0} for i, round_video_path in enumerate(round_videos, 1): if not os.path.exists(round_video_path): LOG.warning(f回合 {i} 视频文件不存在: {round_video_path}) continue # 构建目标文件名 round_filename fround_{i:03d}.{export_format} dest_path rounds_subdir / round_filename try: success False # 如果启用优化使用优化导出 if optimize_video: LOG.info(f 优化导出回合 {i}...) success optimize_video_export(input_pathround_video_path, output_pathstr(dest_path), target_fpstarget_fps, qualityvideo_quality) # 如果优化失败或未启用使用简单复制 if not success: LOG.info(f 使用简单复制回合 {i}) shutil.copy2(round_video_path, dest_path) success True if success: exported_files.append(str(dest_path)) # 统计信息 file_size os.path.getsize(dest_path) export_stats[total_size] file_size LOG.info(f✅ 回合 {i} 导出成功: {dest_path} ({file_size / 1024 / 1024:.2f}MB)) else: LOG.error(f❌ 回合 {i} 导出失败) except Exception as e: LOG.error(f❌ 回合 {i} 导出异常: {e}) # 最后尝试直接复制 try: shutil.copy2(round_video_path, dest_path) exported_files.append(str(dest_path)) LOG.warning(f⚠️ 回合 {i} 使用应急复制) except Exception as e2: LOG.error(f❌ 回合 {i} 所有导出方式都失败: {e2}) # 更新统计信息 export_stats[exported_count] len(exported_files) if exported_files: export_stats[avg_size] export_stats[total_size] / len(exported_files) # 导出元数据 metadata_file _export_metadata(export_dirrounds_subdir, video_pathvideo_path, exported_filesexported_files, resultresult, export_formatexport_format, low_roundsis_low_rounds, total_roundstotal_rounds, optimize_infoexported_info[optimization_info] if optimize_video else None) # 更新返回信息 exported_info.update({total_rounds: total_rounds, exported_files: exported_files, export_dir: str(rounds_subdir), metadata_file: str(metadata_file) if metadata_file else None, success: len(exported_files) 0, is_low_rounds: is_low_rounds, low_rounds_count: len(exported_files) if is_low_rounds else 0, low_rounds_dir: str(rounds_subdir) if is_low_rounds else None, export_stats: export_stats}) # 打印总结信息 print(\n * 60) print( 导出完成统计) print( * 60) if is_low_rounds: print(f⚠️ 低回合视频) print(f 总回合数: {total_rounds} (少于{low_rounds_threshold}个)) else: print(f✅ 正常视频) print(f 总回合数: {total_rounds}) print(f 成功导出: {len(exported_files)} 个) print(f 导出目录: {rounds_subdir}) if optimize_video: print(f 视频优化: 已启用) if target_fps: print(f 目标帧率: {target_fps} fps) print(f 视频质量: {video_quality}) else: print(f 视频优化: 未启用) if metadata_file: print(f 元数据: {metadata_file}) print( * 60 \n) return exported_info def run_clip(args: argparse.Namespace, config: Config) - None: video_path os.path.abspath(args.video_path) if not os.path.isfile(video_path): LOG.error(f视频文件不存在: {video_path}) sys.exit(1) if not args.sport: LOG.error(clip 模式需要指定 --sportping_pong 或 badminton) sys.exit(1) auto_clip_config config.auto_clip_config common_options auto_clip_config.common_options if args.output_dir: common_options.output_dir path_utils.get_project_path(args.output_dir) large_model_service LargeModelService(config.large_model_service_config) if args.sport ping_pong: clipper PingPongAutoClipper(auto_clip_config.ping_pong, common_options, large_model_service) else: clipper BadmintonAutoClipper(auto_clip_config.badminton, common_options, large_model_service) LOG.info(f开始剪辑: {video_path}) result clipper.autoclip_video(video_path, auto_clip_config_build_auto_clip_config(args)) # 导出合并视频 merged_video_path result.all_match_merged_video_path LOG.info(f✅ 合并视频完成: {merged_video_path}) print(f\n合并视频: {merged_video_path}) # 如果启用了回合导出 if args.export_rounds: LOG.info( 开始导出回合分段视频...) # 确定输出目录 if args.rounds_dir: output_dir os.path.abspath(args.rounds_dir) else: output_dir args.output_dir or str(common_options.output_dir) # 导出回合视频 exported_info export_rounds_videos(resultresult, video_pathvideo_path, output_diroutput_dir, export_formatargs.export_format, low_rounds_thresholdargs.low_rounds_threshold, optimize_videoargs.optimize_video, target_fpsargs.target_fps, video_qualityargs.video_quality) if exported_info[success]: LOG.info(f✅ 所有回合导出完成共 {exported_info[total_rounds]} 个回合) # 显示详细信息 print(f\n 最终结果:) print(f 视频文件: {Path(video_path).name}) print(f 总回合数: {exported_info[total_rounds]}) print(f 成功导出: {len(exported_info[exported_files])} 个) if exported_info[is_low_rounds]: print(f 状态: ⚠️ 低回合视频 ( {args.low_rounds_threshold} 个)) else: print(f 状态: ✅ 正常视频) print(f 导出目录: {exported_info[export_dir]}) if exported_info.get(metadata_file): print(f 元数据: {exported_info[metadata_file]}) # 显示优化信息 if args.optimize_video: print(f 优化: ✅ 已启用 (质量: {args.video_quality})) else: print(f 优化: ❌ 未启用) else: LOG.warning(⚠️ 没有回合视频被导出请检查剪辑结果) print(f\n✅ 处理完成: {merged_video_path}) def run_serve(config: Config) - None: from src.main.http.internal_http import InternalHttp from src.main.service.video_edit_service import VideoEditService auto_clip_config config.auto_clip_config common_options auto_clip_config.common_options large_model_service LargeModelService(config.large_model_service_config) http_client InternalHttp(config.internal.http).client pingpong_auto_clipper PingPongAutoClipper(auto_clip_config.ping_pong, common_options, large_model_service) badminton_auto_clipper BadmintonAutoClipper(auto_clip_config.badminton, common_options, large_model_service) video_edit_service VideoEditService(service_configconfig.service_config, mysql_configconfig.datasource_config.mysql, pingpong_auto_clipperpingpong_auto_clipper, badminton_auto_clipperbadminton_auto_clipper, kafka_configconfig.kafka_config, http_clienthttp_client, ) try: video_edit_service.start() except Exception as e: video_edit_service.stop() LOG.error(f启动服务失败: {e}) def run_from_config(config: Config) - None: if config.job_type JobType.SERVICE: run_serve(config) else: LOG.error(f未知的 job_type: {config.job_type}) sys.exit(1) def main() - None: parser _build_parser() args parser.parse_args() config load_config(args.config) mode _resolve_mode(args) if mode clip: run_clip(args, config) elif mode serve: run_serve(config) else: run_from_config(config) if __name__ __main__: # patch_auto_clipper() main()羽球时刻 推荐yuqiushike.comBadminton-Highlight-Extractionhttps://github.com/Manoj-A-Anandan/Badminton-Highlight-Extraction

相关新闻

C++高性能序列化与数据传输:大数据架构师的底层优化指南

C++高性能序列化与数据传输:大数据架构师的底层优化指南

1. 项目概述:从C基础到大数据架构的必经之路在技术这条路上,我见过太多开发者,尤其是那些从后端或大数据领域切入的朋友,对C的态度总是有些微妙。一方面,它被誉为“性能之王”,是构建底层基础设施、处理海量…

2026/7/27 7:35:28 阅读更多 →
GHelper终极指南:10MB轻量化工具如何彻底掌控华硕笔记本性能

GHelper终极指南:10MB轻量化工具如何彻底掌控华硕笔记本性能

GHelper终极指南:10MB轻量化工具如何彻底掌控华硕笔记本性能 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbo…

2026/7/27 7:35:28 阅读更多 →
(二十六)BLSG方案

(二十六)BLSG方案

先看方案设计: 插入一条分析:假设哈希函数H是一个随机预言机。如果CDH问题是困难的, 那么BLSG签名方案在EU - CMA安全模型下是可证明安全的, 约化损失为2根号qH,其中qH是对随机预言机的哈希查询次数。规约损失是如何得到的呢?慢慢分析,继续往下看证明如下: 假定存在一…

2026/7/27 7:35:28 阅读更多 →

最新新闻

Python历史事件爬虫系统:架构设计与实战技巧

Python历史事件爬虫系统:架构设计与实战技巧

1. 项目概述:历史事件时间线爬虫系统的核心价值在信息爆炸的时代,历史研究者、数据分析师和内容创作者经常面临一个共同痛点:如何高效获取结构化历史事件数据。传统手工收集方式不仅耗时耗力,而且难以保证数据的完整性和一致性。这…

2026/7/27 7:42:31 阅读更多 →
RAG系统解析:检索增强生成技术在企业AI应用中的实践

RAG系统解析:检索增强生成技术在企业AI应用中的实践

1. RAG系统概述:为什么它正在改变AI应用开发方式在AI大模型应用开发领域,检索增强生成(Retrieval-Augmented Generation,简称RAG)已经成为解决大模型实际落地痛点的关键技术方案。作为一名经历过多个企业级AI项目落地的…

2026/7/27 7:42:31 阅读更多 →
Ceph 分布式存储安全实践:cephx 协议、密钥环与精细化访问权限配置

Ceph 分布式存储安全实践:cephx 协议、密钥环与精细化访问权限配置

Ceph 分布式存储 认证和授权管理 摘要:本文全面介绍了Ceph分布式存储系统的认证和授权管理机制。首先详细讲解了Ceph集群身份验证的cephx协议工作原理、账户命名规则、密钥环文件管理以及用户身份指定方法。接着系统阐述了用户账户的创建、查看、删除、导出导入等管…

2026/7/27 7:42:31 阅读更多 →
SpringBoot智慧物业管理系统开发实践与优化

SpringBoot智慧物业管理系统开发实践与优化

1. 项目概述:SpringBoot智慧物业管理系统这个智慧物业管理系统本质上是一个面向现代社区的数字化运营平台。我去年为本地一个中型社区开发过类似系统,上线后物业报修响应时间从平均48小时缩短到4小时以内,业主满意度提升了35%。系统基于Sprin…

2026/7/27 7:42:31 阅读更多 →
WuminPy 一个在 Android 设备上运行 Python 脚本的工具应用

WuminPy 一个在 Android 设备上运行 Python 脚本的工具应用

WuminPy — 在 Android 上运行 Python,还能打包成独立 APK 项目简介 WuminPy 是一个在 Android 设备上运行 Python 脚本的工具应用。它不仅提供完整的 Python 3.14 运行环境,还集成了代码编辑器、终端模拟器、Git、AI 助手、无障碍自动化、插件系统&am…

2026/7/27 7:42:31 阅读更多 →
DM6467硬件设计核心:仿真控制、电源时钟与上拉电阻实战解析

DM6467硬件设计核心:仿真控制、电源时钟与上拉电阻实战解析

1. 项目概述:深入DM6467的硬件设计核心在嵌入式系统,尤其是涉及音视频编解码、通信处理这类复杂实时任务的领域,硬件平台的稳定性和可调试性直接决定了项目的成败。我接触过不少基于TI Davinci系列DMSoC(数字媒体片上系统&#xf…

2026/7/27 7:41:31 阅读更多 →

日新闻

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:54 阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻