Quantcast
Channel: ppedv Team Blog
Viewing all articles
Browse latest Browse all 1198

AI Trainingsdaten generieren mit Blazor

$
0
0

Auf meiner Reise durch das AI Universum stellte sich die Frage, welches Problem lösen wir. Da finden sich Taxi Fare und House Prices als Regression Beispiele. Oder Hund und Auto Erkennung in Bildern in der Kategorie Vision. 

Also konstruieren wir uns ein Problem. Ein Whiteboard in das der Benutzer per Ink/Pen Figuren zeichnet, die AI erkennt was es ist und an die gleiche Stelle eine korrekt unverwackelte Skizze erstellt, Gibt es schon.

Lösung soll mit Blazor sein. Dazu brauch ich eine Trainings Web App. Sogar Server basiert, damit ich keinen Aufwand mit speichern habe. Recht unspektakulär nehme ich dazu SVG

   1:  <divid="Whiteboard" @ref="Whiteboard"
   2:      @onmousemove="MoveMouse" @onmousedown="DownMouse" @onmouseup="UpMouse"
   3:       @ontouchmove="MoveTouch" @ontouchstart="DownTouch" @ontouchend="UpTouch"draggable="false"
   4:  style="border:2px solid black;display:inline-block;
max-height:80vh;max-width:100vw;overflow:hidden;touch-action: none;"
>
   5:  <svgstyle="width:800px; height:800px;">
   6:          @foreach (var (line, i) in Lines.WithIndex())
   7:          {
   8:  <LineComponentX1=@line.prevXY1=@line.prevY
X2=@line.currXY2=@line.currYStroke=@line.colorStrokeWidth=@line.lineWidth @key="i"/>
   9:          }
  10:  </svg>
  11:  </div>

 

Die Idee ist eine Liste von Linien zu einer Figur zu verbinden. Für einen Kreis nicht ganz so optimal, aber was solls.

   1:  protected List<Line> Lines = new List<Line>();
   2:  protectedbool flag = false;
   3:  protecteddouble prevX = 0;
   4:  protecteddouble currX = 0;
   5:  protecteddouble prevY = 0;
   6:  protecteddouble currY = 0;
   7:  protectedint count = 0;
   8:  protectedint status = 0;
   9:  protectedstring color = "#000000";
  10:  protectedfloat lineWidth = 2;
  11:      ElementReference Whiteboard;
  12:      BoundingClientRect DIVOffset;
  13:  int counter;
  14:  protectedoverride async Task OnAfterRenderAsync(bool firstRender)
  15:      {
  16:  if (firstRender)
  17:          {
  18:              DIVOffset = await JSRuntime.InvokeAsync<BoundingClientRect>(
"eval", "document.getElementById('Whiteboard').getBoundingClientRect()");
  19:          }
  20:   
  21:      }

Der Trick beliebigen JavaScript Code per Eval auszuführen ist nicht fein aber Effektiv um die Position des Boards zu erhalten. Dann führe ich zwei Hilfsklassen ein

   1:  publicclass Line
   2:  {
   3:  public Line() { }
   4:  public Line(double prevX, double prevY, double currX, double currY, string color, float lineWidth)
   5:      {
   6:  this.prevX = prevX;
   7:  this.prevY = prevY;
   8:  this.currX = currX;
   9:  this.currY = currY;
  10:  this.color = color;
  11:  this.lineWidth = lineWidth;
  12:      }
  13:  publicdouble prevX { get; set; }
  14:  publicdouble currX { get; set; }
  15:  publicdouble prevY { get; set; }
  16:  publicdouble currY { get; set; }
  17:  publicstring color { get; set; }
  18:  publicfloat lineWidth { get; set; }
  19:   
  20:  }
  21:   
  22:  publicclass BoundingClientRect
  23:  {
  24:  publicdouble X { get; set; }
  25:  publicdouble Y { get; set; }
  26:  publicdouble Width { get; set; }
  27:  publicdouble Height { get; set; }
  28:  publicdouble Top { get; set; }
  29:  publicdouble Right { get; set; }
  30:  publicdouble Bottom { get; set; }
  31:  publicdouble Left { get; set; }
  32:  }

Den folgenden C# Blazor Code erläutere ich nicht im Detail.

   1:  private async Task MoveMouse(MouseEventArgs e)
   2:   {
   3:       await Move(e.ClientX, e.ClientY);
   4:   }
   5:  private async Task MoveTouch(TouchEventArgs e)
   6:   {
   7:       await Move(e.Touches[0].ClientX, e.Touches[0].ClientY);
   8:   }
   9:  private async Task Move(double clientX, double clientY)
  10:   {
  11:  if (flag)
  12:       {
  13:           prevX = currX;
  14:           prevY = currY;
  15:           currX = clientX - DIVOffset.X;
  16:           currY = clientY - DIVOffset.Y;
  17:           var addedLine = new Line(prevX, prevY, currX, currY, color, lineWidth);
  18:           Lines.Add(addedLine);
  19:           status++;
  20:           count++;
  21:  this.StateHasChanged();
  22:       }
  23:   }
  24:  private async Task DownMouse(MouseEventArgs e)
  25:   {
  26:       await Down(e.ClientX, e.ClientY);
  27:   }
  28:  private async Task DownTouch(TouchEventArgs e)
  29:   {
  30:       await Down(e.Touches[0].ClientX, e.Touches[0].ClientY);
  31:   }

