You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by te...@apache.org on 2020/03/05 12:03:51 UTC

[incubator-streampipes] branch image-labeling updated: [STREAMPIPES-78] add mockup rest endpoints to get image, mock saving after changes

This is an automated email from the ASF dual-hosted git repository.

tex pushed a commit to branch image-labeling
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git


The following commit(s) were added to refs/heads/image-labeling by this push:
     new b600d26  [STREAMPIPES-78] add mockup rest endpoints to get image, mock saving after changes
b600d26 is described below

commit b600d268f2bafe4cbef33a91c16fb7a5f9d44d15
Author: tex <te...@fzi.de>
AuthorDate: Thu Mar 5 13:03:35 2020 +0100

    [STREAMPIPES-78] add mockup rest endpoints to get image, mock saving after changes
---
 .../datalake/datalake-rest.service.ts              | 15 ++++-
 .../imageLabeler/annotation/imageAnnotation.ts     | 16 +++++-
 .../classification/imageClassification.ts          | 15 ++++-
 .../imageLabeler/imageLabeler.component.css        |  1 +
 .../imageLabeler/imageLabeler.component.html       | 22 +++-----
 .../core-ui/imageLabeler/imageLabeler.component.ts | 66 +++++++++++++++++++---
 6 files changed, 107 insertions(+), 28 deletions(-)

diff --git a/ui/src/app/core-services/datalake/datalake-rest.service.ts b/ui/src/app/core-services/datalake/datalake-rest.service.ts
index 43f780f..a041d70 100644
--- a/ui/src/app/core-services/datalake/datalake-rest.service.ts
+++ b/ui/src/app/core-services/datalake/datalake-rest.service.ts
@@ -105,8 +105,19 @@ export class DatalakeRestService {
         return this.http.request(request)
     }
 
