반응형
#9. 실시간 인식 구현하기 (캡처 + 전송 + 결과 표시)
이번 편에서는 실시간 인식을 위한 핵심인 주기적인 이미지 캡처 → 전송 → 결과 표시를 구현해볼게. 초반에는 5초 간격으로 테스트해보는 게 좋아.
🔄 1단계: 이미지 주기적 캡처 타이머 설정
realtime_screen.dart에 타이머와 이미지 인식 로직 추가:
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import '../services/plant_id_service.dart';
import '../services/image_encoder.dart';
class RealtimeScreen extends StatefulWidget {
const RealtimeScreen({super.key});
@override
State<RealtimeScreen> createState() => _RealtimeScreenState();
}
class _RealtimeScreenState extends State<RealtimeScreen> {
CameraController? _controller;
List<CameraDescription>? _cameras;
Timer? _timer;
String? _result;
@override
void initState() {
super.initState();
_initCamera();
}
Future<void> _initCamera() async {
_cameras = await availableCameras();
_controller = CameraController(_cameras![0], ResolutionPreset.medium);
await _controller!.initialize();
setState(() {});
_startTimer();
}
void _startTimer() {
_timer = Timer.periodic(const Duration(seconds: 5), (_) => _captureAndIdentify());
}
Future<void> _captureAndIdentify() async {
if (!_controller!.value.isInitialized || _controller!.value.isTakingPicture) return;
final tempDir = await getTemporaryDirectory();
final imagePath = '${tempDir.path}/${DateTime.now().millisecondsSinceEpoch}.jpg';
final file = await _controller!.takePicture();
final imageFile = File(file.path);
final base64Image = await encodeImageToBase64(imageFile);
try {
final result = await identifyPlant(base64Image);
final name = result['suggestions']?[0]?['plant_name'] ?? 'Unknown';
setState(() => _result = name);
} catch (e) {
setState(() => _result = 'Error');
}
}
@override
void dispose() {
_timer?.cancel();
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_controller == null || !_controller!.value.isInitialized) {
return const Scaffold(body: Center(child: CircularProgressIndicator()));
}
return Scaffold(
appBar: AppBar(title: const Text('실시간 식물 인식')),
body: Stack(
children: [
CameraPreview(_controller!),
if (_result != null)
Positioned(
bottom: 32,
left: 16,
right: 16,
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.6),
borderRadius: BorderRadius.circular(12),
),
child: Text(
'인식 결과: $_result',
style: const TextStyle(color: Colors.white, fontSize: 16),
textAlign: TextAlign.center,
),
),
),
],
),
);
}
}
✅ 작동 흐름
- 카메라가 켜지고 5초마다 사진 1장 캡처
- 서버로 전송하여 식물 이름 분석
- 인식된 이름을 화면 아래쪽에 표시
🧪 팁 & 개선 방향
- 일정 거리 이상 이동하거나, 프레임 차이 클 때만 캡처하도록 개선 가능
- 사용자가 “중지/시작” 버튼을 누를 수 있게 인터페이스 추가할 수도 있음
- 실시간 오버레이 개선: 인식 정확도, 유사 이미지도 함께 표시 가능
다음 에피소드 예고
#10. 앱 완성 및 배포 준비
- 앱 아이콘/스플래시 화면 설정
- Android/iOS 빌드 및 테스트
- 블로그 시리즈 정리 및 깃허브 공유 준비
반응형
'06. 앱' 카테고리의 다른 글
| 00020. [APP-00003] AI 음식 영양 분석 앱 개발기 #1 – 기획과 방향 설정 (0) | 2025.04.15 |
|---|---|
| 00019. [APP-00002] 사진 기반 식물/동물 인식 앱 개발기 #10 (0) | 2025.04.05 |
| 00017. [APP-00002] 사진 기반 식물/동물 인식 앱 개발기 #8 (0) | 2025.04.05 |
| 00016. [APP-00002] 사진 기반 식물/동물 인식 앱 개발기 #7 (0) | 2025.04.05 |
| 00015. [APP-00002] 사진 기반 식물/동물 인식 앱 개발기 #6 (0) | 2025.04.05 |