Skip to content

Commit

Permalink
Merge pull request #10 from JordyForNow/InputManipulation-Csharp
Browse files Browse the repository at this point in the history
Input manipulation csharp
  • Loading branch information
jetenergy authored Jan 14, 2020
2 parents c701605 + 4075546 commit 91cb829
Show file tree
Hide file tree
Showing 8 changed files with 376 additions and 49 deletions.
8 changes: 7 additions & 1 deletion MotionRecognition.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MotionRecognition", "Motion
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "Sandbox\Sandbox.csproj", "{D219E982-F66C-4B01-AAEF-461BEDB9B838}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{06B71FFE-B063-4C40-A78B-0C135EAEDCD9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "UnitTests\UnitTests.csproj", "{06B71FFE-B063-4C40-A78B-0C135EAEDCD9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MotionRecognitionHelper", "MotionRecognitionHelper\MotionRecognitionHelper.csproj", "{CAF5CCD8-B455-4543-93A5-E238FD710832}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -26,6 +28,10 @@ Global
{06B71FFE-B063-4C40-A78B-0C135EAEDCD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06B71FFE-B063-4C40-A78B-0C135EAEDCD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06B71FFE-B063-4C40-A78B-0C135EAEDCD9}.Release|Any CPU.Build.0 = Release|Any CPU
{CAF5CCD8-B455-4543-93A5-E238FD710832}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CAF5CCD8-B455-4543-93A5-E238FD710832}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CAF5CCD8-B455-4543-93A5-E238FD710832}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CAF5CCD8-B455-4543-93A5-E238FD710832}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 0 additions & 1 deletion MotionRecognition/MotionRecognition.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@

<ItemGroup>
<PackageReference Include="encog-dotnet-core" Version="3.4.0" />
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
</ItemGroup>
</Project>
234 changes: 234 additions & 0 deletions MotionRecognitionHelper/CSVManipulator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;

namespace MotionRecognitionHelper
{
public struct CSVManipulatorSettings
{
public int copyLines; // How many lines to just copy over.
public int removeLines; // How many lines to skip and forget.
public int mutationCount; // Amount of mutations.
public float deviationPercentage; // Float 0 - 1.
public float innerDeviationPercentage; // Float 0 - 1 / Innerdeviation means the random deviation after the total deviation.

// Only one of these needs to be filled, if both are filled then the file will take precedence.
public string dataFile; // Csv movement file to copy and mutate.
public string dataFolder; // Folder with csv movement files to use and mutate, please end with /.

public string outputFolder;

public bool alterInput; // Alter the input files to have dots instead of commas in the timestamp value.

public bool verbose;
}

public static class CSVManipulator
{
private static readonly Random random = new Random();

public static void RunManipulator(ref CSVManipulatorSettings settings)
{
if (!Directory.Exists(settings.outputFolder))
{
Directory.CreateDirectory(settings.outputFolder); // Create output directory if necessary.
}
else
{
ClearOutputFolder(settings.outputFolder); // Clear otherwise.
}

if (!string.IsNullOrEmpty(settings.dataFile))
{
// Mutate a single csv file.
if (settings.verbose)
Console.WriteLine($"From: {settings.dataFile} to {settings.outputFolder}");

ChangeOriginalFile(ref settings);
MutateFile(ref settings);
}
else if (!string.IsNullOrEmpty(settings.dataFolder))
{
// Mutate a folder with csv files.
if (settings.verbose)
Console.WriteLine($"From: {settings.dataFolder} to {settings.outputFolder}");
ChangeOriginalBatch(ref settings);
MutateFolder(ref settings);
}
else
{
if (settings.verbose)
Console.WriteLine("You didn't select any input!");
}

if (settings.verbose)
Console.WriteLine("Finished manipulating.");
}

// Method to make sleight changes to the original file,
// Currently only checks if the second character in the line is a comma and changes it to '.'
// This is to make sure the CSV file doesnt break because the comma is the splitter.
private static void ChangeOriginalFile(ref CSVManipulatorSettings settings)
{
if (!settings.alterInput) return;

var lines = File.ReadAllText(settings.dataFile).Split(Environment.NewLine);

for (int i = 0; i < lines.Length; i++)
{
if (lines[i].IndexOf(',') == 1)
{
ReplaceInString(ref lines[i], 1, '.');
}
else if (i > 5)
{
return;
}
}

File.WriteAllText(settings.dataFile, string.Join(Environment.NewLine, lines));
}

// Gets all files in input directory and does the change function.
private static void ChangeOriginalBatch(ref CSVManipulatorSettings settings)
{
FileInfo[] fileInfo = new DirectoryInfo(settings.dataFolder).GetFiles();

for (int i = 0; i < fileInfo.Length; i++)
{
settings.dataFile = fileInfo[i].FullName;
ChangeOriginalFile(ref settings);
}
}

// FileNamePrefix is only used in batch mutate.
private static void MutateFile(ref CSVManipulatorSettings settings, string fileNamePrefix = "")
{
// This variable stores the general deviation of each joint per mutated file (i.e. [OutputFile1][Joint1])
Dictionary<string, List<double>> deviations = new Dictionary<string, List<double>>();

// Local variable to store the amount of lines to copy over.
int CPL = settings.copyLines;

// Local variable to store the amount of lines to remove.
int RML = settings.removeLines;

StreamReader reader = new StreamReader(settings.dataFile);
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.IndexOf(',') == 1)
{
ReplaceInString(ref line, 1, '.');
}

// Copy line to new mutated files.
if (CPL > 0)
{
for (int i = 0; i < settings.mutationCount; i++)
{
using StreamWriter sw = File.AppendText(settings.outputFolder + fileNamePrefix + "-" + i.ToString() + ".csv");
sw.WriteLine(line);
sw.Close();
}
CPL--;
continue;
}

// Remove line.
if (RML > 0)
{
RML--;
continue;
}

string[] data = line.Split(',');
if (data.Length > 1)
{
for (int i = 0; i < settings.mutationCount; i++)
{
StringBuilder sb = new StringBuilder(data[0]);

for (int j = 1; j < data.Length; j += 2)
{ // For each pair of Vector3 and Quarternion edit only Vector3 - data[j] = Vector3, data[j + 1] = Quaternion.
sb.Append($",{MutateVector(ref settings, data[j], j / 2, fileNamePrefix + i, ref deviations)},{data[j + 1]}");
}

File.AppendAllText(settings.outputFolder + fileNamePrefix + "-" + i.ToString() + ".csv", sb.ToString() + Environment.NewLine);
}
}
}
}

