correction suppression modele yolo
This commit is contained in:
@@ -363,47 +363,6 @@ class AnalysisProvider extends ChangeNotifier {
|
|||||||
return detectedImpacts.length;
|
return detectedImpacts.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Auto-detect impacts using YOLOv8 model
|
|
||||||
Future<int> autoDetectImpactsWithYOLO({bool clearExisting = false}) async {
|
|
||||||
if (_imagePath == null || _targetType == null) return 0;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final detectedImpacts = await _detectionService.detectImpactsWithYOLO(
|
|
||||||
_imagePath!,
|
|
||||||
_targetType!,
|
|
||||||
_targetCenterX,
|
|
||||||
_targetCenterY,
|
|
||||||
_targetRadius,
|
|
||||||
_ringCount,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (clearExisting) {
|
|
||||||
_shots.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add detected impacts as shots
|
|
||||||
for (final impact in detectedImpacts) {
|
|
||||||
final shot = Shot(
|
|
||||||
id: _uuid.v4(),
|
|
||||||
x: impact.x,
|
|
||||||
y: impact.y,
|
|
||||||
score: impact.suggestedScore,
|
|
||||||
sessionId: '',
|
|
||||||
);
|
|
||||||
_shots.add(shot);
|
|
||||||
}
|
|
||||||
|
|
||||||
_recalculateScores();
|
|
||||||
_recalculateGrouping();
|
|
||||||
notifyListeners();
|
|
||||||
|
|
||||||
return detectedImpacts.length;
|
|
||||||
} catch (e) {
|
|
||||||
print('Error in YOLO auto-detection: $e');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Detect impacts with OpenCV using reference points
|
/// Detect impacts with OpenCV using reference points
|
||||||
Future<int> detectFromReferencesWithOpenCV({
|
Future<int> detectFromReferencesWithOpenCV({
|
||||||
double tolerance = 2.0,
|
double tolerance = 2.0,
|
||||||
|
|||||||
@@ -1050,72 +1050,6 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// YOLO option button
|
|
||||||
Card(
|
|
||||||
color: AppTheme.primaryColor.withAlpha(25),
|
|
||||||
child: ListTile(
|
|
||||||
leading: const Icon(Icons.psychology, color: AppTheme.primaryColor),
|
|
||||||
title: const Text('IA Detection (YOLOv8)', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
subtitle: const Text('Détection intelligente via modèle entraîné'),
|
|
||||||
onTap: () async {
|
|
||||||
Navigator.pop(context);
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Row(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 12),
|
|
||||||
Text('Détection IA en cours...'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
duration: Duration(seconds: 10),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final count = await provider.autoDetectImpactsWithYOLO(
|
|
||||||
clearExisting: clearExisting,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
count > 0
|
|
||||||
? '$count impact(s) détecté(s) par l\'IA'
|
|
||||||
: 'Aucun impact détecté par l\'IA.',
|
|
||||||
),
|
|
||||||
backgroundColor: count > 0
|
|
||||||
? AppTheme.successColor
|
|
||||||
: AppTheme.warningColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 12),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Divider()),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
|
||||||
child: Text('OU', style: TextStyle(color: Colors.grey, fontSize: 12)),
|
|
||||||
),
|
|
||||||
Expanded(child: Divider()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const Text(
|
const Text(
|
||||||
'Détection Classique (Paramétrable):',
|
'Détection Classique (Paramétrable):',
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import 'services/target_detection_service.dart';
|
|||||||
import 'services/score_calculator_service.dart';
|
import 'services/score_calculator_service.dart';
|
||||||
import 'services/grouping_analyzer_service.dart';
|
import 'services/grouping_analyzer_service.dart';
|
||||||
import 'services/image_processing_service.dart';
|
import 'services/image_processing_service.dart';
|
||||||
import 'services/yolo_impact_detection_service.dart';
|
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -34,13 +33,9 @@ void main() async {
|
|||||||
Provider<ImageProcessingService>(
|
Provider<ImageProcessingService>(
|
||||||
create: (_) => ImageProcessingService(),
|
create: (_) => ImageProcessingService(),
|
||||||
),
|
),
|
||||||
Provider<YOLOImpactDetectionService>(
|
|
||||||
create: (_) => YOLOImpactDetectionService(),
|
|
||||||
),
|
|
||||||
Provider<TargetDetectionService>(
|
Provider<TargetDetectionService>(
|
||||||
create: (context) => TargetDetectionService(
|
create: (context) => TargetDetectionService(
|
||||||
imageProcessingService: context.read<ImageProcessingService>(),
|
imageProcessingService: context.read<ImageProcessingService>(),
|
||||||
yoloService: context.read<YOLOImpactDetectionService>(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Provider<ScoreCalculatorService>(
|
Provider<ScoreCalculatorService>(
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import 'dart:math' as math;
|
|||||||
import '../data/models/target_type.dart';
|
import '../data/models/target_type.dart';
|
||||||
import 'image_processing_service.dart';
|
import 'image_processing_service.dart';
|
||||||
import 'opencv_impact_detection_service.dart';
|
import 'opencv_impact_detection_service.dart';
|
||||||
import 'yolo_impact_detection_service.dart';
|
|
||||||
|
|
||||||
export 'image_processing_service.dart'
|
export 'image_processing_service.dart'
|
||||||
show ImpactDetectionSettings, ReferenceImpact, ImpactCharacteristics;
|
show ImpactDetectionSettings, ReferenceImpact, ImpactCharacteristics;
|
||||||
export 'opencv_impact_detection_service.dart'
|
export 'opencv_impact_detection_service.dart'
|
||||||
@@ -55,16 +53,13 @@ class DetectedImpactResult {
|
|||||||
class TargetDetectionService {
|
class TargetDetectionService {
|
||||||
final ImageProcessingService _imageProcessingService;
|
final ImageProcessingService _imageProcessingService;
|
||||||
final OpenCVImpactDetectionService _opencvService;
|
final OpenCVImpactDetectionService _opencvService;
|
||||||
final YOLOImpactDetectionService _yoloService;
|
|
||||||
|
|
||||||
TargetDetectionService({
|
TargetDetectionService({
|
||||||
ImageProcessingService? imageProcessingService,
|
ImageProcessingService? imageProcessingService,
|
||||||
OpenCVImpactDetectionService? opencvService,
|
OpenCVImpactDetectionService? opencvService,
|
||||||
YOLOImpactDetectionService? yoloService,
|
|
||||||
}) : _imageProcessingService =
|
}) : _imageProcessingService =
|
||||||
imageProcessingService ?? ImageProcessingService(),
|
imageProcessingService ?? ImageProcessingService(),
|
||||||
_opencvService = opencvService ?? OpenCVImpactDetectionService(),
|
_opencvService = opencvService ?? OpenCVImpactDetectionService();
|
||||||
_yoloService = yoloService ?? YOLOImpactDetectionService();
|
|
||||||
|
|
||||||
/// Detect target and impacts from an image file
|
/// Detect target and impacts from an image file
|
||||||
TargetDetectionResult detectTarget(String imagePath, TargetType targetType) {
|
TargetDetectionResult detectTarget(String imagePath, TargetType targetType) {
|
||||||
@@ -379,45 +374,4 @@ class TargetDetectionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Détecte les impacts en utilisant YOLOv8
|
|
||||||
Future<List<DetectedImpactResult>> detectImpactsWithYOLO(
|
|
||||||
String imagePath,
|
|
||||||
TargetType targetType,
|
|
||||||
double centerX,
|
|
||||||
double centerY,
|
|
||||||
double radius,
|
|
||||||
int ringCount,
|
|
||||||
) async {
|
|
||||||
try {
|
|
||||||
final impacts = await _yoloService.detectImpacts(imagePath);
|
|
||||||
|
|
||||||
return impacts.map((impact) {
|
|
||||||
// Use YOLO-detected score (valeur) if available, otherwise calculate it
|
|
||||||
int score = impact.suggestedScore;
|
|
||||||
|
|
||||||
if (score <= 0) {
|
|
||||||
score = targetType == TargetType.concentric
|
|
||||||
? _calculateConcentricScoreWithRings(
|
|
||||||
impact.x,
|
|
||||||
impact.y,
|
|
||||||
centerX,
|
|
||||||
centerY,
|
|
||||||
radius,
|
|
||||||
ringCount,
|
|
||||||
)
|
|
||||||
: _calculateSilhouetteScore(impact.x, impact.y, centerX, centerY);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DetectedImpactResult(
|
|
||||||
x: impact.x,
|
|
||||||
y: impact.y,
|
|
||||||
radius: impact.radius,
|
|
||||||
suggestedScore: score,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
} catch (e) {
|
|
||||||
print('Erreur détection YOLOv8: $e');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,217 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
import 'dart:math' as math;
|
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'package:tflite_flutter/tflite_flutter.dart';
|
|
||||||
import 'package:image/image.dart' as img;
|
|
||||||
import 'target_detection_service.dart';
|
|
||||||
|
|
||||||
class YOLOImpactDetectionService {
|
|
||||||
Interpreter? _interpreter;
|
|
||||||
int _inputSize = 640;
|
|
||||||
List<int> _outputShape = [1, 17, 8400];
|
|
||||||
int _numClasses = 13;
|
|
||||||
|
|
||||||
static const String modelPath = 'assets/models/yolov8n_32.tflite';
|
|
||||||
static const String labelsPath = 'assets/models/labels.txt';
|
|
||||||
|
|
||||||
Future<void> init() async {
|
|
||||||
if (_interpreter != null) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
_interpreter = await Interpreter.fromAsset(modelPath);
|
|
||||||
|
|
||||||
// Get model metadata
|
|
||||||
final inputTensors = _interpreter!.getInputTensors();
|
|
||||||
if (inputTensors.isNotEmpty) {
|
|
||||||
// [1, 640, 640, 3] or [1, 3, 640, 640]
|
|
||||||
final shape = inputTensors[0].shape;
|
|
||||||
if (shape.length == 4) {
|
|
||||||
_inputSize = shape[1] == 3 ? shape[2] : shape[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final outputTensors = _interpreter!.getOutputTensors();
|
|
||||||
if (outputTensors.isNotEmpty) {
|
|
||||||
_outputShape = outputTensors[0].shape;
|
|
||||||
// Output is usually [1, 4 + num_classes, num_boxes]
|
|
||||||
if (_outputShape.length == 3) {
|
|
||||||
_numClasses = _outputShape[1] - 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print('YOLO Interpreter loaded successfully');
|
|
||||||
print('Model Input Size: $_inputSize');
|
|
||||||
print('Model Output Shape: $_outputShape (Classes: $_numClasses)');
|
|
||||||
} catch (e) {
|
|
||||||
print('Error loading YOLO model: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<DetectedImpactResult>> detectImpacts(String imagePath) async {
|
|
||||||
if (_interpreter == null) await init();
|
|
||||||
if (_interpreter == null) return [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
final bytes = File(imagePath).readAsBytesSync();
|
|
||||||
final decodedImage = img.decodeImage(bytes);
|
|
||||||
if (decodedImage == null) return [];
|
|
||||||
|
|
||||||
final originalImage = img.bakeOrientation(decodedImage);
|
|
||||||
|
|
||||||
final resizedImage = img.copyResize(
|
|
||||||
originalImage,
|
|
||||||
width: _inputSize,
|
|
||||||
height: _inputSize,
|
|
||||||
);
|
|
||||||
|
|
||||||
var input = _imageToByteListFloat32(resizedImage, _inputSize);
|
|
||||||
|
|
||||||
// Allocate output buffer dynamically
|
|
||||||
var output = List<double>.filled(
|
|
||||||
_outputShape.fold(1, (a, b) => a * b),
|
|
||||||
0
|
|
||||||
).reshape(_outputShape);
|
|
||||||
|
|
||||||
_interpreter!.run(input, output);
|
|
||||||
|
|
||||||
final results = _processOutput(
|
|
||||||
output[0],
|
|
||||||
originalImage.width,
|
|
||||||
originalImage.height,
|
|
||||||
);
|
|
||||||
|
|
||||||
print('YOLO Detection result count: ${results.length}');
|
|
||||||
return results;
|
|
||||||
} catch (e) {
|
|
||||||
print('Error during YOLO inference: $e');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DetectedImpactResult> _processOutput(
|
|
||||||
List<List<double>> output,
|
|
||||||
int imgWidth,
|
|
||||||
int imgHeight,
|
|
||||||
) {
|
|
||||||
final List<_Detection> candidates = [];
|
|
||||||
const double threshold = 0.25;
|
|
||||||
|
|
||||||
// output is typically [4 + numClasses, numBoxes]
|
|
||||||
final int rows = output.length;
|
|
||||||
final int numBoxes = output[0].length;
|
|
||||||
|
|
||||||
for (int i = 0; i < numBoxes; i++) {
|
|
||||||
double maxConfidence = 0;
|
|
||||||
int bestClass = 4;
|
|
||||||
|
|
||||||
// Find best class among all classes (indices 4 to rows-1)
|
|
||||||
for (int c = 4; c < rows; c++) {
|
|
||||||
if (output[c][i] > maxConfidence) {
|
|
||||||
maxConfidence = output[c][i];
|
|
||||||
bestClass = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxConfidence > threshold) {
|
|
||||||
final int classIndex = bestClass - 4;
|
|
||||||
|
|
||||||
candidates.add(
|
|
||||||
_Detection(
|
|
||||||
// Use dynamic mapping: 0,1,2,3 are typically x,y,w,h
|
|
||||||
// We'll keep the current mapping for now as it matches user's previous model
|
|
||||||
y: output[0][i],
|
|
||||||
x: output[1][i],
|
|
||||||
w: output[2][i],
|
|
||||||
h: output[3][i],
|
|
||||||
confidence: maxConfidence,
|
|
||||||
classIndex: classIndex,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<_Detection> suppressed = _nms(candidates);
|
|
||||||
|
|
||||||
return suppressed
|
|
||||||
.map(
|
|
||||||
(det) {
|
|
||||||
// Score = ClassIndex (0 to 10) for impact models
|
|
||||||
int score = det.classIndex;
|
|
||||||
|
|
||||||
return DetectedImpactResult(
|
|
||||||
x: det.x,
|
|
||||||
y: det.y,
|
|
||||||
radius: 5.0,
|
|
||||||
suggestedScore: score,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<_Detection> _nms(List<_Detection> detections) {
|
|
||||||
if (detections.isEmpty) return [];
|
|
||||||
|
|
||||||
detections.sort((a, b) => b.confidence.compareTo(a.confidence));
|
|
||||||
|
|
||||||
final List<_Detection> selected = [];
|
|
||||||
final List<bool> active = List.filled(detections.length, true);
|
|
||||||
|
|
||||||
for (int i = 0; i < detections.length; i++) {
|
|
||||||
if (!active[i]) continue;
|
|
||||||
|
|
||||||
selected.add(detections[i]);
|
|
||||||
|
|
||||||
for (int j = i + 1; j < detections.length; j++) {
|
|
||||||
if (!active[j]) continue;
|
|
||||||
|
|
||||||
if (_iou(detections[i], detections[j]) > 0.45) {
|
|
||||||
active[j] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
double _iou(_Detection a, _Detection b) {
|
|
||||||
final double areaA = a.w * a.h;
|
|
||||||
final double areaB = b.w * b.h;
|
|
||||||
|
|
||||||
final double x1 = math.max(a.x - a.w / 2, b.x - b.w / 2);
|
|
||||||
final double y1 = math.max(a.y - a.h / 2, b.y - b.h / 2);
|
|
||||||
final double x2 = math.min(a.x + a.w / 2, b.x + b.w / 2);
|
|
||||||
final double y2 = math.min(a.y + a.h / 2, b.y + b.h / 2);
|
|
||||||
|
|
||||||
final double intersection = math.max(0.0, x2 - x1) * math.max(0.0, y2 - y1);
|
|
||||||
return intersection / (areaA + areaB - intersection);
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint8List _imageToByteListFloat32(img.Image image, int inputSize) {
|
|
||||||
var convertedBytes = Float32List(1 * inputSize * inputSize * 3);
|
|
||||||
var buffer = Float32List.view(convertedBytes.buffer);
|
|
||||||
int pixelIndex = 0;
|
|
||||||
for (int i = 0; i < inputSize; i++) {
|
|
||||||
for (int j = 0; j < inputSize; j++) {
|
|
||||||
var pixel = image.getPixel(j, i);
|
|
||||||
buffer[pixelIndex++] = (pixel.r / 255.0);
|
|
||||||
buffer[pixelIndex++] = (pixel.g / 255.0);
|
|
||||||
buffer[pixelIndex++] = (pixel.b / 255.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return convertedBytes.buffer.asUint8List();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Detection {
|
|
||||||
final double x, y, w, h, confidence;
|
|
||||||
final int classIndex;
|
|
||||||
_Detection({
|
|
||||||
required this.x,
|
|
||||||
required this.y,
|
|
||||||
required this.w,
|
|
||||||
required this.h,
|
|
||||||
required this.confidence,
|
|
||||||
required this.classIndex,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
tflite_flutter
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@@ -536,14 +536,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
quiver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quiver
|
|
||||||
sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.2.2"
|
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -661,14 +653,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.9"
|
version: "0.7.9"
|
||||||
tflite_flutter:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: tflite_flutter
|
|
||||||
sha256: "48e6fde2ad97162bb66a16a142f4c4698add9e8cd397ce9d1cc7451b55537ac1"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.11.0"
|
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ dependencies:
|
|||||||
image: ^4.1.7
|
image: ^4.1.7
|
||||||
|
|
||||||
# Machine Learning for YOLOv8
|
# Machine Learning for YOLOv8
|
||||||
tflite_flutter: ^0.11.0
|
# tflite_flutter: ^0.11.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -90,8 +90,8 @@ flutter:
|
|||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
assets:
|
# assets:
|
||||||
- assets/models/yolov8n_32.tflite
|
# - assets/models/yolov8n_32.tflite
|
||||||
# - images/a_dot_burr.jpeg
|
# - images/a_dot_burr.jpeg
|
||||||
# - images/a_dot_ham.jpeg
|
# - images/a_dot_ham.jpeg
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
tflite_flutter
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
Reference in New Issue
Block a user