import 'dart:io'; import 'package:http/http.dart' as http; import 'dart:convert'; class YOLOAnalysisResult { final List objects; final String? error; YOLOAnalysisResult({ required this.objects, this.error, }); factory YOLOAnalysisResult.fromJson(Map json) { if (json.containsKey('error')) { return YOLOAnalysisResult( objects: [], error: json['error'], ); } List objects = []; if (json.containsKey('objects') || json.containsKey('detections')) { final detections = json['objects'] ?? json['detections'] ?? []; objects = (detections as List) .map((item) => DetectedObject.fromJson(item)) .toList(); } return YOLOAnalysisResult(objects: objects); } } class DetectedObject { final String label; final double confidence; final BoundingBox bbox; DetectedObject({ required this.label, required this.confidence, required this.bbox, }); factory DetectedObject.fromJson(Map json) { return DetectedObject( label: json['label'] ?? json['class'] ?? json['name'] ?? 'Unknown', confidence: (json['confidence'] ?? json['score'] ?? 0.0).toDouble(), bbox: BoundingBox.fromJson(json['bbox'] ?? json['box'] ?? {}), ); } } class BoundingBox { final double x; final double y; final double width; final double height; BoundingBox({ required this.x, required this.y, required this.width, required this.height, }); factory BoundingBox.fromJson(Map json) { return BoundingBox( x: (json['x'] ?? json['x1'] ?? 0.0).toDouble(), y: (json['y'] ?? json['y1'] ?? 0.0).toDouble(), width: (json['width'] ?? (json['x2'] ?? 0.0) - (json['x1'] ?? 0.0)).toDouble(), height: (json['height'] ?? (json['y2'] ?? 0.0) - (json['y1'] ?? 0.0)).toDouble(), ); } } class YOLOService { // 配置YOLO API端点(用户可以修改) static const String yoloApiUrl = 'http://10.168.2.249:3000/api/upload'; // 分析单张图片 Future analyzeImage(String imagePath) async { try { final file = File(imagePath); if (!await file.exists()) { return YOLOAnalysisResult( objects: [], error: '图片文件不存在', ); } // 创建multipart请求 var request = http.MultipartRequest('POST', Uri.parse(yoloApiUrl)); request.files.add( await http.MultipartFile.fromPath('image', imagePath), ); // 发送请求 var response = await request.send(); var responseBody = await response.stream.bytesToString(); if (response.statusCode == 200) { final jsonData = json.decode(responseBody); return YOLOAnalysisResult.fromJson(jsonData); } else { return YOLOAnalysisResult( objects: [], error: 'API请求失败: ${response.statusCode}', ); } } catch (e) { // 如果API不可用,返回模拟数据(用于测试) return _getMockAnalysisResult(); } } // 分析多张图片 Future> analyzeImages(List imagePaths) async { Map results = {}; for (String path in imagePaths) { results[path] = await analyzeImage(path); } return results; } // 获取模拟分析结果(用于测试,当API不可用时) YOLOAnalysisResult _getMockAnalysisResult() { return YOLOAnalysisResult( objects: [ DetectedObject( label: 'person', confidence: 0.95, bbox: BoundingBox(x: 100, y: 100, width: 200, height: 300), ), DetectedObject( label: 'chair', confidence: 0.87, bbox: BoundingBox(x: 300, y: 250, width: 150, height: 200), ), ], error: '使用模拟数据(YOLO API未配置或不可用)', ); } }