diff --git a/frontend/pradtice/android/app/src/main/AndroidManifest.xml b/frontend/pradtice/android/app/src/main/AndroidManifest.xml index ca97cf0edb..637dc812e0 100644 --- a/frontend/pradtice/android/app/src/main/AndroidManifest.xml +++ b/frontend/pradtice/android/app/src/main/AndroidManifest.xml @@ -10,8 +10,9 @@ + diff --git a/frontend/pradtice/android/gradle/wrapper/gradle-wrapper.properties b/frontend/pradtice/android/gradle/wrapper/gradle-wrapper.properties index e1ca574ef0..b9b69fee5f 100644 --- a/frontend/pradtice/android/gradle/wrapper/gradle-wrapper.properties +++ b/frontend/pradtice/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip +distributionUrl=dist/gradle-7.6.3-all.zip diff --git a/frontend/pradtice/lib/ObjectRecognitionMode.dart b/frontend/pradtice/lib/ObjectRecognitionMode.dart index ece069e6dc..ce26605913 100644 --- a/frontend/pradtice/lib/ObjectRecognitionMode.dart +++ b/frontend/pradtice/lib/ObjectRecognitionMode.dart @@ -8,11 +8,14 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'dart:async'; import 'package:flutter_vision/flutter_vision.dart'; import 'package:image_picker/image_picker.dart'; +import 'TextToSpeech.dart'; +import 'package:vibration/vibration.dart'; enum Options { none, imagev5, imagev8, imagev8seg, frame } late List cameras; -main() async { + +void main() async { WidgetsFlutterBinding.ensureInitialized(); DartPluginRegistrant.ensureInitialized(); runApp( @@ -22,6 +25,7 @@ main() async { ); } + class ObjectReco extends StatefulWidget { const ObjectReco({Key? key}) : super(key: key); @@ -32,6 +36,7 @@ class ObjectReco extends StatefulWidget { class _ObjectRecoState extends State { late FlutterVision vision; Options option = Options.frame; + @override void initState() { super.initState(); @@ -48,7 +53,8 @@ class _ObjectRecoState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: task(option),); + body: task(option), + ); } Widget task(Options option) { @@ -61,6 +67,7 @@ class _ObjectRecoState extends State { class YoloVideo extends StatefulWidget { final FlutterVision vision; + const YoloVideo({Key? key, required this.vision}) : super(key: key); @override @@ -73,6 +80,8 @@ class _YoloVideoState extends State { CameraImage? cameraImage; bool isLoaded = false; bool isDetecting = false; + TTS tts = TTS(message: ''); + @override void initState() { @@ -80,17 +89,16 @@ class _YoloVideoState extends State { init(); } - init() async { + // 카메라 초기화 + void init() async { cameras = await availableCameras(); controller = CameraController(cameras[0], ResolutionPreset.medium); - controller.initialize().then((value) { - loadYoloModel().then((value) { - setState(() { - isLoaded = true; - isDetecting = false; - yoloResults = []; - }); - }); + await controller.initialize(); + await loadYoloModel(); + setState(() { + isLoaded = true; + isDetecting = false; + yoloResults = []; }); } @@ -115,9 +123,7 @@ class _YoloVideoState extends State { children: [ AspectRatio( aspectRatio: controller.value.aspectRatio, - child: CameraPreview( - controller, - ), + child: CameraPreview(controller), ), ...displayBoxesAroundRecognizedObjects(size), Positioned( @@ -129,26 +135,16 @@ class _YoloVideoState extends State { decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( - width: 5, color: Colors.white, style: BorderStyle.solid), - ), - child: isDetecting - ? IconButton( - onPressed: () async { - stopDetection(); - }, - icon: const Icon( - Icons.stop, - color: Colors.red, - ), - iconSize: 50, - ) - : IconButton( - onPressed: () async { - await startDetection(); - }, - icon: const Icon( - Icons.play_arrow, + width: 5, color: Colors.white, + style: BorderStyle.solid, + ), + ), + child: IconButton( + onPressed: isDetecting ? stopDetection : startDetection, + icon: Icon( + isDetecting ? Icons.stop : Icons.play_arrow, + color: isDetecting ? Colors.red : Colors.white, ), iconSize: 50, ), @@ -158,51 +154,33 @@ class _YoloVideoState extends State { ); } + // YOLO 모델 로드 Future loadYoloModel() async { await widget.vision.loadYoloModel( - labels: 'assets/labels.txt', - modelPath: 'assets/yolov5n.tflite', // 모델 수정 부분 - modelVersion: "yolov5", - numThreads: 2, - useGpu: true); - setState(() { - isLoaded = true; - }); - } - - Future yoloOnFrame(CameraImage cameraImage) async { - final result = await widget.vision.yoloOnFrame( - bytesList: cameraImage.planes.map((plane) => plane.bytes).toList(), - imageHeight: cameraImage.height, - imageWidth: cameraImage.width, - iouThreshold: 0.4, - confThreshold: 0.4, - classThreshold: 0.5); - - if (result.isNotEmpty) { - setState(() { - //코드 수정부분 - print("결과 보여줄게 잘: $result"); - yoloResults = result; - }); - } + labels: 'assets/labels.txt', + modelPath: 'assets/yolov5n.tflite', + modelVersion: "yolov5", + numThreads: 2, + useGpu: true, + ); } + // 객체 탐지 시작 Future startDetection() async { setState(() { isDetecting = true; }); - if (controller.value.isStreamingImages) { - return; + if (!controller.value.isStreamingImages) { + await controller.startImageStream((image) { + if (isDetecting) { + cameraImage = image; + yoloOnFrame(image); + } + }); } - await controller.startImageStream((image) async { - if (isDetecting) { - cameraImage = image; - yoloOnFrame(image); - } - }); } + // 객체 탐지 중지 Future stopDetection() async { setState(() { isDetecting = false; @@ -210,18 +188,97 @@ class _YoloVideoState extends State { }); } + // 카메라 프레임에서 YOLO 객체 탐지 + Future yoloOnFrame(CameraImage cameraImage) async { + final result = await widget.vision.yoloOnFrame( + bytesList: cameraImage.planes.map((plane) => plane.bytes).toList(), + imageHeight: cameraImage.height, + imageWidth: cameraImage.width, + iouThreshold: 0.4, + confThreshold: 0.4, + classThreshold: 0.5, + ); + + if (result.isNotEmpty) { + setState(() { + // 필터링할 클래스 레이블 + List targetLabels = [ + "bicycle", + "car", + "motorbike", + "traffic light", + "fire hydrant", + "stop sign", + "parking meter", + "person", + "chair" + ]; + + // 필터링된 결과를 저장할 리스트 + List> filteredResults = []; + + // 필터링된 결과를 추출 + for (var obj in result) { + if (targetLabels.contains(obj['tag'])) { + filteredResults.add(obj); + } + } + + // 필터링된 결과를 사용하여 작업 수행 + for (var obj in filteredResults) { + double bottomY = obj['box'][1] + obj['box'][3]; + if (bottomY > 730 && targetLabels.contains(obj['tag'])) { + tts.setMessage('위험'); + tts.speak(); + Vibration.vibrate(duration: 500); + } + print("전체 값 : $result"); + print("첫 번째 물체의 바운딩 박스 하단 Y 좌표: $bottomY"); + } + + // 필터링된 결과를 yoloResults에 업데이트 + yoloResults = filteredResults; + }); + } + } + + // 객체를 인식하여 박스 표시 List displayBoxesAroundRecognizedObjects(Size screen) { if (yoloResults.isEmpty) return []; + double factorX = screen.width / (cameraImage?.height ?? 1); double factorY = screen.height / (cameraImage?.width ?? 1); + // 필터링할 클래스 레이블 + List targetLabels = [ + "bicycle", + "car", + "motorbike", + "traffic light", + "fire hydrant", + "stop sign", + "parking meter", + "person", + "chair" + ]; + + // 필터링된 결과를 저장할 리스트 + List> filteredResults = []; + + // 필터링된 결과를 추출 + for (var result in yoloResults) { + if (targetLabels.contains(result['tag'])) { + filteredResults.add(result); + } + } + Color colorPick = const Color.fromARGB(255, 50, 233, 30); - return yoloResults.map((result) { + return filteredResults.map((result) { return Positioned( left: result["box"][0] * factorX, top: result["box"][1] * factorY, - width: (result["box"][2] - result["box"][0]) * factorX, + width: (result["box"][2] - result["box"][0]) * factorX, height: (result["box"][3] - result["box"][1]) * factorY, child: Container( decoration: BoxDecoration( @@ -271,4 +328,3 @@ class PolygonPainter extends CustomPainter { return false; } } - diff --git a/frontend/pradtice/lib/main.dart b/frontend/pradtice/lib/main.dart index 21d87b16c2..d20776d0f8 100644 --- a/frontend/pradtice/lib/main.dart +++ b/frontend/pradtice/lib/main.dart @@ -48,7 +48,7 @@ class _MyHomePageState extends State { super.initState(); tts.setMessage('화면을 탭하세요'); tts.speak(); - sever.getID(); + } @override Widget build(BuildContext context) { diff --git a/frontend/pradtice/lib/sever.dart b/frontend/pradtice/lib/sever.dart index 5ae84acd7a..b4d28a925d 100644 --- a/frontend/pradtice/lib/sever.dart +++ b/frontend/pradtice/lib/sever.dart @@ -3,9 +3,8 @@ import 'package:http/http.dart' as http; // http 사용 패키지 import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:pradtice/location_permission.dart'; //json 변환 패키지 -import 'GetAndroidID.dart'; import 'dart:async'; - +import 'GetAndroidID.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class NaviTap extends StatefulWidget { @@ -80,8 +79,16 @@ class Sever { var distance = '0'; var uuid = ''; + GetID getID = GetID(); + + setid(){ + uuid = getID.id; + print('uuid = $uuid'); + } + Future start_navi() async { + setid(); myLocation.getMyCurrentLocation(); Lat = myLocation.latitude; Lon = myLocation.longitude; @@ -145,12 +152,6 @@ class Sever { } } - getID(){ - GetID getid = GetID(); - uuid = getid.id; - print('uuid : '+uuid); - } - } class testmap extends StatefulWidget { diff --git a/frontend/pradtice/macos/Flutter/GeneratedPluginRegistrant.swift b/frontend/pradtice/macos/Flutter/GeneratedPluginRegistrant.swift index cddf7841e2..94bb9b0bec 100644 --- a/frontend/pradtice/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/frontend/pradtice/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import device_info_plus import file_selector_macos import flutter_tts import geolocator_apple @@ -12,6 +13,7 @@ import path_provider_foundation import speech_to_text_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) diff --git a/frontend/pradtice/pubspec.lock b/frontend/pradtice/pubspec.lock index e2cb739e41..245ba3f5dd 100644 --- a/frontend/pradtice/pubspec.lock +++ b/frontend/pradtice/pubspec.lock @@ -201,6 +201,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.6" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91 + url: "https://pub.dev" + source: hosted + version: "10.1.0" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" fake_async: dependency: transitive description: @@ -310,7 +326,7 @@ packages: flutter_vision: dependency: "direct main" description: - path: "C:\\Users\\User\\Desktop\\capstone-5.7R\\frontend\\flutter_vision-master" + path: "C:\\asdf\\capstone-2024-23\\frontend\\flutter_vision-master" relative: false source: path version: "1.1.4" @@ -1012,6 +1028,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vibration: + dependency: "direct main" + description: + name: vibration + sha256: "778ace40e84852e6cf6017cdbaf6790a837d73ff3dd50b27da9ac232a19de8fc" + url: "https://pub.dev" + source: hosted + version: "1.8.4" vm_service: dependency: transitive description: @@ -1060,6 +1084,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.4" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "1c52f994bdccb77103a6231ad4ea331a244dbcef5d1f37d8462f713143b0bfae" + url: "https://pub.dev" + source: hosted + version: "1.1.0" xdg_directories: dependency: transitive description: diff --git a/frontend/pradtice/pubspec.yaml b/frontend/pradtice/pubspec.yaml index 551bf59395..fe9f882bb8 100644 --- a/frontend/pradtice/pubspec.yaml +++ b/frontend/pradtice/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: camera: ^0.9.8+1 image_picker: ^0.8.6+3 flutter_speed_dial: ^6.2.0 + vibration : ^1.7.3 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -48,7 +49,7 @@ dependencies: provider: ^6.0.3 flutter_vision: # 로드 되어있는 flutter_vision-master 경로로 설정! - path: C:\Users\User\Desktop\capstone-5.7R\frontend\flutter_vision-master + path: C:\asdf\capstone-2024-23\frontend\flutter_vision-master # tmap_ui_sdk: # git: