基于CNN的水面漂浮垃圾智能识别系统开发实践
1. 项目概述基于CNN的水面漂浮垃圾识别系统水面环境污染治理一直是环保领域的重要课题其中漂浮垃圾的快速识别与定位是开展清理工作的首要环节。传统的人工巡查方式效率低下且成本高昂而基于计算机视觉的自动识别技术为解决这一问题提供了新的思路。本项目采用卷积神经网络CNN构建了一个水面漂浮垃圾识别系统能够对航拍或监控视频中的水面区域进行实时检测和分类。在实际测试中系统对塑料袋、泡沫制品、树枝等常见漂浮物的识别准确率达到92.3%单帧图像处理时间仅为0.15秒使用GTX 1080Ti显卡完全满足实时监测需求。系统采用B/S架构设计前端通过Vue.js实现可视化交互界面后端基于Spring Boot框架搭建服务模型训练使用Python的TensorFlow框架完成。2. 系统架构设计2.1 整体技术栈选择系统采用前后端分离的架构设计主要基于以下技术栈前端技术Vue.js 2.x轻量级前端框架组件化开发Element UI提供丰富的UI组件ECharts用于数据可视化展示Axios处理HTTP请求后端技术Spring Boot 2.5简化配置的Java后端框架MyBatis-Plus增强型ORM框架Shiro权限控制框架Redis缓存处理AI模型部分Python 3.8TensorFlow 2.4OpenCV 4.5图像预处理LabelImg标注工具2.2 系统架构设计系统采用典型的三层架构┌───────────────────────────────────────┐ │ 客户端层 │ │ (Web浏览器、移动端、API调用端) │ └───────────────┬───────────────┬───────┘ │ │ ┌───────────────▼───────┐ ┌─────▼───────────────┐ │ 表现层 │ │ API网关 │ │ (Vue.js前端界面) │ │ (路由、鉴权、限流) │ └───────────────┬───────┘ └──────────┬──────────┘ │ │ ┌───────────────▼────────────────────▼───────┐ │ 业务逻辑层 │ │ (Spring Boot服务、算法模型调用、业务处理) │ └───────────────┬────────────────────┬───────┘ │ │ ┌───────────────▼───────┐ ┌──────────▼──────────┐ │ 数据访问层 │ │ 模型服务层 │ │ (MySQL数据库操作) │ │ (TensorFlow模型推理) │ └───────────────────────┘ └─────────────────────┘2.3 数据库设计系统使用MySQL 8.0作为主数据库主要包含以下表结构用户管理模块CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码, salt varchar(20) DEFAULT NULL COMMENT 盐, email varchar(100) DEFAULT NULL COMMENT 邮箱, mobile varchar(100) DEFAULT NULL COMMENT 手机号, status tinyint DEFAULT 1 COMMENT 状态 0:禁用 1:正常, create_time datetime DEFAULT NULL COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户;检测记录模块CREATE TABLE detect_record ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint DEFAULT NULL COMMENT 用户ID, image_path varchar(255) DEFAULT NULL COMMENT 图片路径, result_json text COMMENT 检测结果JSON, detect_time datetime DEFAULT NULL COMMENT 检测时间, device_type varchar(50) DEFAULT NULL COMMENT 设备类型, location varchar(100) DEFAULT NULL COMMENT 地理位置, PRIMARY KEY (id), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT检测记录表;垃圾类别模块CREATE TABLE garbage_category ( id int NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 类别名称, code varchar(20) NOT NULL COMMENT 类别编码, description varchar(255) DEFAULT NULL COMMENT 类别描述, create_time datetime DEFAULT NULL COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY idx_code (code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT垃圾类别表;3. CNN模型设计与实现3.1 数据集准备与预处理项目使用了自建的水面垃圾数据集包含以下类别塑料制品塑料袋、瓶子等泡沫制品树枝树叶纸制品其他垃圾数据集统计总样本数12,458张训练集9,966张80%验证集1,246张10%测试集1,246张10%数据增强策略train_datagen ImageDataGenerator( rotation_range20, width_shift_range0.2, height_shift_range0.2, shear_range0.2, zoom_range0.2, horizontal_flipTrue, fill_modenearest, rescale1./255 )3.2 模型架构设计采用改进的ResNet50架构作为基础模型def build_model(input_shape(256, 256, 3), num_classes5): base_model ResNet50( weightsimagenet, include_topFalse, input_shapeinput_shape ) # 冻结基础模型的前面层 for layer in base_model.layers[:100]: layer.trainable False # 添加自定义层 x base_model.output x GlobalAveragePooling2D()(x) x Dense(1024, activationrelu)(x) x Dropout(0.5)(x) predictions Dense(num_classes, activationsoftmax)(x) model Model(inputsbase_model.input, outputspredictions) model.compile( optimizerAdam(lr0.0001), losscategorical_crossentropy, metrics[accuracy] ) return model3.3 模型训练与优化训练参数配置Batch size: 32Epochs: 50初始学习率: 0.0001使用ReduceLROnPlateau回调自动调整学习率使用EarlyStopping防止过拟合训练过程可视化模型评估结果测试集准确率: 92.3%平均推理时间: 0.15秒/帧模型大小: 98MB3.4 模型部署方案采用TensorFlow Serving进行模型部署# Dockerfile示例 FROM tensorflow/serving:2.4.0 COPY models/ /models/ ENV MODEL_NAMEfloating_garbage EXPOSE 8500 EXPOSE 8501后端服务调用模型示例public DetectionResult detectGarbage(String imagePath) { // 图像预处理 BufferedImage image ImageIO.read(new File(imagePath)); ByteArrayOutputStream baos new ByteArrayOutputStream(); ImageIO.write(image, jpg, baos); byte[] imageBytes baos.toByteArray(); // 构建gRPC请求 PredictRequest request PredictRequest.newBuilder() .setModelSpec(ModelSpec.newBuilder() .setName(floating_garbage) .setSignatureName(serving_default)) .putInputs(input_1, TensorProto.newBuilder() .setDtype(DataType.DT_STRING) .addStringVal(ByteString.copyFrom(imageBytes)) .build()) .build(); // 调用TensorFlow Serving PredictResponse response stub.predict(request); // 处理返回结果 MapString, TensorProto outputs response.getOutputsMap(); TensorProto outputProto outputs.get(output_1); // 转换为DetectionResult对象 return convertToResult(outputProto); }4. 系统功能实现4.1 用户管理模块实现基于RBAC的权限控制系统Service public class UserServiceImpl implements UserService { Autowired private UserMapper userMapper; Autowired private PasswordEncoder passwordEncoder; Override public User registerUser(UserRegisterDTO dto) { if (userMapper.existsByUsername(dto.getUsername())) { throw new BusinessException(用户名已存在); } User user new User(); user.setUsername(dto.getUsername()); user.setPassword(passwordEncoder.encode(dto.getPassword())); user.setEmail(dto.getEmail()); user.setStatus(1); user.setCreateTime(new Date()); userMapper.insert(user); // 分配默认角色 userRoleMapper.insert(new UserRole(user.getId(), 2L)); // 2为普通用户角色 return user; } Override public PageInfoUserVO listUsers(UserQueryDTO query) { PageHelper.startPage(query.getPageNum(), query.getPageSize()); ListUser users userMapper.selectByQuery(query); return PageInfo.of(users.stream().map(this::convertToVO).collect(Collectors.toList())); } }4.2 图像检测模块前端上传检测代码示例template div classdetect-container el-upload action/api/detect/upload :before-uploadbeforeUpload :on-successhandleSuccess :show-file-listfalse acceptimage/* el-button typeprimary上传图片检测/el-button /el-upload div v-ifresult classresult-container h3检测结果/h3 el-image :srcimageUrl fitcontain/el-image el-table :dataresult.details border el-table-column propcategory label垃圾类别/el-table-column el-table-column propconfidence label置信度 template #default{row} {{ (row.confidence * 100).toFixed(2) }}% /template /el-table-column el-table-column proplocation label位置 template #default{row} ({{ row.x1 }}, {{ row.y1 }}) - ({{ row.x2 }}, {{ row.y2 }}) /template /el-table-column /el-table /div /div /template script export default { data() { return { imageUrl: , result: null } }, methods: { beforeUpload(file) { const isImage file.type.startsWith(image/) if (!isImage) { this.$message.error(只能上传图片文件) } return isImage }, handleSuccess(response) { this.imageUrl response.data.imageUrl this.result response.data.result } } } /script4.3 历史记录管理实现检测记录的查询与统计功能RestController RequestMapping(/api/record) public class RecordController { Autowired private RecordService recordService; GetMapping(/list) public Result listRecords(RecordQueryDTO query) { PageInfoRecordVO pageInfo recordService.listRecords(query); return Result.success(pageInfo); } GetMapping(/statistics) public Result getStatistics(StatisticsQuery query) { MapString, Object data recordService.getStatistics(query); return Result.success(data); } } Service public class RecordServiceImpl implements RecordService { Override public MapString, Object getStatistics(StatisticsQuery query) { MapString, Object result new HashMap(); // 按类别统计 ListCategoryStat categoryStats recordMapper.countByCategory(query); result.put(byCategory, categoryStats); // 按时间统计 ListDateStat dateStats recordMapper.countByDate(query); result.put(byDate, dateStats); // 总量统计 int totalCount recordMapper.countTotal(query); result.put(totalCount, totalCount); return result; } }5. 系统测试与优化5.1 功能测试用例图像检测功能测试测试项测试步骤预期结果实际结果状态正常检测上传清晰的水面垃圾图片返回正确的检测结果和置信度符合预期通过空图像上传空白或全黑图片返回未检测到垃圾提示符合预期通过大文件上传20MB以上的图片返回文件过大错误符合预期通过非图像文件上传PDF文档提示不支持的文件格式符合预期通过多物体识别上传包含多种垃圾的图片正确识别所有垃圾类别识别率92%通过5.2 性能测试结果使用JMeter进行压力测试单接口测试登录接口500并发平均响应时间238ms错误率0%图像检测接口100并发平均响应时间1.2s错误率0%混合场景测试模拟50用户同时操作系统登录→上传检测→查看历史平均响应时间890ms吞吐量68请求/秒CPU使用率峰值78%内存使用峰值2.3GB/4GB5.3 模型优化策略针对实际使用中发现的问题采取了以下优化措施类别不平衡处理使用类别权重调整损失函数class_weights compute_class_weight(balanced, classes, y_train) model.fit(..., class_weightclass_weights)小目标检测优化在原始模型基础上添加FPN(Feature Pyramid Network)结构使用Focal Loss替代交叉熵损失推理速度优化使用TensorRT加速推理将模型量化为FP16精度优化后推理时间从0.15s降至0.08s数据增强改进添加针对水面场景的特殊增强def water_ripple_augmentation(image): # 模拟水面波纹效果 rows, cols image.shape[:2] img_output np.zeros_like(image) for i in range(rows): for j in range(cols): offset_x int(5.0 * math.sin(2 * 3.14 * i / 60)) offset_y 0 if j offset_x cols: img_output[i,j] image[i, (j offset_x) % cols] else: img_output[i,j] 0 return img_output6. 项目部署与运维6.1 服务器环境配置推荐生产环境配置CPU: Intel Xeon 4核以上内存: 8GB以上GPU: NVIDIA T4或以上(如需实时检测)系统: Ubuntu 20.04 LTS环境安装脚本示例# 安装Docker sudo apt-get update sudo apt-get install docker.io sudo systemctl start docker sudo systemctl enable docker # 安装NVIDIA Docker(如使用GPU) distribution$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list sudo apt-get update sudo apt-get install -y nvidia-docker2 sudo systemctl restart docker # 拉取TensorFlow Serving镜像 docker pull tensorflow/serving:2.4.0-gpu6.2 容器化部署使用Docker Compose编排服务version: 3 services: web: image: openjdk:11-jre ports: - 8080:8080 volumes: - ./app.jar:/app.jar environment: - SPRING_PROFILES_ACTIVEprod - TF_SERVING_HOSTtf-serving command: [java, -jar, /app.jar] depends_on: - tf-serving - mysql - redis tf-serving: image: tensorflow/serving:2.4.0-gpu ports: - 8500:8500 - 8501:8501 volumes: - ./models:/models environment: - MODEL_NAMEfloating_garbage deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] mysql: image: mysql:8.0 ports: - 3306:3306 environment: - MYSQL_ROOT_PASSWORDyourpassword - MYSQL_DATABASEgarbage_db volumes: - ./mysql_data:/var/lib/mysql redis: image: redis:6.0 ports: - 6379:6379 volumes: - ./redis_data:/data nginx: image: nginx:1.19 ports: - 80:80 - 443:443 volumes: - ./nginx.conf:/etc/nginx/nginx.conf - ./frontend/dist:/usr/share/nginx/html depends_on: - web6.3 监控与日志使用Prometheus Grafana监控系统Spring Boot配置Prometheus监控# application.yml management: endpoints: web: exposure: include: health,info,prometheus metrics: tags: application: ${spring.application.name}Grafana监控面板示例日志收集方案使用ELK(Elasticsearch Logstash Kibana)收集分析日志日志格式规范Slf4j RestController public class DetectController { PostMapping(/detect) public Result detect(RequestParam MultipartFile file) { log.info(检测请求接收文件大小: {}KB, file.getSize()/1024); try { DetectionResult result detectService.detect(file); log.info(检测完成结果: {}, result); return Result.success(result); } catch (Exception e) { log.error(检测失败, e); return Result.error(检测失败); } } }7. 项目总结与改进方向7.1 项目成果本项目实现了一个完整的水面漂浮垃圾识别系统主要成果包括开发了基于改进ResNet50的垃圾识别模型准确率达到92.3%构建了完整的B/S架构业务系统支持用户管理、图像检测、历史查询等功能实现了前后端分离的开发模式前端使用Vue.js后端使用Spring Boot设计了高性能的部署方案支持Docker容器化部署建立了完整的监控体系包括系统指标、业务日志和模型性能监控7.2 经验总结在项目开发过程中积累的主要经验数据质量至关重要初期由于数据标注不统一导致模型性能波动建立严格的标注规范后效果显著提升模型服务化考量需要平衡模型大小和推理速度考虑多模型版本管理和灰度发布监控模型性能衰减建立定期重训练机制前后端协作优化制定统一的API规范使用Swagger维护接口文档建立Mock服务支持并行开发性能优化技巧使用Redis缓存频繁访问的数据采用消息队列处理耗时操作前端实现图片压缩上传7.3 未来改进方向模型层面尝试YOLOv5等目标检测模型实现像素级定位引入半监督学习减少标注成本开发多模态模型结合红外等传感器数据系统功能增加视频流实时分析功能开发移动端APP支持现场拍摄检测实现区域污染热力图分析工程化改进引入CI/CD自动化部署流程完善自动化测试体系增加模型解释性模块提高结果可信度业务扩展对接政府环保监管平台开发垃圾清理任务调度模块建立污染源追踪分析功能在实际部署使用过程中我们发现模型对光线变化较为敏感下一步计划通过增加数据增强策略和使用更先进的网络结构来提升模型的鲁棒性。同时我们也在探索将系统与无人机巡检平台集成实现更大范围的自动化水面监测。