private static void MutateFolder(ref CSVManipulatorSettings settings)
{
FileInfo[] fileInfo = new DirectoryInfo(settings.dataFolder).GetFiles();

for (int i = 0; i < fileInfo.Length; i++) // For each input do settings.MutationCount mutations.
{
if (settings.verbose)
Console.WriteLine($"Working on {fileInfo[i].Name}");
settings.dataFile = fileInfo[i].FullName;
MutateFile(ref settings, i.ToString());
}
}

// Extra method to change a char at specified position.
private static void ReplaceInString(ref string original, int pos, char replacement)
{
StringBuilder sb = new StringBuilder(original);
sb[pos] = replacement;
original = sb.ToString();
}

private static void ClearOutputFolder(string folder)
{
DirectoryInfo directoryInfo = new DirectoryInfo(folder);

foreach (FileInfo file in directoryInfo.GetFiles())
{
file.Delete();
}
}

private static string MutateVector(ref CSVManipulatorSettings settings, string vector, int col, string name, ref Dictionary<string, List<double>> deviations)
{
if (!deviations.ContainsKey(name)) // Creates a new List for the joint deviations.
{
deviations.Add(name, new List<double>());
}

if (deviations[name].Count - 1 <= col) // Create new deviation for the joint.
{
deviations[name].Add(CalculateDeviation(settings.deviationPercentage));
}

var innerdeviation = CalculateDeviation(settings.innerDeviationPercentage); // Inner deviation is the deviation after the general deviation of the whole joint path.

var points = vector.Substring(1, vector.Length - 2).Split("| ");

// Method for doing the calculation and rewriting it to the proper string length.
string DoDeviation(string data, ref Dictionary<string, List<double>> deviations)
{
// InvariantCulture is used to properly read and write the float data.
return (float.Parse(data, CultureInfo.InvariantCulture) * deviations[name][col] * innerdeviation).ToString("0.000000", CultureInfo.InvariantCulture);
}

points[0] = DoDeviation(points[0], ref deviations);
points[1] = DoDeviation(points[1], ref deviations);
points[2] = DoDeviation(points[2], ref deviations);

return $"({string.Join("| ", points)})";
}

// Calculates a random deviation depending on the input percentage.
private static double CalculateDeviation(double percentage)
{
double positive = random.NextDouble() * percentage;
double negative = random.NextDouble() * percentage;
return 1.0d + ((positive > negative) ? positive : -negative);
}
}
}
44 changes: 44 additions & 0 deletions MotionRecognitionHelper/ImageCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace MotionRecognitionHelper
{
public static class ImageCreator
{
// Creates a Bitmap from a double array.
// If Is3DImage = true then it creates an image that is double the height.
public static Bitmap CreateNeuralImageFromDoubleArray(ref double[] arr, int size, bool Is3DImage = false)
{
int width = size;
int height = Is3DImage ? size * 2 : size;

Bitmap bitmap = new Bitmap(width, height);

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
bitmap.SetPixel(x, y, (y < size) ? Color.Gray : Color.White); // Use different background color for either halve of the image.

if (arr[x + y * width] != 0) // y * width equates to the offset within the array.
{
bitmap.SetPixel(x, y, (y >= size) ? Color.Blue : Color.Black); // Different foreground pixel color.
}
}
}
return bitmap;
}

public static void WriteBitmapToFS(Bitmap bitmap, string filePath = "Image.bmp")
{
var outputDirectory = Path.GetDirectoryName(filePath);

if (!Directory.Exists(outputDirectory)) {
Directory.CreateDirectory(outputDirectory);
}

bitmap.Save($"{outputDirectory}/{Path.GetFileNameWithoutExtension(filePath)}.bmp", ImageFormat.Bmp);
}
}
}
18 changes: 18 additions & 0 deletions MotionRecognitionHelper/MotionRecognitionHelper.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.1</TargetFramework>
<ApplicationIcon />
<StartupObject />
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MotionRecognition\MotionRecognition.csproj" />
</ItemGroup>

</Project>
34 changes: 0 additions & 34 deletions Sandbox/ImageCreator.cs

This file was deleted.

Loading

0 comments on commit 91cb829

Please sign in to comment.