Pārlūkot izejas kodu

fixed drawing boxes on fruit isses

Dr-Swopt 1 nedēļu atpakaļ
vecāks
revīzija
8e8f687551

+ 5 - 0
frontend/angular.json

@@ -36,6 +36,11 @@
                 "glob": "**/*",
                 "input": "src/assets",
                 "output": "/assets/"
+              },
+              {
+                "glob": "{*.js,*.wasm}",
+                "input": "src/assets/tflite-wasm",
+                "output": "/"
               }
             ],
             "styles": [

+ 26 - 11
frontend/src/app/components/analyzer/analyzer.component.ts

@@ -68,17 +68,38 @@ export class AnalyzerComponent implements OnInit {
     const reader = new FileReader();
     reader.onload = (e: any) => {
       this.previewUrl = e.target.result;
-      this.results = null;
+      this.resetAnalysisState(); // Full UI wipe on new selection
     };
     reader.readAsDataURL(file);
   }
 
   onModeChange(newMode: any): void {
     this.inferenceService.mode.set(newMode as InferenceMode);
+    this.resetAnalysisState();
   }
 
   onEngineChange(newEngine: any): void {
     this.inferenceService.localEngine.set(newEngine as LocalEngine);
+    this.resetAnalysisState();
+  }
+
+  // Global state resetter
+  private resetAnalysisState(): void {
+    this.results = null; // Clears the results panel
+    this.inferenceService.detections.set([]); // Clears global detection signal
+    this.inferenceService.summary.set({}); // Resets the industrial counts
+    this.clearCanvas(); // Wipes the drawing surface
+  }
+
+  // Add this helper method to clear the viewport
+  private clearCanvas(): void {
+    if (this.canvas && this.canvas.nativeElement) {
+      const canvas = this.canvas.nativeElement;
+      const ctx = canvas.getContext('2d');
+      if (ctx) {
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+      }
+    }
   }
 
   async analyze(): Promise<void> {
@@ -144,12 +165,12 @@ export class AnalyzerComponent implements OnInit {
     if (!ctx) return;
 
     const img = new Image();
+    // For now we use the local previewUrl to keep things stable
     img.src = this.previewUrl;
+
     img.onload = () => {
       const canvas = this.canvas.nativeElement;
       const containerWidth = canvas.parentElement!.clientWidth;
-      
-      // Calculate display scale factor
       const displayScale = containerWidth / img.width;
       
       canvas.width = containerWidth;
@@ -160,14 +181,8 @@ export class AnalyzerComponent implements OnInit {
       detections.forEach((det: any) => {
         let x1: number, y1: number, x2: number, y2: number;
 
-        if (this.inferenceService.mode() === 'api') {
-          x1 = det.box[0] * canvas.width;
-          y1 = det.box[1] * canvas.height;
-          x2 = det.box[2] * canvas.width;
-          y2 = det.box[3] * canvas.height;
-        } else {
-          [x1, y1, x2, y2] = det.box.map((v: number) => v * displayScale);
-        }
+        // Apply consistent 'displayScale' for both API and Local modes
+        [x1, y1, x2, y2] = det.box.map((v: number) => v * displayScale);
         
         ctx.strokeStyle = det.color || '#00A651';
         ctx.lineWidth = 3;

+ 12 - 11
frontend/src/app/core/services/inference.service.ts

@@ -23,7 +23,7 @@ export class InferenceService {
     private readonly localInferenceService: LocalInferenceService,
     private readonly remoteInferenceService: RemoteInferenceService,
     private readonly imageProcessor: ImageProcessorService
-  ) {}
+  ) { }
 
   /**
    * Main analyze entry point. imageData is base64 string.
@@ -42,8 +42,8 @@ export class InferenceService {
 
     const file = new File([blob], 'capture.jpg', { type: 'image/jpeg' });
 
-    const modelPath = this.localEngine() === 'onnx' 
-      ? 'assets/models/onnx/best.onnx' 
+    const modelPath = this.localEngine() === 'onnx'
+      ? 'assets/models/onnx/best.onnx'
       : 'assets/models/tflite/best_float32.tflite';
 
     return from(this.localInferenceService.loadModel(modelPath)).pipe(
@@ -70,6 +70,7 @@ export class InferenceService {
 
     return this.remoteInferenceService.analyze(blob).pipe(
       map((response: AnalysisResponse) => {
+        // console.log(response)
         const mappedDets = response.detections.map(det => ({
           box: det.box,
           confidence: det.confidence,
@@ -77,10 +78,10 @@ export class InferenceService {
           color: this.getGradeColor(det.class),
           is_health_alert: det.is_health_alert
         }));
-        
+
         this.detections.set(mappedDets);
-        this.summary.set({ ...response.industrial_summary }); 
-        
+        this.summary.set({ ...response.industrial_summary });
+
         return mappedDets;
       }),
       catchError(err => {
@@ -91,8 +92,8 @@ export class InferenceService {
   }
 
   private calculateSummary(detections: any[]): any {
-    const summary: any = { 
-        'Empty_Bunch': 0, 'Underripe': 0, 'Abnormal': 0, 'Ripe': 0, 'Unripe': 0, 'Overripe': 0 
+    const summary: any = {
+      'Empty_Bunch': 0, 'Underripe': 0, 'Abnormal': 0, 'Ripe': 0, 'Unripe': 0, 'Overripe': 0
     };
     detections.forEach(d => { if (summary[d.class] !== undefined) summary[d.class]++; });
     return summary;
@@ -107,7 +108,7 @@ export class InferenceService {
       const ab = new ArrayBuffer(byteString.length);
       const ia = new Uint8Array(ab);
       for (let i = 0; i < byteString.length; i++) {
-          ia[i] = byteString.charCodeAt(i);
+        ia[i] = byteString.charCodeAt(i);
       }
       return new Blob([ab], { type: mimeString });
     } catch (e) {
@@ -118,8 +119,8 @@ export class InferenceService {
 
   private getGradeColor(className: string): string {
     const colors: { [key: string]: string } = {
-        'Empty_Bunch': '#6C757D', 'Underripe': '#F9A825', 'Abnormal': '#DC3545',
-        'Ripe': '#00A651', 'Unripe': '#9E9D24', 'Overripe': '#5D4037'
+      'Empty_Bunch': '#6C757D', 'Underripe': '#F9A825', 'Abnormal': '#DC3545',
+      'Ripe': '#00A651', 'Unripe': '#9E9D24', 'Overripe': '#5D4037'
     };
     return colors[className] || '#000000';
   }