-    getImage(path) {
-
+    getImageSrcs() {
+        return [
+          'https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg',
+          'https://cdn.pixabay.com/photo/2014/04/02/19/32/dead-end-308178_1280.jpg',
+          'https://cdn.pixabay.com/photo/2015/05/01/14/46/new-york-748595_1280.jpg',
+          'https://cdn.pixabay.com/photo/2015/02/13/10/18/stop-634941_1280.jpg',
+          'https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg',
+          'https://cdn.pixabay.com/photo/2017/04/23/08/43/new-york-2253292_1280.jpg',
+          'https://cdn.pixabay.com/photo/2015/05/01/14/46/new-york-748595_1280.jpg',
+          'https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg',
+          'https://cdn.pixabay.com/photo/2015/02/13/10/18/stop-634941_1280.jpg',
+          'https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg',
+        ];
     }
 
     getLabels() {
diff --git a/ui/src/app/core-ui/imageLabeler/annotation/imageAnnotation.ts b/ui/src/app/core-ui/imageLabeler/annotation/imageAnnotation.ts
index 42d82db..a97afc0 100644
--- a/ui/src/app/core-ui/imageLabeler/annotation/imageAnnotation.ts
+++ b/ui/src/app/core-ui/imageLabeler/annotation/imageAnnotation.ts
@@ -29,9 +29,15 @@ export class ImageAnnotation {
   private selectedAnnotation;
 
   private coco: CocoFormat;
+  private src;
+  public saved: boolean = true;
 
-  newImage(imageName, width, height) {
+
+  newImage(src, imageName, width, height) {
+    this.src = src;
+    //TODO get Coco file form backend if exists
     this.coco = new CocoFormat(imageName, width, height);
+    this.saved = true;
   }
 
   mouseDown(imageCord, scale) {
@@ -46,11 +52,13 @@ export class ImageAnnotation {
       ReactAnnotationUtil.mouseDownTransform(imageCord,
         this.selectedAnnotation, scale)
     } else if (this.interactionMode == AnnotationMode.PolygonLabeling){
+      this.saved = false;
       PolygonAnnotationUtil.mouseDownCreate(imageCord)
     }
   }
 
   mouseMover(imageCord, imageXShift, imageYShift, context, label) {
+    this.saved = false;
     if (this.interactionMode == AnnotationMode.PolygonTransform){
       PolygonAnnotationUtil.mouseMoveTransform(imageCord, this.selectedAnnotation)
     } else if (this.interactionMode == AnnotationMode.ReactLabeling) {
@@ -74,8 +82,10 @@ export class ImageAnnotation {
     PolygonAnnotationUtil.finishCreate(imageCords, this.coco, labelId)
   }
 
-  getSelectedAnnotation() {
-    return this.selectedAnnotation;
+  save(): boolean {
+    //TODO save coco file in backend
+    this.saved = true;
+    return true;
   }
 
   deleteAnnotation(annotation) {
diff --git a/ui/src/app/core-ui/imageLabeler/classification/imageClassification.ts b/ui/src/app/core-ui/imageLabeler/classification/imageClassification.ts
index f4ab151..f580aa3 100644
--- a/ui/src/app/core-ui/imageLabeler/classification/imageClassification.ts
+++ b/ui/src/app/core-ui/imageLabeler/classification/imageClassification.ts
@@ -21,12 +21,18 @@ import { Injectable } from "@angular/core";
 export class ImageClassification {
 
   private classes: string[];
+  public saved: boolean = true;
+  private src;
 
-  newImage() {
+  newImage(src) {
+    this.saved = true;
+    this.src = src;
+    //TODO get class from backend
     this.classes = [];
   }
 
   addClass(clazz) {
+    this.saved = false;
     this.classes.push(clazz);
   }
 
@@ -35,6 +41,13 @@ export class ImageClassification {
   }
 
   removeClass(clazz) {
+    this.saved = false;
     this.classes = this.classes.filter(c => c != clazz);
   }
+
+  save(): boolean {
+    //todo: save  in backend
+    this.saved = true;
+    return true;
+  }
 }
\ No newline at end of file
diff --git a/ui/src/app/core-ui/imageLabeler/imageLabeler.component.css b/ui/src/app/core-ui/imageLabeler/imageLabeler.component.css
index b94e19f..d8f0592 100644
--- a/ui/src/app/core-ui/imageLabeler/imageLabeler.component.css
+++ b/ui/src/app/core-ui/imageLabeler/imageLabeler.component.css
@@ -27,6 +27,7 @@ canvas {
 }
 
 .imageBar {
+    height: 70px;
     background-color: lightgrey;
 }
 
diff --git a/ui/src/app/core-ui/imageLabeler/imageLabeler.component.html b/ui/src/app/core-ui/imageLabeler/imageLabeler.component.html
index 1c4cef3..fba9a88 100644
--- a/ui/src/app/core-ui/imageLabeler/imageLabeler.component.html
+++ b/ui/src/app/core-ui/imageLabeler/imageLabeler.component.html
@@ -68,6 +68,8 @@
                 <button mat-button (click)="imageAnnotation.setPolygonMode()" [style.background-color]="imageAnnotation.isPolygonMode() ? 'lightgrey' : 'white'"> <mat-icon>details</mat-icon></button>
             </div>
 
+            <button mat-button [disabled]="imageAnnotation.saved && imageClassification.saved" (click)="save()"><mat-icon>save</mat-icon></button>
+
             <canvas (mousedown)="imageMouseDown($event)" (mousemove)="imageMouseMove($event)" (mouseup)="imageMouseUp($event)"
                     #canvas width="800" height="500" (dblclick)="dblclick($event)">
                 Your browser does not support the canvas element.
@@ -106,23 +108,15 @@
     <br />
 
     <div fxLayout="row" fxLayoutAlign="space-around center" >
-        <button mat-icon-button> <mat-icon>keyboard_arrow_left</mat-icon></button>
-
-        <div fxLayout="row" fxLayoutAlign="center " style="height: 70px" class="imageBar">
-            <img src="https://cdn.pixabay.com/photo/2015/05/01/14/46/new-york-748595_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2016/02/19/11/01/taxi-1209542_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2016/02/19/11/01/taxi-1209542_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2015/05/01/14/46/new-york-748595_1280.jpg">
-            <img src="https://cdn.pixabay.com/photo/2017/10/29/21/05/bridge-2900839_1280.jpg">
+        <button mat-icon-button (click)="previousImage()"> <mat-icon>keyboard_arrow_left</mat-icon></button>
+
+        <div fxLayout="row" fxLayoutAlign="center " class="imageBar">
+            <img *ngFor="let src of imagesSrcs; let i = index" src="{{src}}" (click)="imagesSrcIndex = i; changeImage(imagesSrcIndex)"
+                 [style.border]="i == imagesSrcIndex ? '5px solid #39b54a' : 'none'">
         </div>
 
 
-        <button mat-icon-button> <mat-icon>keyboard_arrow_right</mat-icon></button>
+        <button mat-icon-button (click)="nextImage()"> <mat-icon>keyboard_arrow_right</mat-icon></button>
 
     </div>
 </div>
diff --git a/ui/src/app/core-ui/imageLabeler/imageLabeler.component.ts b/ui/src/app/core-ui/imageLabeler/imageLabeler.component.ts
index b698b84..4e18ce3 100644
--- a/ui/src/app/core-ui/imageLabeler/imageLabeler.component.ts
+++ b/ui/src/app/core-ui/imageLabeler/imageLabeler.component.ts
@@ -23,6 +23,7 @@ import { ColorUtil } from "./util/color.util";
 import { ImageAnnotation } from "./annotation/imageAnnotation";
 import { InteractionMode } from "./interactionMode";
 import { ImageClassification } from "./classification/imageClassification";
+import { MatSnackBar } from "@angular/material/snack-bar";
 
 @Component({
   selector: 'sp-image-labeler',
@@ -44,6 +45,8 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
   private isHoverComponent;
 
   //image
+  public imagesSrcs;
+  public imagesSrcIndex;
   private image;
   private imageTranslationX = 0;
   private imageTranslationY = 0;
@@ -58,12 +61,16 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
   //scale
   private scale: number = 1;
 
-  constructor(private restService: DatalakeRestService, public imageAnnotation: ImageAnnotation, public imageClassification: ImageClassification) {
+
+  constructor(private restService: DatalakeRestService, public imageAnnotation: ImageAnnotation, public imageClassification: ImageClassification,
+              private snackBar: MatSnackBar) {
 
   }
 
   ngOnInit(): void {
     //1. get Image Paths
+    this.imagesSrcs = this.restService.getImageSrcs();
+    this.imagesSrcIndex = 0;
     //2. get Images
 
     //3. get Labels
@@ -89,19 +96,20 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
     this.context.lineWidth = 2;
   }
 
-  changeImage(url) {
+  changeImage(index) {
     this.image = new Image();
 
     this.image.onload = () => {
-      this.imageAnnotation.newImage("Test.png", this.image.width, this.image.height);
-      this.imageClassification.newImage();
+      let src = this.imagesSrcs[this.imagesSrcIndex]
+      this.imageAnnotation.newImage(src,"Test.png", this.image.width, this.image.height);
+      this.imageClassification.newImage(src);
       console.log('Image width: ' + this.image.width);
       console.log('Image height: ' + this.image.height);
       this.scale = Math.min(1, this.canvasWidth / this.image.width, this.canvasHeight / this.image.height);
       console.log('Set Scale to: ' + this.scale);
       this.draw();
     };
-    this.image.src = url;
+    this.image.src = this.imagesSrcs[this.imagesSrcIndex];
   }
 
   imageMouseDown(e) {
@@ -200,7 +208,6 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
     this.context.drawImage(this.image, this.canvasWidth / 2 - this.image.width / 2, this.canvasHeight / 2 - this.image.height / 2);
   }
 
-
   endDraw() {
     this.context.restore();
 
@@ -235,9 +242,9 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
       } else {
         let key = event.key;
         switch (key.toLowerCase()) {
-          case 'q': alert('Previous image'); //TODO
+          case 'q': this.previousImage();
             break;
-          case 'e': alert('Next image'); //TODOd
+          case 'e': this.nextImage();
             break;
           case 'w': this.imageTranslationY += 5; this.draw();
             break;
@@ -280,8 +287,48 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
     ]
   }
 
+  save() {
+    let success: boolean;
+
+    if (!this.imageAnnotation.saved) {
+      success = this.imageAnnotation.save();
+    }
+    if (!this.imageClassification.saved) {
+      success = this.imageClassification.save();
+    }
+    if (success) {
+      this.openSnackBar('Saved');
+    } else {
+      this.openSnackBar('Error while saving');
+    }
+  }
+
+  openSnackBar(message: string) {
+    this.snackBar.open(message, '', {
+      duration: 2000,
+      verticalPosition: 'top',
+      horizontalPosition: 'right'
+    });
+  }
+
   //UI Callbacks
 
+  nextImage() {
+    if (this.imagesSrcIndex < this.imagesSrcs.length - 1) {
+      this.save();
+      this.imagesSrcIndex++;
+      this.changeImage(this.imagesSrcIndex);
+    }
+  }
+
+  previousImage() {
+    if (this.imagesSrcIndex > 0) {
+      this.save();
+      this.imagesSrcIndex--;
+      this.changeImage(this.imagesSrcIndex);
+    }
+  }
+
   scroll(e) {
     this.scale += e.wheelDeltaY * (1/6000);
     this.draw();
@@ -319,14 +366,17 @@ export class ImageLabelerComponent implements OnInit, AfterViewInit {
   }
 
   setImageViewInteractionMode() {
+    this.save();
     this.interactionMode = InteractionMode.imageViewing;
   }
 
   setImageAnnotateInteractionMode() {
+    this.save();
     this.interactionMode = InteractionMode.imageAnnotate;
   }
 
   setImageClassifyInteractionMode() {
+    this.save();
     this.interactionMode = InteractionMode.imageClassify;
   }