public void TrainSet(EncogOCR_SketchData[] sketches, bool shouldGenerateGarbage = true) { // Assign a token so that only the latest result will be used long token = TokenGenerator.NextToken(); _currentToken = token; _parent.lblTraining.Content = "training..."; // Kill existing tasks //NOTE: Removing from the list is done in the continue foreach (var runningTask in _currentTasks) { runningTask.Item2.Cancel(); } // Group the sketches by name var groupedSketches = sketches.ToLookup(o => o.Name). Select(o => Tuple.Create(o.Key, o.Select(p => p).ToArray())). ToArray(); if (groupedSketches.Length == 0) { _parent._network = null; _parent.lblTraining.Content = ""; return; } TrainNetwork(groupedSketches, token, shouldGenerateGarbage); }
private void AddSketch(EncogOCR_SketchData sketch) { _prevSketches.Add(sketch); // Find existing name node TreeViewItem nameNode = null; foreach (TreeViewItem node in pnlPreviousDrawings.Items) { if (((string)node.Header).Equals(sketch.Name, StringComparison.OrdinalIgnoreCase)) { nameNode = node; break; } } if (nameNode == null) { // Create new nameNode = new TreeViewItem() { Header = sketch.Name }; pnlPreviousDrawings.Items.Add(nameNode); } // Add the image control to this name node nameNode.Items.Add(sketch.ImageControl); nameNode.IsExpanded = true; #region Update the sketch name combo string currentText = cboDrawingLabel.Text; cboDrawingLabel.Items.Clear(); foreach (string comboItem in _prevSketches.Select(o => o.Name).Distinct().OrderBy(o => o)) { cboDrawingLabel.Items.Add(comboItem); } cboDrawingLabel.Text = currentText; #endregion }
/// <summary> /// This compares the strokes (ignores token) /// </summary> private static bool IsSame_Strokes(EncogOCR_SketchData sketch1, EncogOCR_SketchData sketch2) { if (sketch1.Strokes.Length != sketch2.Strokes.Length) { return(false); } if (!Enumerable.Range(0, sketch1.Strokes.Length). All(o => { if (sketch1.Strokes[o].Points.Length != sketch2.Strokes[o].Points.Length) { return(false); } if (sketch1.Strokes[o].Color != sketch2.Strokes[o].Color) { return(false); } if (!sketch1.Strokes[o].Thickness.IsNearValue(sketch2.Strokes[o].Thickness)) { return(false); } return(true); })) { return(false); } // Compare each point for (int outer = 0; outer < sketch1.Strokes.Length; outer++) { for (int inner = 0; inner < sketch1.Strokes[outer].Points.Length; inner++) { if (!Math2D.IsNearValue(sketch1.Strokes[outer].Points[inner], sketch2.Strokes[outer].Points[inner])) { return(false); } } } return(true); }
private void btnStoreDrawing_Click(object sender, RoutedEventArgs e) { try { if (cboDrawingLabel.Text == "") { MessageBox.Show("Please give this drawing a name", this.Title, MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (_currentSketch == null) { RedrawSmallImage(); } #region Create sketch for storage EncogOCR_SketchData sketch = new EncogOCR_SketchData() { Name = cboDrawingLabel.Text, InkCanvasSize = new Size(canvasInk.ActualWidth, canvasInk.ActualHeight), Strokes = _currentSketch.Strokes.ToArray(), }; sketch.GenerateBitmap(_pixels); sketch.GenerateImageControl(); #endregion AddSketch(sketch); TrainNetwork(); //NOTE: Event listeners will clear the rest based on this canvasInk.Strokes.Clear(); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// It's ok to add the same sketch multiple times. Only one copy will be kept (based on token) /// </summary> public void AddSketch(EncogOCR_SketchData sketch) { if (_vectorImages.Any(o => o.Token == sketch.Token)) { // Already have it return; } else if (sketch.Strokes.Length == 0 && _vectorImages.Any(o => o.Strokes.Length == 0)) { // Only store one blank image return; } else if (_vectorImages.AsParallel().Any(o => IsSame_Strokes(o, sketch))) { // When they draw a test image, it gets added. Then when they hit store, a duplicate gets added (different token), so // look for an exact dupe return; } _vectorImages.Add(sketch); EnsureDotCreated(sketch); }
/// <summary> /// This clears everything except: /// session names out of the combo box /// pixels /// pen size /// </summary> private void ClearEverything() { if (_visualizer != null) { _visualizer.Clear(); } _currentSketch = null; grdGuessDetails.Children.Clear(); grdGuessDetails.RowDefinitions.Clear(); pnlPreviousDrawings.Items.Clear(); _prevSketches.Clear(); cboDrawingLabel.Items.Clear(); canvasInk.Strokes.Clear(); _network = null; RedrawSmallImage(); RedrawPreviousImages(true); }
private void RedrawSmallImage() { //canvasPixels.Source = UtilityWPF.RenderControl(canvasInk, _pixels, _pixels, true); _currentSketch = new EncogOCR_SketchData() { Name = cboDrawingLabel.Text, Strokes = canvasInk.Strokes. Select(o => new EncogOCR_StrokeDefinition(o)). ToArray(), InkCanvasSize = new Size(canvasInk.ActualWidth, canvasInk.ActualHeight), }; _currentSketch.GenerateBitmap(_pixels); canvasPixels.Source = _currentSketch.Bitmap; RecognizeImage(); if (_visualizer != null) { _visualizer.AddSketch(_currentSketch.Clone()); } }
private void EnsureDotCreated(EncogOCR_SketchData sketch) { if (_dots == null) { return; } else if (_dots.Dots.Any(o => o.Token == sketch.Token)) { return; } Dot dot = new Dot(sketch.Token) { VectorSource = sketch.Clone(), // cloning to ensure the sketch passed in doesn't get manipulated. NOTE: The clone will have a different token Position = Math3D.GetRandomVector_Spherical(RADIUS).ToPoint(), }; _dots.Dots.Add(dot); if (_networkOutputs != null) { ReconstructDot(dot); } }
private static SketchSample[] TestSamples_InputOutput(TrainedNework_Simple network, EncogOCR_SketchData[] inputSketches) { List<SketchSample> retVal = new List<SketchSample>(); int inputSize = network.Network.InputCount; int outputSize = network.Network.OutputCount; // Inputs foreach (EncogOCR_SketchData input in inputSketches) { double[] output = new double[outputSize]; network.Network.Compute(input.NNInput, output); retVal.Add(new SketchSample() { NNInput = input.NNInput, NNOutput = output }); } // Solid Colors for (int cntr = 0; cntr <= 16; cntr++) { double val = cntr / 16d; double[] input = Enumerable.Range(0, inputSize).Select(o => val).ToArray(); double[] output = new double[outputSize]; network.Network.Compute(input, output); retVal.Add(new SketchSample() { NNInput = input, NNOutput = output }); } //TODO: Generate random brush stroke images //TODO: Generate random pixelated images return retVal.ToArray(); }
private void StrokeCollection_StrokesChanged(object sender, System.Windows.Ink.StrokeCollectionChangedEventArgs e) { try { EncogOCR_SketchData sketch = new EncogOCR_SketchData() { Name = "", Strokes = canvasInk.Strokes. Select(o => new EncogOCR_StrokeDefinition(o)). ToArray(), InkCanvasSize = new Size(canvasInk.ActualWidth, canvasInk.ActualHeight), }; sketch.GenerateBitmap(IMAGESIZE); // The bitmap is white on black, switch to black on white double[] inverted = sketch.NNInput. Select(o => 1d - o). ToArray(); double[] converted = inverted; if (_patternStorage != null) { converted = _patternStorage.Convert_Local_External(converted); } DrawImage(imageCurrent, converted); panelGuessedImages.Children.Clear(); if (_patternStorage != null) { double[][] recognized = _patternStorage.Recognize(inverted); #region show thumbnails if (recognized != null) { foreach (var guessImage in recognized) { DrawImage(panelGuessedImages.Children, guessImage); } } #endregion } } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
private static void GenerateGarbageData(EncogOCR_SketchData[] sketches, int outputSize, List<double[]> inputs, List<double[]> outputs) { #region validate #if DEBUG if (sketches.Select(o => o.BitmapColors.Width).Distinct().Count() != 1 || sketches.Select(o => o.BitmapColors.Height).Distinct().Count() != 1) { throw new ApplicationException("Stored images are different sizes"); } #endif #endregion double[] zeroOutput = Enumerable.Range(0, outputSize).Select(o => 0d).ToArray(); #region efficient if only a final is needed //Color[][] colors = sketches. // Select(o => o.BitmapColors.GetColors(0, 0, o.Bitmap.PixelWidth, o.Bitmap.PixelHeight)). // ToArray(); //bool[] isBlack = Enumerable.Range(0, colors[0].Length). // AsParallel(). // Select(o => new { Index = o, IsBlack = colors.Any(p => p[o].A > 200 && Math3D.Avg(p[o].R, p[o].G, p[o].B) < 20) }). // OrderBy(o => o.Index). // Select(o => o.IsBlack). // ToArray(); #endregion // Figure out which pixels of each sketch are black bool[][] isBlack = sketches. Select(o => o.BitmapColors.GetColors(0, 0, o.BitmapColors.Width, o.BitmapColors.Height)). Select(o => o.Select(p => p.A > 200 && Math1D.Avg(p.R, p.G, p.B) < 20).ToArray()). ToArray(); // Or the images together bool[] composite = Enumerable.Range(0, isBlack[0].Length). AsParallel(). Select(o => new { Index = o, IsBlack = isBlack.Any(p => p[o]) }). OrderBy(o => o.Index). Select(o => o.IsBlack). ToArray(); #region Blank sketch double[] percentBlack = isBlack. Select(o => o.Sum(p => p ? 1d : 0d) / o.Length). ToArray(); if (percentBlack.All(o => o > .01)) { // None of the inputs are blank, so make blank a garbage state inputs.Add(Enumerable.Range(0, composite.Length).Select(o => 0d).ToArray()); outputs.Add(zeroOutput); } #endregion #region Inverted sketch // Making this, because the assumption is that if they draw in a region outside any of the inputs, then it should be a zero output inputs.Add(composite.Select(o => o ? 0d : 1d).ToArray()); outputs.Add(zeroOutput); #endregion //TODO: Do a few subsets of inverted }
/// <summary> /// This compares the strokes (ignores token) /// </summary> private static bool IsSame_Strokes(EncogOCR_SketchData sketch1, EncogOCR_SketchData sketch2) { if (sketch1.Strokes.Length != sketch2.Strokes.Length) { return false; } if (!Enumerable.Range(0, sketch1.Strokes.Length). All(o => { if (sketch1.Strokes[o].Points.Length != sketch2.Strokes[o].Points.Length) return false; if (sketch1.Strokes[o].Color != sketch2.Strokes[o].Color) return false; if (!sketch1.Strokes[o].Thickness.IsNearValue(sketch2.Strokes[o].Thickness)) return false; return true; })) { return false; } // Compare each point for (int outer = 0; outer < sketch1.Strokes.Length; outer++) { for (int inner = 0; inner < sketch1.Strokes[outer].Points.Length; inner++) { if (!Math2D.IsNearValue(sketch1.Strokes[outer].Points[inner], sketch2.Strokes[outer].Points[inner])) { return false; } } } return true; }
private static SketchDots TestSamples(TrainedNework_Simple network, EncogOCR_SketchData[] inputSketches, double[] hues) { // Run a bunch of test images through the NN //NOTE: Only .NNInput and .NNOutput props are populated SketchSample[] sketches = TestSamples_InputOutput(network, inputSketches); // Build a visual with each sketch as a dot Visual3D visual = TestSamples_Draw(sketches, hues); // Calculate the forces between each sketch Tuple<int, int, double>[] distance_Input, distance_Output; TestSamples_Distance(out distance_Input, out distance_Output, sketches); return new SketchDots() { Sketches = sketches, Visual = visual, Distances_Input = distance_Input, Distances_Output = distance_Output, }; }