Simply3DScan
ScanControl.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.IO;
6 using System.Linq;
7 using System.Windows.Forms;
8 using AForge.Video.DirectShow;
10 using Configuration;
11 using PointWriter;
12 using SharedObjects;
13 using Syncfusion.Windows.Forms.Tools;
14 
15 namespace Simple3DScan.UI
16 {
20  public partial class ScanControl : UserControl
21  {
22  #region fields
23 
27  protected readonly BackgroundWorker ScanWorker = new BackgroundWorker();
28 
32  protected readonly Information ConfigurationInformation = Singleton<Config>.Instance.Information;
33 
37  public ArduinoCommands Arduino { get; set; }
38 
42  protected readonly Dictionary<string, string> VideoSources = new Dictionary<string, string>();
43 
44  #endregion
45 
46  #region events
47  public delegate void StartScan();
54  public event StartScan StartScanning;
58  public delegate void StopScan();
62  public event StopScan StopScanning;
63  #endregion
64 
65  #region Constructor
66 
70  [Log]
71  [LogException]
72  public ScanControl()
73  {
74  this.InitializeComponent();
75  }
76 
77  #endregion
78 
79  #region load
80 
81  [Log]
82  [LogException]
83  private void ScanControl_Load(object sender, EventArgs e)
84  {
85  if(!this.DesignMode)
86  this.InitiateCameraDropdown();
87  }
88 
93  [Log]
94  [LogException]
95  public void Init(ArduinoCommands arduino)
96  {
97  this.Arduino = arduino;
98  this.Arduino.ActivateLaser(false);
99 
100  ButtonRenderer styleRenderer = new ButtonRenderer();
101  this.ToggleButtonCapture.Renderer = styleRenderer;
102 
103  this.RadialSliderPrecision.ValueChanged += this.RadialSliderPrecision_ValueChanged;
104 
105  }
106 
110  [Log]
111  [LogException]
112  protected void InitiateCameraDropdown()
113  {
114  FilterInfoCollection filterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
115 
116  int i = 0;
117  foreach (FilterInfo filterInfo in filterInfoCollection)
118  {
119  this.ComboBoxCameras.Items.Add(filterInfo.Name);
120  this.VideoSources.Add(filterInfo.Name, filterInfo.MonikerString);
121  if (!String.IsNullOrEmpty(this.ConfigurationInformation.Camera.Name) &&
122  filterInfo.Name == this.ConfigurationInformation.Camera.Name)
123  this.ComboBoxCameras.SelectedIndex = i;
124  i++;
125  }
126  }
127 
133  [Log]
134  [LogException]
135  private void buttonRefreshCams_Click(object sender, EventArgs e)
136  {
137  this.ComboBoxCameras.Items.Clear();
138  this.VideoSources.Clear();
139  this.InitiateCameraDropdown();
140  this.ConfigurationInformation.Camera.Name = this.ComboBoxCameras.SelectedItem.ToString();
141  this.ImagingControl.StartImaging(this.ConfigurationInformation.Camera.Name);
142  }
143 
144  #endregion
145 
146  #region dispose
147  [Log]
152  [LogException]
153  protected override void Dispose(bool disposing)
154  {
155  if (disposing && (this.components != null))
156  {
157  this.components.Dispose();
158  }
159  this.ImagingControl.StopImaging();
160 
161  base.Dispose(disposing);
162  }
163  #endregion
164 
165  #region background job
166  [Log]
172  [LogException]
173  protected void ScanWorker_DoWork(object sender, DoWorkEventArgs e)
174  {
175  if (this.StartScanning != null)
176  this.StartScanning();
177  Precision precision = (Precision)e.Argument;
178 
179  string imageFolder = ResetImageFolder(this.ConfigurationInformation);
180 
181  int numberOfTotalSteps;
182  Resolution resolution;
183  GetResolutionAndSteps(precision, this.ConfigurationInformation, out numberOfTotalSteps, out resolution);
184 
185  MoveLaserToLeftStartPosition(this.Arduino, this.ImagingControl, this.ConfigurationInformation);
186 
187  IPointWriter writer;
188  if (!this.InitiateWriter(this.Arduino, this.ConfigurationInformation, out writer))
189  return;
190 
191  if (this.PerformScan(this.Arduino, this.ImagingControl, this.ConfigurationInformation, numberOfTotalSteps, resolution, imageFolder, writer)) return;
192 
193  if (this.ConfigurationInformation.Places.FileFormat == FileFormat.Ascii)
194  this.Arduino.ActivateLaser(false);
195 
196  SavePoints(this, writer, this.ConfigurationInformation);
197  }
198 
204  [LogException]
205  protected void ScanWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
206  {
207  this.RadialGaugeProgress.Value = e.ProgressPercentage;
208  }
209 
215  [Log]
216  [LogException]
217  protected virtual void ScanWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
218  {
219  if (this.StopScanning != null)
220  this.StopScanning();
221 
222  this.ToggleButtonCapture.ToggleState = ToggleButtonState.Inactive;
223  this.ScanWorker.DoWork -= this.ScanWorker_DoWork;
224  this.ScanWorker.ProgressChanged -= this.ScanWorker_ProgressChanged;
225  this.ScanWorker.RunWorkerCompleted -= this.ScanWorker_RunWorkerCompleted;
226  this.Arduino.ActivateLaser(false);
227  }
228 
229  #endregion
230 
231  #region controls
232  [Log]
238  [LogException]
239  protected void ToggleButtonCapture_Click(object sender, EventArgs e)
240  {
241  this.RadialGaugeProgress.Value = 0;
242 
243  if (this.ScanWorker.IsBusy != true)
244  {
245  this.ScanWorker.DoWork += this.ScanWorker_DoWork;
246  this.ScanWorker.ProgressChanged += this.ScanWorker_ProgressChanged;
247  this.ScanWorker.RunWorkerCompleted += this.ScanWorker_RunWorkerCompleted;
248  this.ScanWorker.WorkerReportsProgress = true;
249  this.ScanWorker.WorkerSupportsCancellation = true;
250  this.ScanWorker.RunWorkerAsync((Precision)this.RadialSliderPrecision.Value);
251  }
252  else
253  this.ScanWorker.CancelAsync();
254  }
255 
261  [Log]
262  [LogException]
263  protected void ComboBoxCameras_SelectedIndexChanged(object sender, EventArgs e)
264  {
265  if (!this.VideoSources.ContainsKey(this.ComboBoxCameras.SelectedItem.ToString()))
266  return;
267 
268  this.ConfigurationInformation.Camera.Name = this.ComboBoxCameras.SelectedItem.ToString();
269  this.ConfigurationInformation.Camera.Moniker = this.VideoSources[this.ComboBoxCameras.SelectedItem.ToString()];
270 
271  this.SetMaxFrameSizes(this.ConfigurationInformation.Camera.Moniker);
272 
273  this.ImagingControl.LaserMotorEnabled = this.ConfigurationInformation.Laser.MotorEnabled;
274  this.ImagingControl.LaserLeftPosition = this.ConfigurationInformation.Laser.SwipeMin * this.ConfigurationInformation.Camera.Width / 100;
275  this.ImagingControl.LaserRightPosition = this.ConfigurationInformation.Laser.SwipeMax * this.ConfigurationInformation.Camera.Width / 100;
276 
277  this.ImagingControl.StartImaging(this.ConfigurationInformation.Camera.Name);
278  }
279 
280  [Log]
281  [LogException]
282  private void SetMaxFrameSizes(string monikerString)
283  {
284  VideoCaptureDevice source = new VideoCaptureDevice(monikerString);
285 
286  if (source.VideoCapabilities.Length > 0)
287  {
288  VideoCapabilities max = source.VideoCapabilities.OrderBy(p => p.FrameSize.Width).Last();
289  source.VideoResolution = max;
290  }
291  if (null != source.VideoResolution)
292  {
293  this.ConfigurationInformation.Camera.Height = source.VideoResolution.FrameSize.Height;
294  this.ConfigurationInformation.Camera.Width = source.VideoResolution.FrameSize.Width;
295  }
296  }
297 
298  #endregion
299 
300  #region scan
301 
313  [Log]
314  [LogException]
315  protected IEnumerable<ColorPoint3D> ScanImage(int actualSteps, string imageFolder, int steps, int sweep, ArduinoCommands arduino, CameraControl imaging, Information configuration)
316  {
317  Image image;
318  Image imageOff = null;
319  List<ColorPoint3D> points = new List<ColorPoint3D>();
320 
321  if (!configuration.Laser.MotorEnabled)
322  {
323  if (configuration.Places.FileFormat == FileFormat.Pcd)
324  {
325  arduino.ActivateLaser(false);
326 
327  image = imaging.GetNextPicture();
328 
329  imageOff = (Image) image.Clone();
330  imageOff.SaveImage(imageFolder, "OffLaserLight", actualSteps, configuration); // for autodesk 123d
331 
332  arduino.ActivateLaser();
333  }
334 
335  image = imaging.GetNextPicture();
336 
337  if (configuration.Places.FileFormat == FileFormat.Pcd)
338  arduino.ActivateLaser(false);
339 
340  image.SaveImage(imageFolder, "OnLaserLight", actualSteps, configuration);
341 
342  image = TransformImage.CreateGrayImageOfLaser((Bitmap) image, configuration.Filter);
343  image.SaveImage(imageFolder, "LaserLight", actualSteps, configuration);
344 
345  Image skeletonImage = TransformImage.SimpleSkeletonizationImage((Bitmap) image);
346  skeletonImage.SaveImage(imageFolder, "Skeleton", actualSteps, configuration);
347 
348  points = TransformImage.TransformStepImage(skeletonImage, imageOff, actualSteps,
349  configuration.Motor.MicroStepsEnabled, configuration);
350  }
351 
352  if (configuration.Laser.MotorEnabled)
353  {
354  if (configuration.Places.FileFormat == FileFormat.Pcd)
355  arduino.ActivateLaser();
356 
357  image = imaging.GetNextPicture();
358 
359  float actualX = TransformImage.GetLaserLinePosition(image, configuration.Filter);
360  bool swipeRight = actualX <= configuration.Laser.SwipeMin*configuration.Camera.Width/100;
361 
362  if (swipeRight)
363  {
364  while (TransformImage.GetLaserLinePosition(image, configuration.Filter) <
365  configuration.Laser.SwipeMax*configuration.Camera.Width/100)
366  {
367  if (this.ScanWorker.CancellationPending)
368  return null;
369 
370  arduino.RotateLaserCw(sweep);
371 
372  image = CaptureSweepImage(actualSteps, imaging, configuration, ref points);
373  }
374  }
375  else
376  {
377  while (TransformImage.GetLaserLinePosition(image, configuration.Filter) >
378  configuration.Laser.SwipeMin*configuration.Camera.Width/100)
379  {
380  if (this.ScanWorker.CancellationPending)
381  return null;
382 
383  arduino.RotateLaserCcw(sweep);
384 
385  image = CaptureSweepImage(actualSteps, imaging, configuration, ref points);
386  }
387  }
388  }
389  arduino.RotateTurnTableCw(steps);
390 
391  return points;
392  }
393 
394  [LogException]
395  private static Image CaptureSweepImage(int actualSteps, CameraControl imaging, Information configuration, ref List<ColorPoint3D> points)
396  {
397  Image image = imaging.GetNextPicture();
398  image = TransformImage.CreateGrayImageOfLaser((Bitmap)image, configuration.Filter);
399  Image skeletonImage = TransformImage.SimpleSkeletonizationImage((Bitmap)image);
400 
401  points.AddRange(TransformImage.TransformStepImage(skeletonImage, null, actualSteps,
402  configuration.Motor.MicroStepsEnabled, configuration));
403 
404  image = imaging.GetNextPicture();
405  return image;
406  }
407 
419  [Log]
420  [LogException]
421  protected bool PerformScan(ArduinoCommands arduino, CameraControl cameraControl, Information configuration, int numberOfTotalSteps, Resolution resolution, string imageFolder, IPointWriter writer)
422  {
423  for (int actualSteps = 0; actualSteps <= numberOfTotalSteps; actualSteps += resolution.Steps)
424  {
425  if (this.ScanWorker.CancellationPending)
426  return true;
427 
428  int percentage = actualSteps*100/numberOfTotalSteps;
429 
430  IEnumerable<ColorPoint3D> points = this.ScanImage(actualSteps, imageFolder, resolution.Steps, resolution.SweepSteps, arduino, cameraControl, configuration);
431 
432  if(null != points)
433  foreach (ColorPoint3D point in points)
434  writer.AddPoint(point);
435 
436  this.ScanWorker.ReportProgress(percentage);
437  }
438  return false;
439  }
440 
441  #endregion
442 
443  #region laser
444 
451  [Log]
452  [LogException]
453  protected static void MoveLaserToLeftStartPosition(ArduinoCommands arduino, CameraControl cameraControl, Information configuration)
454  {
455  if (!configuration.Laser.MotorEnabled)
456  return;
457  arduino.ActivateLaser();
458 
459  float actualX = TransformImage.GetLaserLinePosition(cameraControl.GetNextPicture(), configuration.Filter);
460 
461  while (actualX > configuration.Laser.SwipeMin*configuration.Camera.Width/100)
462  {
463  arduino.RotateLaserCcw(4);
464  actualX = TransformImage.GetLaserLinePosition(cameraControl.GetNextPicture(), configuration.Filter);
465  }
466  arduino.RotateLaserCcw(4);
467  arduino.ActivateLaser(false);
468  }
469 
470  #endregion
471 
472  #region resolution
473 
481  [Log]
482  [LogException]
483  protected static void GetResolutionAndSteps(Precision precision, Information configuration, out int numberOfTotalSteps, out Resolution resolution)
484  {
485  numberOfTotalSteps = configuration.Motor.MicroStepsEnabled
486  ? configuration.Motor.MicroSteps*configuration.Motor.Steps
487  : configuration.Motor.Steps;
488 
489  resolution = configuration.Resolutions.First(x => x.Precision == precision);
490  }
491 
492  #endregion
493 
494  #region writer
495 
501  [Log]
502  [LogException]
503  protected static string ResetImageFolder(Information configuration)
504  {
505  string imageFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
506  configuration.Places.ImageSubPath);
507 
508  FileHelper.CreatePathIfNotExisting(imageFolder);
509 
510  FileHelper.DeleteAllFilesInFolder(imageFolder);
511  return imageFolder;
512  }
513 
521  [Log]
522  [LogException]
523  protected bool InitiateWriter(ArduinoCommands arduino, Information configuration, out IPointWriter writer)
524  {
525  switch (configuration.Places.FileFormat)
526  {
527  case FileFormat.Ascii:
528  arduino.ActivateLaser();
529  writer = new WriterAsc();
530  break;
531  case FileFormat.Pcd:
532  writer = new WriterPcd();
533  break;
534  default:
535  writer = null;
536  return false;
537  }
538  return true;
539  }
540 
547  [Log]
548  [LogException]
549  protected static void SavePoints(Control control, IPointWriter writer, Information configuration)
550  {
551  control.Invoke((MethodInvoker) delegate
552  {
553  SaveFileDialog saveDialog = new SaveFileDialog();
554  if (!String.IsNullOrEmpty(configuration.Places.ImageSubPath))
555  saveDialog.InitialDirectory = configuration.Places.ImageSubPath;
556 
557  switch (configuration.Places.FileFormat)
558  {
559 
560  case FileFormat.Pcd:
561  saveDialog.DefaultExt = ".PLY";
562  saveDialog.Filter = "PLY (.ply)|*.ply";
563  saveDialog.FileName = "ColoredPoints" + DateTime.Now.ToFileTime();
564  break;
565  default:
566  saveDialog.DefaultExt = ".asc";
567  saveDialog.Filter = "Ascii (.asc)|*.asc";
568  saveDialog.FileName = "Points" + DateTime.Now.ToFileTime();
569  break;
570  }
571 
572  DialogResult result = saveDialog.ShowDialog();
573 
574  if (result != DialogResult.OK)
575  return;
576 
577  string filename = saveDialog.FileName;
578  configuration.Places.LastFilePath = Path.GetDirectoryName(filename);
579  writer.Write(filename);
580  });
581  }
582 
583  #endregion
584 
585  #region start stop
586  [Log]
590  [LogException]
591  internal void Stop()
592  {
593  this.ImagingControl.StopImaging();
594  if (this.ScanWorker.IsBusy)
595  this.ScanWorker.CancelAsync();
596  }
597 
601  [Log]
602  [LogException]
603  internal void Start()
604  {
605  this.ImagingControl.StartImaging(this.ConfigurationInformation.Camera.Name);
606  }
607 
608  private void RadialSliderPrecision_ValueChanged(object sender, RadialSlider.ValueChangedEventArgs args)
609  {
610  this.RadialSliderPrecision.ValueChanged -= this.RadialSliderPrecision_ValueChanged;
611 
612  int testValue = (int)Math.Round(this.RadialSliderPrecision.Value);
613  this.RadialSliderPrecision.Value = testValue;
614 
615  this.RadialSliderPrecision.ValueChanged += this.RadialSliderPrecision_ValueChanged;
616  }
617  #endregion
618  }
619 }
static void CreatePathIfNotExisting(string folder)
Creates the path if not existing.
Definition: FileHelper.cs:14
Filter Filter
Gets or sets the filter.
Definition: Information.cs:89
FileFormat FileFormat
Gets or sets the file format.
Definition: Places.cs:46
ScanControl()
Initializes a new instance of the ScanControl class.
Definition: ScanControl.cs:72
Configuration of a scan resulution
Definition: Resolution.cs:10
void ToggleButtonCapture_Click(object sender, EventArgs e)
Handles the Click event of the toggleButtonCapture control.
Definition: ScanControl.cs:239
Class for detecting an arduino and sending commands to it
Camera Camera
Gets or sets the camera.
Definition: Information.cs:24
string LastFilePath
Gets or sets the last file path.
Definition: Places.cs:22
void RotateLaserCw(int steps)
Rotates the laser clockwise.
static float GetLaserLinePosition(Image laserImage, Filter filter)
Gets the laser line position.
void Start()
Starts this instance.
Definition: ScanControl.cs:603
void ScanWorker_DoWork(object sender, DoWorkEventArgs e)
Handles the DoWork event of the scanWorker control.
Definition: ScanControl.cs:173
void Init(ArduinoCommands arduino)
Initializes the control.
Definition: ScanControl.cs:95
Class holding configuration to access an arduino
Definition: Arduino.cs:7
static string ResetImageFolder(Information configuration)
Resets the image folder.
Definition: ScanControl.cs:503
override void Dispose(bool disposing)
Verwendete Ressourcen bereinigen.
Definition: ScanControl.cs:153
Class holding the configuration information
Definition: Information.cs:8
void Write(string fileName)
Writes to specified file name.
int Steps
Gets or sets the steps.
Definition: Resolution.cs:33
Laser Laser
Gets or sets the laser.
Definition: Information.cs:17
static void MoveLaserToLeftStartPosition(ArduinoCommands arduino, CameraControl cameraControl, Information configuration)
Moves the laser to left start position.
Definition: ScanControl.cs:453
static Bitmap CreateGrayImageOfLaser(Bitmap image, Filter filter)
Creates the gray image of laser.
float SwipeMax
Gets or sets the swipe maximum.
Definition: Laser.cs:52
static Bitmap SimpleSkeletonizationImage(Bitmap bitmap)
Skeletonization for image.
string ImageSubPath
Gets or sets the image sub path.
Definition: Places.cs:38
Control for accessing a camera
void AddPoint(ColorPoint3D point)
Adds the point.
bool MicroStepsEnabled
Gets or sets a value indicating whether [micro steps enabled].
Definition: Motor.cs:31
Class for creating a singleton for a generic class
Definition: Singleton.cs:9
static List< ColorPoint3D > TransformStepImage(Image skeletonImage, Image colorImage, int step, bool microSteps, Information configuration)
Transforms the step image.
static File Helpers
Definition: FileHelper.cs:8
Write Points to PCD file
Definition: WriterPcd.cs:27
void InitiateCameraDropdown()
Initiates the camera dropdown.
Definition: ScanControl.cs:112
IEnumerable< ColorPoint3D > ScanImage(int actualSteps, string imageFolder, int steps, int sweep, ArduinoCommands arduino, CameraControl imaging, Information configuration)
Scans the image.
Definition: ScanControl.cs:315
void ComboBoxCameras_SelectedIndexChanged(object sender, EventArgs e)
Handles the SelectedIndexChanged event of the comboBoxCameras control.
Definition: ScanControl.cs:263
void RotateTurnTableCw(int steps)
Rotates the turn table clockwise.
Places Places
Gets or sets the places.
Definition: Information.cs:59
Just a class for a special style of the toogle buttons
FileFormat
File output format
Definition: FileFormat.cs:6
Control for 3d Scanning
Definition: ScanControl.cs:20
static T Instance
Gets the instance.
Definition: Singleton.cs:27
void ActivateLaser(bool on=true)
Activates the laser.
Does transformations of an image
int MicroSteps
Gets or sets the number of micro steps.
Definition: Motor.cs:24
Image GetNextPicture()
Gets the next picture.
void RotateLaserCcw(int steps)
Rotates the laser counter clockwise.
bool PerformScan(ArduinoCommands arduino, CameraControl cameraControl, Information configuration, int numberOfTotalSteps, Resolution resolution, string imageFolder, IPointWriter writer)
Performs the scan.
Definition: ScanControl.cs:421
List< Resolution > Resolutions
Gets or sets the resolutions.
Definition: Information.cs:67
Interface for writing points to file
Definition: IPointWriter.cs:8
int Width
Gets or sets the width.
Definition: Camera.cs:38
void ScanWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
Handles the ProgressChanged event of the ScanWorker control.
Definition: ScanControl.cs:205
static void DeleteAllFilesInFolder(string imageFolder)
Deletes all files in folder.
Definition: FileHelper.cs:26
Write Points to Asc file
Definition: WriterAsc.cs:13
System.Drawing.Image Image
int SweepSteps
Gets or sets the sweep steps.
Definition: Resolution.cs:41
static void GetResolutionAndSteps(Precision precision, Information configuration, out int numberOfTotalSteps, out Resolution resolution)
Gets the resolution and steps.
Definition: ScanControl.cs:483
Motor Motor
Gets or sets the motor.
Definition: Information.cs:52
StartScan StartScanning
Occurs when [start scanning].
Definition: ScanControl.cs:54
Precision
Information about the precision of a scan
Definition: Precision.cs:6
int Steps
Gets or sets the number of steps.
Definition: Motor.cs:16
float SwipeMin
Gets or sets the swipe minimum.
Definition: Laser.cs:45
static void SavePoints(Control control, IPointWriter writer, Information configuration)
Saves the points.
Definition: ScanControl.cs:549
StopScan StopScanning
Occurs when [stop scanning].
Definition: ScanControl.cs:62
virtual void ScanWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
Handles the RunWorkerCompleted event of the ScanWorker control.
Definition: ScanControl.cs:217
void Stop()
Stops this instance.
Definition: ScanControl.cs:591
bool MotorEnabled
Gets or sets a value indicating whether [motor enabled].
Definition: Laser.cs:59
bool InitiateWriter(ArduinoCommands arduino, Information configuration, out IPointWriter writer)
Initiates the writer.
Definition: ScanControl.cs:523