@@ -22,7 +22,7 @@ use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
2222use image:: { DynamicImage , ImageBuffer , Rgba } ;
2323use tauri:: Emitter ;
2424use crate :: modules:: yolo:: services:: desktop_capture:: {
25- MonitorInfo , DesktopCaptureFrame , DesktopCaptureStatus ,
25+ MonitorInfo , DesktopCaptureFrame , DesktopCaptureStatus , AnnotationBox ,
2626} ;
2727use crate :: modules:: yolo:: services:: inference_engine:: InferenceEngine ;
2828
@@ -168,55 +168,66 @@ impl AsyncDesktopCaptureService {
168168 if let Some ( ref engine) = inference {
169169 let detect_start = Instant :: now ( ) ;
170170
171- // Convert image to RGB bytes
172- let rgba_data = image. into_raw ( ) ;
171+ // Convert to DynamicImage
172+ let dynamic_img = DynamicImage :: ImageRgba8 ( image. clone ( ) ) ;
173173
174- match engine. detect ( & rgba_data, width, height, confidence) {
175- Ok ( boxes) => {
176- let detect_time = detect_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
177-
178- // Encode image to base64
179- let encode_start = Instant :: now ( ) ;
180- let img_buffer = ImageBuffer :: < Rgba < u8 > , Vec < u8 > > :: from_raw ( width, height, rgba_data)
181- . unwrap_or_else ( || ImageBuffer :: new ( width, height) ) ;
182- let dynamic_img = DynamicImage :: ImageRgba8 ( img_buffer) ;
183- let mut jpg_data = Vec :: new ( ) ;
184- let mut cursor = std:: io:: Cursor :: new ( & mut jpg_data) ;
185- dynamic_img. write_to ( & mut cursor, image:: ImageFormat :: Jpeg )
186- . map_err ( |e| format ! ( "Failed to encode: {:?}" , e) ) . ok ( ) ;
187- let base64_image = BASE64 . encode ( & jpg_data) ;
188- let encode_time = encode_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
189-
190- let total_time = frame_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
191- let fps = ( 1000.0 / total_time) as f32 ;
192-
193- // Emit frame to frontend
194- let frame = DesktopCaptureFrame {
195- session_id : session_id_clone. clone ( ) ,
196- image : base64_image,
197- boxes,
198- width,
199- height,
200- fps,
201- timestamp : std:: time:: SystemTime :: now ( )
202- . duration_since ( std:: time:: UNIX_EPOCH )
203- . unwrap ( )
204- . as_secs ( ) ,
205- } ;
206-
207- let emit_start = Instant :: now ( ) ;
208- app_handle. emit ( "desktop-frame" , & frame) . ok ( ) ;
209- let emit_time = emit_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
210-
211- eprintln ! (
212- "[AsyncCap-Perf] capture: {:.1}ms | detect: {:.1}ms | encode: {:.1}ms | emit: {:.1}ms | total: {:.1}ms | FPS: {:.1}" ,
213- capture_time, detect_time, encode_time, emit_time, total_time, fps
214- ) ;
215- }
216- Err ( e) => {
217- eprintln ! ( "[AsyncCapture] Detection error: {}" , e) ;
174+ // Run inference
175+ let boxes = engine. detect ( & dynamic_img, confidence) ;
176+ let detect_time = detect_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
177+
178+ // Encode image to base64
179+ let encode_start = Instant :: now ( ) ;
180+ let rgba_data = image. into_raw ( ) ; // 转换为RGBA数据用于编码
181+ let img_buffer = ImageBuffer :: < Rgba < u8 > , Vec < u8 > > :: from_raw ( width, height, rgba_data)
182+ . unwrap_or_else ( || ImageBuffer :: new ( width, height) ) ;
183+ let dynamic_img_for_encode = DynamicImage :: ImageRgba8 ( img_buffer) ;
184+ let mut jpg_data = Vec :: new ( ) ;
185+ let mut cursor = std:: io:: Cursor :: new ( & mut jpg_data) ;
186+ dynamic_img_for_encode. write_to ( & mut cursor, image:: ImageFormat :: Jpeg )
187+ . map_err ( |e| format ! ( "Failed to encode: {:?}" , e) ) . ok ( ) ;
188+ let base64_image = BASE64 . encode ( & jpg_data) ;
189+ let encode_time = encode_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
190+
191+ let total_time = frame_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
192+ let fps = ( 1000.0 / total_time) as f32 ;
193+
194+ // Convert DetectionBox to AnnotationBox
195+ let boxes: Vec < AnnotationBox > = boxes. iter ( ) . enumerate ( ) . map ( |( idx, b) | {
196+ AnnotationBox {
197+ id : format ! ( "det_{}" , idx) ,
198+ class_id : b. class_id ,
199+ class_name : b. class_name . clone ( ) ,
200+ confidence : b. confidence ,
201+ x : b. x ,
202+ y : b. y ,
203+ width : b. width ,
204+ height : b. height ,
218205 }
219- }
206+ } ) . collect ( ) ;
207+
208+ // Emit frame to frontend
209+ let frame = DesktopCaptureFrame {
210+ session_id : session_id_clone. clone ( ) ,
211+ image : base64_image,
212+ boxes,
213+ width,
214+ height,
215+ fps,
216+ timestamp : std:: time:: SystemTime :: now ( )
217+ . duration_since ( std:: time:: UNIX_EPOCH )
218+ . unwrap ( )
219+ . as_secs ( ) ,
220+ } ;
221+
222+ // Emit frame to frontend
223+ let emit_start = Instant :: now ( ) ;
224+ app_handle. emit ( "desktop-frame" , & frame) . ok ( ) ;
225+ let emit_time = emit_start. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
226+
227+ eprintln ! (
228+ "[AsyncCap-Perf] capture: {:.1}ms | detect: {:.1}ms | encode: {:.1}ms | emit: {:.1}ms | total: {:.1}ms | FPS: {:.1}" ,
229+ capture_time, detect_time, encode_time, emit_time, total_time, fps
230+ ) ;
220231 }
221232 }
222233 Err ( e) => {
0 commit comments