fix: lenteur de l appli capture screen
This commit is contained in:
@@ -16,7 +16,8 @@ import '../session/session_provider.dart';
|
|||||||
import 'widgets/image_source_button.dart';
|
import 'widgets/image_source_button.dart';
|
||||||
import '../../services/image_crop_service.dart';
|
import '../../services/image_crop_service.dart';
|
||||||
import '../../services/opencv_target_service.dart'; // AJOUT : Pour la détection périodique
|
import '../../services/opencv_target_service.dart'; // AJOUT : Pour la détection périodique
|
||||||
|
import 'package:image/image.dart' as img;
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
class CaptureScreen extends StatefulWidget {
|
class CaptureScreen extends StatefulWidget {
|
||||||
const CaptureScreen({super.key});
|
const CaptureScreen({super.key});
|
||||||
|
|
||||||
@@ -120,11 +121,60 @@ class _CaptureScreenState extends State<CaptureScreen> with SingleTickerProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AJOUT : Démarre la détection périodique du parallélisme toutes les 2 secondes
|
|
||||||
void _startAlignmentDetection() {
|
void _startAlignmentDetection() {
|
||||||
_detectionTimer?.cancel();
|
_detectionTimer?.cancel();
|
||||||
_detectionTimer = Timer.periodic(const Duration(seconds: 2), (_) {
|
_detectionTimer = null;
|
||||||
_analyzeCurrentFrame();
|
|
||||||
|
// OPTIMISATION : startImageStream au lieu de takePicture
|
||||||
|
// On analyse 1 frame toutes les 3 secondes via le stream natif
|
||||||
|
DateTime? _lastAnalysis;
|
||||||
|
|
||||||
|
_cameraController!.startImageStream((CameraImage cameraImage) async {
|
||||||
|
if (_isAnalyzingFrame) return;
|
||||||
|
final now = DateTime.now();
|
||||||
|
if (_lastAnalysis != null &&
|
||||||
|
now.difference(_lastAnalysis!).inSeconds < 3) return;
|
||||||
|
_lastAnalysis = now;
|
||||||
|
_isAnalyzingFrame = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Convertir la CameraImage en fichier temporaire pour OpenCV
|
||||||
|
final tempDir = await getTemporaryDirectory();
|
||||||
|
final tempPath =
|
||||||
|
'${tempDir.path}/frame_analysis.jpg';
|
||||||
|
|
||||||
|
// Conversion YUV420 → JPEG via le package image
|
||||||
|
final img.Image? converted = _convertCameraImage(cameraImage);
|
||||||
|
if (converted == null) {
|
||||||
|
_isAnalyzingFrame = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await File(tempPath)
|
||||||
|
.writeAsBytes(img.encodeJpg(converted, quality: 60));
|
||||||
|
|
||||||
|
final result = await _opencvService.detectTarget(tempPath);
|
||||||
|
|
||||||
|
try { await File(tempPath).delete(); } catch (_) {}
|
||||||
|
|
||||||
|
if (mounted && _showLiveCamera) {
|
||||||
|
setState(() {
|
||||||
|
if (!result.success) {
|
||||||
|
_alignmentStatus = null;
|
||||||
|
} else {
|
||||||
|
final bool isCentered =
|
||||||
|
result.centerX > 0.25 && result.centerX < 0.75 &&
|
||||||
|
result.centerY > 0.25 && result.centerY < 0.75;
|
||||||
|
final bool isSizedCorrectly = result.radius > 0.15;
|
||||||
|
_alignmentStatus = isCentered && isSizedCorrectly;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Erreur analyse frame: $e');
|
||||||
|
} finally {
|
||||||
|
_isAnalyzingFrame = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,11 +182,64 @@ class _CaptureScreenState extends State<CaptureScreen> with SingleTickerProvider
|
|||||||
void _stopAlignmentDetection() {
|
void _stopAlignmentDetection() {
|
||||||
_detectionTimer?.cancel();
|
_detectionTimer?.cancel();
|
||||||
_detectionTimer = null;
|
_detectionTimer = null;
|
||||||
|
// AJOUT : Stopper le stream proprement
|
||||||
|
try {
|
||||||
|
if (_cameraController != null &&
|
||||||
|
_cameraController!.value.isStreamingImages) {
|
||||||
|
_cameraController!.stopImageStream();
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
_alignmentStatus = null;
|
_alignmentStatus = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AJOUT : Conversion CameraImage (YUV420) vers img.Image
|
||||||
|
img.Image? _convertCameraImage(CameraImage cameraImage) {
|
||||||
|
try {
|
||||||
|
final int width = cameraImage.width;
|
||||||
|
final int height = cameraImage.height;
|
||||||
|
|
||||||
|
// Réduction de résolution pour l'analyse : on prend 1 pixel sur 2
|
||||||
|
// (suffisant pour détecter les cercles, beaucoup plus rapide)
|
||||||
|
final int targetW = width ~/ 2;
|
||||||
|
final int targetH = height ~/ 2;
|
||||||
|
|
||||||
|
final yPlane = cameraImage.planes[0];
|
||||||
|
final uPlane = cameraImage.planes[1];
|
||||||
|
final vPlane = cameraImage.planes[2];
|
||||||
|
|
||||||
|
final image = img.Image(width: targetW, height: targetH);
|
||||||
|
|
||||||
|
for (int y = 0; y < targetH; y++) {
|
||||||
|
for (int x = 0; x < targetW; x++) {
|
||||||
|
final int srcX = x * 2;
|
||||||
|
final int srcY = y * 2;
|
||||||
|
|
||||||
|
final int yIndex = srcY * yPlane.bytesPerRow + srcX;
|
||||||
|
final int uvIndex =
|
||||||
|
(srcY ~/ 2) * uPlane.bytesPerRow + (srcX ~/ 2) * uPlane.bytesPerPixel!;
|
||||||
|
|
||||||
|
final int yVal = yPlane.bytes[yIndex];
|
||||||
|
final int uVal = uPlane.bytes[uvIndex] - 128;
|
||||||
|
final int vVal = vPlane.bytes[uvIndex] - 128;
|
||||||
|
|
||||||
|
// Conversion YUV → RGB
|
||||||
|
final int r = (yVal + 1.402 * vVal).clamp(0, 255).toInt();
|
||||||
|
final int g = (yVal - 0.344136 * uVal - 0.714136 * vVal).clamp(0, 255).toInt();
|
||||||
|
final int b = (yVal + 1.772 * uVal).clamp(0, 255).toInt();
|
||||||
|
|
||||||
|
image.setPixelRgb(x, y, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Erreur conversion frame: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AJOUT : Capture une frame et analyse le parallélisme via OpenCV
|
// AJOUT : Capture une frame et analyse le parallélisme via OpenCV
|
||||||
Future<void> _analyzeCurrentFrame() async {
|
Future<void> _analyzeCurrentFrame() async {/*
|
||||||
// Verrou : on n'analyse pas si une analyse est déjà en cours
|
// Verrou : on n'analyse pas si une analyse est déjà en cours
|
||||||
if (_isAnalyzingFrame) return;
|
if (_isAnalyzingFrame) return;
|
||||||
if (_cameraController == null || !_cameraController!.value.isInitialized) return;
|
if (_cameraController == null || !_cameraController!.value.isInitialized) return;
|
||||||
@@ -177,7 +280,7 @@ class _CaptureScreenState extends State<CaptureScreen> with SingleTickerProvider
|
|||||||
debugPrint('Erreur analyse frame: $e');
|
debugPrint('Erreur analyse frame: $e');
|
||||||
} finally {
|
} finally {
|
||||||
_isAnalyzingFrame = false;
|
_isAnalyzingFrame = false;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleGallerySelection() async {
|
Future<void> _handleGallerySelection() async {
|
||||||
|
|||||||
Reference in New Issue
Block a user