Schon etwas spannender ist der Code wenn der Stift den Bildschirm verlässt. Die Figur ist dann fertig gezeichnet. Allerdings als SVG. Wir brauchen eine Library

NuGet\Install-Package Svg.Skia 
 

Aus dem Line Array wird ein SVG String zusammengesetzt. Danach (Zeile 23) ein SK Bitmap generiert. Ab Zeile 25 wird das SVG in das Bitmap Objekt gezeichnet und am Ende als png (Zeile 23) auf der Festplatt des Webservers abgelegt.

   1:  privatevoid UpTouch(TouchEventArgs e)
   2:  {
   3:   flag = false;
   4:  using (var svg = new SKSvg())
   5:     {
   6:         var sr = new StringBuilder();
   7:         sr.Append("<svg style=\"width: 800px; height: 800px; \">\n");
   8:  foreach (var line in Lines)
   9:          {
  10:          sr.Append($@"<line x1=""{line.prevX.ToString(
CultureInfo.InvariantCulture)}"
" y1 =""{line.prevY.ToString(
CultureInfo.InvariantCulture)}"
"
  11:             x2 =""{line.currX.ToString(CultureInfo.InvariantCulture)}""
y2 ="
"{line.currY.ToString(CultureInfo.InvariantCulture)}"" stroke=""black""
  12:  stroke-width =""{line.lineWidth.ToString(CultureInfo.InvariantCulture)}"" />");
  13:              }
  14:              sr.Append("</svg>");
  15:      }
  16:     var cs = SKColorSpace.CreateSrgb();
  17:     var farbe = SKColor.Parse("#ffffff");
  18:     svg.FromSvg(sr.ToString());
  19:  if (svg.Picture != null)
  20:         {
  21:         var width = (int)svg.Picture.CullRect.Width;
  22:         var height = (int)svg.Picture.CullRect.Height;
  23:  using (var bitmap = new SKBitmap(width, height))
  24:           {
  25:  using (var canvas = new SKCanvas(bitmap))
  26:             {
  27:             canvas.Clear(farbe);
  28:             canvas.DrawPicture(svg.Picture);
  29:             canvas.Flush();
  30:             }
  31:   
  32:  using (var stream = File.OpenWrite($@"c:\temp\viereck{counter}.png"))
  33:            {
  34:             bitmap.Encode(stream, SKEncodedImageFormat.Png, 100);
  35:            }
  36:   
  37:          }
  38:          Lines.Clear();
  39:          counter++;
  40:      }
  41:  }
  42:  
 

Für mein Training habe ich jeweils 50 mal Dreieck, Kreis und Viereck gezeichnet. Den Code geändert und das Blazor Programm neu gestartet.

Im letzten Schritt kann man die Grafiken für zwei verschiedene Model Builder Szenarien aufbereiten, Bild Klassifizierung und Bild Erkennung.

Für die Bilderkennung werden drei Unterordner angelegt, die den Labels entsprechen und die PNG jeweils in den passenden Ordner verschoben,

daten1

Deutlich mehr Aufwand wird benötigt um Objekte in Bildern zu erkennen. Dazu müssen die Labels definiert werden und die Objekte in Position und Größte markiert werden. Auch hier gibt es eine Reihe von Formaten. Microsoft setzt auf VoTT und bietet dafür einen Editor.

Ich habe hier nur jeweils ein Objekt pro Png um das ganze schneller zu erledigen. In der Praxis werden die Objekte auch mehrfach in Bildern vorhanden sein. Ein Hund, Auto oder Person.

vott1

Am Ende werden die Markierungen exportiert. In ein JSON, CSV, Tensorflow oder Azure Custom Vision Service Format.  Um nur einen Auszug zu nennen.

Mit diesen Daten können wir dann ein Training starten. Das aber in einem anderen Blog Beitrag.

 
 
 

Viewing all articles
Browse latest Browse all 1198

Trending Articles


Vimeo 10.7.1 by Vimeo.com, Inc.


UPDATE SC IDOL: TWO BECOME ONE


KASAMBAHAY BILL IN THE HOUSE


Girasoles para colorear


Presence Quotes – Positive Quotes


EASY COME, EASY GO


Love with Heart Breaking Quotes


Re:Mutton Pies (lleechef)


Ka longiing longsem kaba skhem bad kaba khlain ka pynlong kein ia ka...


Vimeo 10.7.0 by Vimeo.com, Inc.


FORECLOSURE OF REAL ESTATE MORTGAGE


FORTUITOUS EVENT


Pokemon para colorear


Sapos para colorear


Smile Quotes


Letting Go Quotes


Love Song lyrics that marks your Heart


RE: Mutton Pies (frankie241)


Hato lada ym dei namar ka jingpyrshah jong U JJM Nichols Roy (Bah Joy) ngin...


Long Distance Relationship Tagalog Love Quotes