├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── Assets
├── Trainer Studio.png
├── Trainer-Studio.ico
└── Lithicsoft Trainer Studio.png
├── App.xaml.cs
├── Utils
├── LoadingWindow.xaml.cs
└── LoadingWindow.xaml
├── AssemblyInfo.cs
├── App.xaml
├── UserControls
├── Startup.xaml
├── Pages
│ ├── Manager.xaml
│ ├── Creator.xaml
│ ├── Manager.xaml.cs
│ └── Creator.xaml.cs
├── MainPage.xaml
├── MainPage.xaml.cs
└── Startup.xaml.cs
├── Trainer.xaml
├── MainWindow.xaml
├── Python
├── PY
│ ├── TestModel.xaml
│ ├── TrainModel.xaml
│ ├── ModelResult.xaml
│ ├── PrepareDataset.xaml
│ ├── ConfigModel.xaml
│ ├── ModelResult.xaml.cs
│ ├── TestModel.xaml.cs
│ ├── ConfigModel.xaml.cs
│ ├── TrainModel.xaml.cs
│ └── PrepareDataset.xaml.cs
├── Python.xaml
└── Python.xaml.cs
├── CSharp
├── IC
│ ├── TrainModel.xaml
│ ├── ModelResult.xaml
│ ├── TestModel.xaml
│ ├── PrepareDataset.xaml
│ ├── ModelResult.xaml.cs
│ ├── TrainModel.xaml.cs
│ ├── TestModel.xaml.cs
│ └── PrepareDataset.xaml.cs
├── VP
│ ├── TrainModel.xaml
│ ├── ModelResult.xaml
│ ├── PrepareDataset.xaml
│ ├── TestModel.xaml
│ ├── ModelResult.xaml.cs
│ ├── TrainModel.xaml.cs
│ ├── TestModel.xaml.cs
│ └── PrepareDataset.xaml.cs
├── ValuePrediction.xaml
├── ImageClassification.xaml
├── ValuePrediction.xaml.cs
└── ImageClassification.xaml.cs
├── Lithicsoft Trainer Studio.sln
├── CSharpML
├── ValuePrediction.cs
└── ImageClassification.cs
├── README.md
├── Lithicsoft Trainer Studio.csproj
├── Trainer.xaml.cs
├── MainWindow.xaml.cs
├── app.manifest
├── Lithicsoft Trainer Studio.csproj.user
├── .gitignore
└── LICENSE
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | patreon: lithicsoft
2 | buy_me_a_coffee: lithicsoft
3 |
--------------------------------------------------------------------------------
/Assets/Trainer Studio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lithicsoft/TS-Source/HEAD/Assets/Trainer Studio.png
--------------------------------------------------------------------------------
/Assets/Trainer-Studio.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lithicsoft/TS-Source/HEAD/Assets/Trainer-Studio.ico
--------------------------------------------------------------------------------
/Assets/Lithicsoft Trainer Studio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lithicsoft/TS-Source/HEAD/Assets/Lithicsoft Trainer Studio.png
--------------------------------------------------------------------------------
/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Media;
3 |
4 | namespace Lithicsoft_Trainer_Studio
5 | {
6 | ///
7 | /// Interaction logic for App.xaml
8 | ///
9 | public partial class App : Application
10 | {
11 | protected override void OnStartup(StartupEventArgs e)
12 | {
13 | RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
14 | base.OnStartup(e);
15 | }
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/Utils/LoadingWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Utils/LoadingWindow.xaml: Waiting window
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.Windows;
10 |
11 | namespace Lithicsoft_Trainer_Studio.Utils
12 | {
13 | ///
14 | /// Interaction logic for LoadingWindow.xaml
15 | ///
16 | public partial class LoadingWindow : Window
17 | {
18 | public LoadingWindow(string job)
19 | {
20 | InitializeComponent();
21 | this.JobName.Text = job;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Utils/LoadingWindow.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **System (please complete the following information):**
27 | - OS: [e.g. Windows 10, Windows 11]
28 | - Build type [e.g. Releases, Dev]
29 | - Build [e.g. 20240718, 20240714r]
30 |
31 | **Additional context**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/UserControls/Startup.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Trainer.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Python/PY/TestModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/CSharp/IC/TrainModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/CSharp/VP/TrainModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Python/PY/TrainModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Lithicsoft Trainer Studio.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.10.34928.147
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithicsoft Trainer Studio", "Lithicsoft Trainer Studio.csproj", "{1ED87840-A1FB-4C5D-9184-4C291D2B2165}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {1ED87840-A1FB-4C5D-9184-4C291D2B2165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {1ED87840-A1FB-4C5D-9184-4C291D2B2165}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {1ED87840-A1FB-4C5D-9184-4C291D2B2165}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {1ED87840-A1FB-4C5D-9184-4C291D2B2165}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {AD689106-FCFC-4213-A916-32CE2B2984D0}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/CSharp/ValuePrediction.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/CSharp/ImageClassification.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/CSharp/ValuePrediction.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/ValuePrediction.xaml.cs: Trainer usercontrol for value prediction
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.Windows.Controls;
10 |
11 | namespace Lithicsoft_Trainer_Studio.CSharp
12 | {
13 | ///
14 | /// Interaction logic for ValuePrediction.xaml
15 | ///
16 | public partial class ValuePrediction : UserControl
17 | {
18 | private readonly string projectName = string.Empty;
19 |
20 | public ValuePrediction(string name)
21 | {
22 | InitializeComponent();
23 |
24 | projectName = name;
25 | }
26 |
27 | private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
28 | {
29 | MainFrame.Content = new VP.PrepareDataset(projectName);
30 | }
31 |
32 | private void Button_Click_1(object sender, System.Windows.RoutedEventArgs e)
33 | {
34 | MainFrame.Content = new VP.TrainModel(projectName);
35 | }
36 |
37 | private void Button_Click_2(object sender, System.Windows.RoutedEventArgs e)
38 | {
39 | MainFrame.Content = new VP.TestModel(projectName);
40 | }
41 |
42 | private void Button_Click_3(object sender, System.Windows.RoutedEventArgs e)
43 | {
44 | MainFrame.Content = new VP.ModelResult(projectName);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/CSharp/ImageClassification.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/ImageClassification.xaml.cs: Trainer usercontrol for image classification
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.Windows.Controls;
10 |
11 | namespace Lithicsoft_Trainer_Studio.CSharp
12 | {
13 | ///
14 | /// Interaction logic for ImageClassification.xaml
15 | ///
16 | public partial class ImageClassification : UserControl
17 | {
18 | private readonly string projectName = string.Empty;
19 |
20 | public ImageClassification(string name)
21 | {
22 | InitializeComponent();
23 |
24 | projectName = name;
25 | }
26 |
27 | private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
28 | {
29 | MainFrame.Content = new IC.PrepareDataset(projectName);
30 | }
31 |
32 | private void Button_Click_1(object sender, System.Windows.RoutedEventArgs e)
33 | {
34 | MainFrame.Content = new IC.TrainModel(projectName);
35 | }
36 |
37 | private void Button_Click_2(object sender, System.Windows.RoutedEventArgs e)
38 | {
39 | MainFrame.Content = new IC.TestModel(projectName);
40 | }
41 |
42 | private void Button_Click_3(object sender, System.Windows.RoutedEventArgs e)
43 | {
44 | MainFrame.Content = new IC.ModelResult(projectName);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/CSharp/IC/ModelResult.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/CSharp/VP/ModelResult.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Python/PY/ModelResult.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Python/Python.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/CSharp/IC/TestModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
21 |
22 |
23 |
26 |
27 |
28 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Python/Python.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Python/Python.xaml.cs: Trainer usercontrol for image classification
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.Windows.Controls;
10 |
11 | namespace Lithicsoft_Trainer_Studio.Python
12 | {
13 | ///
14 | /// Interaction logic for Python.xaml
15 | ///
16 | public partial class Python : UserControl
17 | {
18 | private readonly string projectName = string.Empty;
19 |
20 | public Python(string name)
21 | {
22 | InitializeComponent();
23 |
24 | projectName = name;
25 | }
26 |
27 | private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
28 | {
29 | MainFrame.Content = new PY.PrepareDataset(projectName);
30 | }
31 |
32 | private void Button_Click1(object sender, System.Windows.RoutedEventArgs e)
33 | {
34 | MainFrame.Content = new PY.ConfigModel(projectName);
35 | }
36 |
37 | private void Button_Click_2(object sender, System.Windows.RoutedEventArgs e)
38 | {
39 | MainFrame.Content = new PY.TrainModel(projectName);
40 | }
41 |
42 | private void Button_Click_3(object sender, System.Windows.RoutedEventArgs e)
43 | {
44 | MainFrame.Content = new PY.TestModel(projectName);
45 | }
46 |
47 | private void Button_Click_4(object sender, System.Windows.RoutedEventArgs e)
48 | {
49 | MainFrame.Content = new PY.ModelResult(projectName);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/CSharp/VP/PrepareDataset.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Python/PY/PrepareDataset.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/CSharp/IC/PrepareDataset.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Python/PY/ConfigModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/UserControls/Pages/Manager.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/UserControls/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Python/PY/ModelResult.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Python/PY/ModelResult.xaml.cs: Back-end source code for model result image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.IO;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Documents;
13 | using MessageBox = ModernWpf.MessageBox;
14 |
15 | namespace Lithicsoft_Trainer_Studio.Python.PY
16 | {
17 | ///
18 | /// Interaction logic for ModelResult.xaml
19 | ///
20 | public partial class ModelResult : Page
21 | {
22 | private readonly string projectName = string.Empty;
23 |
24 | public ModelResult(string name)
25 | {
26 | InitializeComponent();
27 |
28 | projectName = name;
29 | }
30 |
31 | private void Page_Loaded(object sender, RoutedEventArgs e)
32 | {
33 | if (Directory.Exists($"projects\\{projectName}\\outputs"))
34 | {
35 | button1.IsEnabled = true;
36 | }
37 |
38 | string code = @"Fast document is not available for this project, please visit our wiki via website!";
39 | DocCode.Document.Blocks.Clear();
40 | DocCode.Document.Blocks.Add(new Paragraph(new Run(code)));
41 | }
42 |
43 | private void Button1_Click(object sender, RoutedEventArgs e)
44 | {
45 | try
46 | {
47 | string filePath = $"projects\\{projectName}\\outputs";
48 | if (!Directory.Exists(filePath))
49 | {
50 | return;
51 | }
52 |
53 | string argument = "/select, \"" + filePath + "\"";
54 |
55 | System.Diagnostics.Process.Start("explorer.exe", argument);
56 | }
57 | catch (Exception ex)
58 | {
59 | MessageBox.Show($"Error opening model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/CSharp/VP/TestModel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/CSharpML/ValuePrediction.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharpML/ValuePrediction.cs: CSharp trainer for values prediction
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Microsoft.ML;
10 | using Microsoft.ML.Data;
11 |
12 | namespace Lithicsoft_Trainer_Studio.CSharpML
13 | {
14 | class ValuePrediction
15 | {
16 | public class ModelInput
17 | {
18 | [LoadColumn(0)]
19 | public float A { get; set; }
20 |
21 | [LoadColumn(1)]
22 | public float B { get; set; }
23 |
24 | [LoadColumn(2)]
25 | public float C { get; set; }
26 |
27 | [LoadColumn(3)]
28 | public float D { get; set; }
29 |
30 | [LoadColumn(4)]
31 | public float Prediction { get; set; }
32 | }
33 |
34 | public class ModelOutput
35 | {
36 | [ColumnName("Score")]
37 | public float Prediction { get; set; }
38 | }
39 |
40 | static string? _trainDataPath;
41 | static string? _modelPath;
42 |
43 | private string? projectName;
44 |
45 | public void Train(string name)
46 | {
47 | projectName = name;
48 | _trainDataPath = $"projects\\{projectName}\\datasets\\dataset.csv";
49 | _modelPath = $"projects\\{projectName}\\outputs\\model.zip";
50 |
51 | MLContext mlContext = new(seed: 0);
52 | Train(mlContext, _trainDataPath);
53 | }
54 |
55 | private static TransformerChain> Train(MLContext mlContext, string dataPath)
56 | {
57 | IDataView dataView = mlContext.Data.LoadFromTextFile(dataPath, hasHeader: true, separatorChar: ',');
58 |
59 | var pipeline = mlContext.Transforms.CopyColumns(outputColumnName: "Label", inputColumnName: nameof(ModelInput.Prediction))
60 | .Append(mlContext.Transforms.Concatenate("Features", nameof(ModelInput.A), nameof(ModelInput.B), nameof(ModelInput.C), nameof(ModelInput.D)))
61 | .Append(mlContext.Regression.Trainers.FastTree());
62 |
63 | var model = pipeline.Fit(dataView);
64 |
65 | mlContext.Model.Save(model, dataView.Schema, _modelPath);
66 |
67 | return model;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/CSharp/IC/ModelResult.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/IC/ModelResult.xaml.cs: Back-end source code for model result image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.IO;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Documents;
13 | using MessageBox = ModernWpf.MessageBox;
14 |
15 | namespace Lithicsoft_Trainer_Studio.CSharp.IC
16 | {
17 | ///
18 | /// Interaction logic for ModelResult.xaml
19 | ///
20 | public partial class ModelResult : Page
21 | {
22 | private readonly string projectName = string.Empty;
23 |
24 | public ModelResult(string name)
25 | {
26 | InitializeComponent();
27 |
28 | projectName = name;
29 | }
30 |
31 | private void Page_Loaded(object sender, RoutedEventArgs e)
32 | {
33 | if (File.Exists($"projects\\{projectName}\\outputs\\model.zip"))
34 | {
35 | button1.IsEnabled = true;
36 | }
37 |
38 | string code = @"
39 | private MLContext mlContext;
40 | private PredictionEngine predictionEngine;
41 | mlContext = new MLContext();
42 | DataViewSchema predictionPipelineSchema;
43 | ITransformer predictionPipeline = mlContext.Model.Load($""model.zip"", out predictionPipelineSchema);
44 | predictionEngine = mlContext.Model.CreatePredictionEngine(predictionPipeline);
45 | var imageData = new ImageData()
46 | {
47 | ImagePath = ""your_image_file_path.png""
48 | };
49 |
50 | var prediction = predictionEngine.Predict(imageData);
51 | public class ImageData
52 | {
53 | [LoadColumn(0)]
54 | public string ImagePath;
55 |
56 | [LoadColumn(1)]
57 | public string Label;
58 | }
59 |
60 | public class ImagePrediction : ImageData
61 | {
62 | public float[] Score;
63 |
64 | public string PredictedLabelValue;
65 | }";
66 | DocCode.Document.Blocks.Clear();
67 | DocCode.Document.Blocks.Add(new Paragraph(new Run(code)));
68 | }
69 |
70 | private void Button1_Click(object sender, RoutedEventArgs e)
71 | {
72 | try
73 | {
74 | string filePath = $"projects\\{projectName}\\outputs";
75 | if (!Directory.Exists(filePath))
76 | {
77 | return;
78 | }
79 |
80 | string argument = "/select, \"" + filePath + "\"";
81 |
82 | System.Diagnostics.Process.Start("explorer.exe", argument);
83 | }
84 | catch (Exception ex)
85 | {
86 | MessageBox.Show($"Error opening model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Python/PY/TestModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Python/PY/TestModel.xaml.cs: Back-end source code for model tester image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.Diagnostics;
10 | using System.IO;
11 | using System.Windows;
12 | using MessageBox = ModernWpf.MessageBox;
13 | using Page = System.Windows.Controls.Page;
14 |
15 | namespace Lithicsoft_Trainer_Studio.Python.PY
16 | {
17 | ///
18 | /// Interaction logic for TestModel.xaml
19 | ///
20 | public partial class TestModel : Page
21 | {
22 | private readonly string projectName = string.Empty;
23 |
24 | public TestModel(string name)
25 | {
26 | InitializeComponent();
27 |
28 | projectName = name;
29 | }
30 |
31 | private void Page_Loaded(object sender, RoutedEventArgs e)
32 | {
33 | if (File.Exists($"projects\\{projectName}\\tester.py") && Directory.Exists($"projects\\{projectName}\\outputs"))
34 | {
35 | button1.IsEnabled = true;
36 | }
37 | else
38 | {
39 | button1.IsEnabled = false;
40 | button1.Content = "Unavailable";
41 | }
42 | }
43 |
44 | private async void Button_Click(object sender, RoutedEventArgs e)
45 | {
46 | button1.IsEnabled = false;
47 |
48 | progressBar.Visibility = Visibility.Visible;
49 |
50 | await Task.Run(() =>
51 | {
52 | try
53 | {
54 | ProcessStartInfo start = new()
55 | {
56 | FileName = $"cmd.exe",
57 | Arguments = $"/K conda activate \"{projectName}\" & python \"{Path.Combine(Environment.CurrentDirectory, $"projects\\{projectName}\\tester.py")}\" & conda deactivate & pause & exit",
58 | UseShellExecute = true,
59 | RedirectStandardOutput = false
60 | };
61 |
62 | using (var process = Process.Start(start))
63 | {
64 | if (process != null)
65 | {
66 | process.WaitForExit();
67 | }
68 | }
69 | }
70 | catch (Exception ex)
71 | {
72 | Dispatcher.Invoke(() =>
73 | {
74 | MessageBox.Show($"Error testing model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
75 | });
76 | }
77 | });
78 |
79 | progressBar.Visibility = Visibility.Hidden;
80 |
81 | button1.IsEnabled = true;
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/CSharp/VP/ModelResult.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/VP/ModelResult.xaml.cs: Back-end source code for model result value prediction page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.IO;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Documents;
13 | using MessageBox = ModernWpf.MessageBox;
14 |
15 | namespace Lithicsoft_Trainer_Studio.CSharp.VP
16 | {
17 | ///
18 | /// Interaction logic for ModelResult.xaml
19 | ///
20 | public partial class ModelResult : Page
21 | {
22 | private readonly string projectName = string.Empty;
23 |
24 | public ModelResult(string name)
25 | {
26 | InitializeComponent();
27 |
28 | projectName = name;
29 | }
30 |
31 | private void Page_Loaded(object sender, RoutedEventArgs e)
32 | {
33 | if (File.Exists($"projects\\{projectName}\\outputs\\model.zip"))
34 | {
35 | button1.IsEnabled = true;
36 | }
37 |
38 | string code = @"
39 | private MLContext mlContext;
40 | private PredictionEngine predictionEngine;
41 | mlContext = new MLContext();
42 | DataViewSchema predictionPipelineSchema;
43 | ITransformer predictionPipeline = mlContext.Model.Load($""model.zip"", out predictionPipelineSchema);
44 | predictionEngine = mlContext.Model.CreatePredictionEngine(predictionPipeline);
45 | var sampleInput = new ModelInput
46 | {
47 | A = 2.0f,
48 | B = 20.0f,
49 | C = 4.0f,
50 | D = 4.0f
51 | };
52 |
53 | public class ModelInput
54 | {
55 | [LoadColumn(0)]
56 | public float A { get; set; }
57 |
58 | [LoadColumn(1)]
59 | public float B { get; set; }
60 |
61 | [LoadColumn(2)]
62 | public float C { get; set; }
63 |
64 | [LoadColumn(3)]
65 | public float D { get; set; }
66 |
67 | [LoadColumn(4)]
68 | public float Prediction { get; set; }
69 | }
70 |
71 | public class ModelOutput
72 | {
73 | [ColumnName(""Score"")]
74 | public float Prediction { get; set; }
75 | }";
76 | DocCode.Document.Blocks.Clear();
77 | DocCode.Document.Blocks.Add(new Paragraph(new Run(code)));
78 | }
79 |
80 | private void Button1_Click(object sender, RoutedEventArgs e)
81 | {
82 | try
83 | {
84 | string filePath = $"projects\\{projectName}\\outputs";
85 | if (!Directory.Exists(filePath))
86 | {
87 | return;
88 | }
89 |
90 | string argument = "/select, \"" + filePath + "\"";
91 |
92 | System.Diagnostics.Process.Start("explorer.exe", argument);
93 | }
94 | catch (Exception ex)
95 | {
96 | MessageBox.Show($"Error opening model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/UserControls/Pages/Creator.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Lithicsoft Trainer Studio
2 |
3 | 
4 |
5 | Lithicsoft Trainer Studio is a tool that allows you to create artificial intelligence models without coding directly on your training data.
6 |
7 | 
8 | 
9 | 
10 | 
11 | 
12 |
13 | ## Features
14 |
15 | - **Multi-language Support**: Supports C# and Python for model creation.
16 | - **C#**: Create Microsoft.ML models, currently supporting Image Classification and Value Prediction.
17 | - **Python**: Supports LSTM text generation for PyTorch and RNN text generation for TensorFlow.
18 | - **Minimal Coding**: Create models with minimal coding.
19 | - **Easy Parameter Tuning**: Easily tune training parameters (Python only).
20 | - **Intuitive Interface**: User-friendly interface.
21 | - **GPU Training**: Train models on GPUs (Python only).
22 |
23 | ## Screenshots
24 |
25 | ### Startup Window
26 | 
27 |
28 | ### Project Management
29 | 
30 |
31 | ### Usage
32 | 
33 |
34 | ## Installation
35 |
36 | For installation instructions, please refer to our [wiki](https://github.com/Lithicsoft/Lithicsoft-Trainer-Studio/wiki/(User)-Install-Trainer-Studio).
37 |
38 | ## Usage
39 |
40 | For detailed usage instructions, visit our [wiki](https://github.com/Lithicsoft/Lithicsoft-Trainer-Studio/wiki).
41 |
42 | ## Contributing
43 |
44 | Give us a star or contribute to the source code:
45 | - [Main Source Code](https://github.com/Lithicsoft/TS-Source)
46 | - [Python Source Code](https://github.com/Lithicsoft/Lithicsoft-Trainer-Studio)
47 | - [Installer Source Code](https://github.com/Lithicsoft/TS-Installer)
48 |
49 | ## License
50 |
51 | This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENSE) file for details.
52 |
53 | ## Contact
54 |
55 | - **Discord**: [Join our Discord](https://discord.com/invite/dNQunYaXrX)
56 | - **Email**: lithicsoft@gmail.com
57 |
58 | ## Dependencies
59 |
60 | This project is built on C# WPF and requires the following packages:
61 | - Microsoft.ML
62 | - Microsoft.ML.FastTree
63 | - Microsoft.ML.ImageAnalytics
64 | - Microsoft.ML.OnnxConverter
65 | - Microsoft.ML.TensorFlow
66 | - SciSharp.TensorFlow.Redist
67 | - System.Management
68 |
69 | ## Links
70 |
71 | - **Wiki**: [Lithicsoft Trainer Studio Wiki](https://github.com/Lithicsoft/Lithicsoft-Trainer-Studio/wiki)
72 | - **Website**: [Lithicsoft Trainer Studio](https://lithicsoft.rf.gd/trainerstudio)
73 | - **Repositories**:
74 | - [Python Trainer Kit](https://github.com/Lithicsoft/Lithicsoft-Trainer-Studio)
75 | - [Application Source Code](https://github.com/Lithicsoft/TS-Source)
76 | - [Installer Source Code](https://github.com/Lithicsoft/TS-Installer)
77 |
--------------------------------------------------------------------------------
/Lithicsoft Trainer Studio.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net8.0-windows
6 | Lithicsoft_Trainer_Studio
7 | enable
8 | enable
9 | true
10 | Assets\Trainer-Studio.ico
11 | app.manifest
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | Code
44 |
45 |
46 | Code
47 |
48 |
49 | Code
50 |
51 |
52 | Code
53 |
54 |
55 | Code
56 |
57 |
58 | Code
59 |
60 |
61 | Code
62 |
63 |
64 | Code
65 |
66 |
67 | Code
68 |
69 |
70 | Code
71 |
72 |
73 |
74 |
75 |
76 | Designer
77 |
78 |
79 | Designer
80 |
81 |
82 | Designer
83 |
84 |
85 | Designer
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/Trainer.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Trainer.xaml.cs: Back-end source code for trainer
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.CSharp;
10 | using System.Windows;
11 | using MessageBox = ModernWpf.MessageBox;
12 |
13 | namespace Lithicsoft_Trainer_Studio
14 | {
15 | ///
16 | /// Interaction logic for Trainer.xaml
17 | ///
18 | public partial class Trainer : Window
19 | {
20 | private readonly string projectName = string.Empty, projectLanguage = string.Empty, projectType = string.Empty;
21 |
22 | public Trainer(string name, string language, string type)
23 | {
24 | InitializeComponent();
25 |
26 | this.SizeToContent = SizeToContent.WidthAndHeight;
27 | this.Title = $"{name} - {language} - {type}";
28 |
29 | projectName = name;
30 | projectLanguage = language;
31 | projectType = type;
32 | }
33 |
34 | private void Window_Loaded(object sender, RoutedEventArgs e)
35 | {
36 | try
37 | {
38 | if (projectLanguage == "CSharp")
39 | {
40 | if (projectType == "Image Classification")
41 | {
42 | ImageClassification imageClassification = new(projectName);
43 | this.MainStackPanel.Children.Add(imageClassification);
44 | }
45 | else if (projectType == "Value Prediction")
46 | {
47 | ValuePrediction valuePrediction = new(projectName);
48 | this.MainStackPanel.Children.Add(valuePrediction);
49 | }
50 | else
51 | {
52 | MessageBox.Show($"Cannot open project {projectName} ({projectType})", "Project Open");
53 | }
54 | }
55 | else
56 | {
57 | Python.Python python = new(projectName);
58 | this.MainStackPanel.Children.Add(python);
59 | }
60 | }
61 | catch (Exception ex)
62 | {
63 | MessageBox.Show($"Error dectecting project type: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
64 | }
65 | }
66 |
67 | private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
68 | {
69 | if (CSharp.IC.TrainModel.Instance.isTraining || CSharp.VP.TrainModel.Instance.isTraining || Python.PY.TrainModel.Instance.isTraining)
70 | {
71 | MessageBox.Show("You can't not exit Trainer Studio while training model!", "Prevent Closing", MessageBoxButton.OK, MessageBoxImage.Stop);
72 | e.Cancel = true;
73 | }
74 | else
75 | {
76 | var result = MessageBox.Show("Do you want to exit Trainer Studio?", "Close Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question);
77 | if (result == MessageBoxResult.Yes)
78 | System.Windows.Application.Current.Shutdown();
79 | else if (result == MessageBoxResult.No)
80 | e.Cancel = true;
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * MainWindow.xaml.cs: Back-end source code for main window
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.UserControls;
10 | using Lithicsoft_Trainer_Studio.UserControls.Pages;
11 | using System.Windows;
12 | using System.Windows.Controls;
13 | using MessageBox = ModernWpf.MessageBox;
14 |
15 | namespace Lithicsoft_Trainer_Studio
16 | {
17 | ///
18 | /// Interaction logic for MainWindow.xaml
19 | ///
20 | public partial class MainWindow : Window
21 | {
22 | public MainWindow()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | private async void MainWindows_Loaded(object sender, RoutedEventArgs e)
28 | {
29 | try
30 | {
31 | this.WindowStyle = WindowStyle.None;
32 |
33 | Startup startup = new();
34 | startup.UserControlClosed += Startup_UserControlClosed;
35 | MainStackPanel.Children.Add(startup);
36 |
37 | this.SizeToContent = SizeToContent.WidthAndHeight;
38 |
39 | await WaitForUserControlToCloseAsync(startup);
40 | MainStackPanel.Children.Clear();
41 |
42 | this.WindowStyle = WindowStyle.SingleBorderWindow;
43 |
44 | MainPage mainPage = new();
45 | MainStackPanel.Children.Add(mainPage);
46 | }
47 | catch (Exception ex)
48 | {
49 | MessageBox.Show($"Error starting studio: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
50 | Environment.Exit(1);
51 | }
52 | }
53 |
54 | private void Startup_UserControlClosed(object sender, EventArgs e)
55 | {
56 | if (sender is UserControl userControl)
57 | {
58 | MainStackPanel.Children.Remove(userControl);
59 | }
60 | }
61 |
62 | private Task WaitForUserControlToCloseAsync(Startup userControl)
63 | {
64 | var tcs = new TaskCompletionSource();
65 | void handler(object? s, EventArgs e)
66 | {
67 | userControl.UserControlClosed -= handler;
68 | tcs.SetResult(true);
69 | }
70 |
71 | userControl.UserControlClosed += handler;
72 | return tcs.Task;
73 | }
74 |
75 | private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
76 | {
77 | if (Creator.Instance.isCreating)
78 | {
79 | MessageBox.Show("You can't not exit Trainer Studio while creating project!", "Prevent Closing", MessageBoxButton.OK, MessageBoxImage.Stop);
80 | e.Cancel = true;
81 | }
82 | else
83 | {
84 | if (this.Visibility != Visibility.Hidden)
85 | {
86 | var result = MessageBox.Show("Do you want to exit Trainer Studio?", "Close Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question);
87 | if (result == MessageBoxResult.Yes)
88 | System.Windows.Application.Current.Shutdown();
89 | else if (result == MessageBoxResult.No)
90 | e.Cancel = true;
91 | }
92 | }
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
62 |
63 |
64 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/UserControls/Pages/Manager.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * UserControls/Pages/Manager.xaml.cs: Back-end source code for projects manager
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.IO;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Input;
13 | using MessageBox = ModernWpf.MessageBox;
14 |
15 | namespace Lithicsoft_Trainer_Studio.UserControls.Pages
16 | {
17 | ///
18 | /// Interaction logic for Manager.xaml
19 | ///
20 | public partial class Manager : Page
21 | {
22 | public Manager()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | private void Manager_Loaded(object sender, RoutedEventArgs e)
28 | {
29 | UpdateProjectList();
30 | }
31 |
32 | private void UpdateProjectList()
33 | {
34 | try
35 | {
36 | string[] projectFiles = Directory.GetFiles("projects", "*.project", SearchOption.AllDirectories);
37 |
38 | listView1.Items.Clear();
39 |
40 |
41 | foreach (string file in projectFiles)
42 | {
43 | string[] projectConfig = File.ReadAllLines(file);
44 | if (projectConfig[0].Length <= 0)
45 | {
46 | projectConfig[0] = "Unknown";
47 | }
48 | if (projectConfig[1].Length <= 0)
49 | {
50 | projectConfig[1] = "Unknown";
51 | }
52 | string projectName = Path.GetFileNameWithoutExtension(file);
53 |
54 | listView1.Items.Add(new ProjectItems { ProjectName = projectName, ProjectLanguage = projectConfig[0], ProjectType = projectConfig[1] });
55 | }
56 | }
57 | catch (Exception ex)
58 | {
59 | MessageBox.Show($"Error updating project list: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
60 | }
61 | }
62 |
63 | protected void HandleDoubleClick(object sender, MouseButtonEventArgs e)
64 | {
65 | try
66 | {
67 | if (listView1.SelectedItems.Count > 0)
68 | {
69 | ProjectItems? selectedProject = listView1.SelectedItems[0] as ProjectItems;
70 |
71 | string? projectName = selectedProject?.ProjectName;
72 | string? projectLanguage = selectedProject?.ProjectLanguage;
73 | string? projectType = selectedProject?.ProjectType;
74 |
75 | if (!string.IsNullOrEmpty(projectName) && !string.IsNullOrEmpty(projectLanguage) && !string.IsNullOrEmpty(projectType) && projectLanguage != "Unknown" && projectType != "Unknown")
76 | {
77 | Trainer trainer = new(projectName, projectLanguage, projectType);
78 | trainer.Show();
79 | }
80 |
81 | Window parentWindow = Window.GetWindow(this);
82 | parentWindow?.Hide();
83 | }
84 | }
85 | catch (Exception ex)
86 | {
87 | MessageBox.Show($"Error opening project: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
88 | }
89 | }
90 | }
91 |
92 | public class ProjectItems
93 | {
94 | public string? ProjectName { get; set; }
95 |
96 | public string? ProjectLanguage { get; set; }
97 |
98 | public string? ProjectType { get; set; }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/CSharp/VP/TrainModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/VP/TrainModel.xaml.cs: Back-end source code for model trainer value prediction page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using Notifications.Wpf;
11 | using System.IO;
12 | using System.Windows;
13 | using System.Windows.Controls;
14 | using MessageBox = ModernWpf.MessageBox;
15 |
16 | namespace Lithicsoft_Trainer_Studio.CSharp.VP
17 | {
18 | ///
19 | /// Interaction logic for TrainModel.xaml
20 | ///
21 | public partial class TrainModel : Page
22 | {
23 | private readonly string projectName = string.Empty;
24 |
25 | public TrainModel(string name)
26 | {
27 | InitializeComponent();
28 |
29 | projectName = name;
30 | }
31 |
32 | private static TrainModel? _instance;
33 | public bool isTraining = false;
34 |
35 | public static TrainModel Instance
36 | {
37 | get
38 | {
39 | _instance ??= new TrainModel(string.Empty);
40 | return _instance;
41 | }
42 | }
43 |
44 | private void Grid_Loaded(object sender, RoutedEventArgs e)
45 | {
46 | if (File.Exists($"projects\\{projectName}\\datasets\\dataset.csv"))
47 | {
48 | label1.Content = "Ready for train your model";
49 | button1.IsEnabled = true;
50 | }
51 | else
52 | {
53 | label1.Content = "Please prepare your datasets before training model";
54 | }
55 | }
56 |
57 | private async void Button1_Click(object sender, RoutedEventArgs e)
58 | {
59 | button1.IsEnabled = false;
60 | TrainModel.Instance.isTraining = true;
61 | label1.Content = "Training your model...";
62 |
63 | Window parentWindow = Window.GetWindow(this);
64 | parentWindow?.Hide();
65 |
66 | var loadingWindow = new LoadingWindow("Training your model...")
67 | {
68 | Owner = parentWindow
69 | };
70 | loadingWindow.Show();
71 |
72 | await Task.Run(() =>
73 | {
74 | try
75 | {
76 | if (!Directory.Exists($"projects\\{projectName}\\outputs"))
77 | {
78 | Directory.CreateDirectory($"projects\\{projectName}\\outputs");
79 | }
80 |
81 | CSharpML.ValuePrediction valuePrediction = new();
82 | valuePrediction.Train(projectName);
83 | }
84 | catch (Exception ex)
85 | {
86 | Dispatcher.Invoke(() =>
87 | {
88 | MessageBox.Show($"Error training model {ex}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
89 | });
90 | }
91 | });
92 |
93 | parentWindow?.Show();
94 | loadingWindow.Close();
95 |
96 | label1.Content = "Done!";
97 |
98 | var notificationManager = new NotificationManager();
99 |
100 | notificationManager.Show(new NotificationContent
101 | {
102 | Title = "Completed training of the model",
103 | Message = "Return to Trainer Studio to test your new model.",
104 | Type = NotificationType.Information
105 | });
106 |
107 | TrainModel.Instance.isTraining = true;
108 | button1.IsEnabled = true;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/CSharp/IC/TrainModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/IC/TrainModel.xaml.cs: Back-end source code for model trainer image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using Notifications.Wpf;
11 | using System.IO;
12 | using System.Windows;
13 | using System.Windows.Controls;
14 | using MessageBox = ModernWpf.MessageBox;
15 |
16 | namespace Lithicsoft_Trainer_Studio.CSharp.IC
17 | {
18 | ///
19 | /// Interaction logic for TrainModel.xaml
20 | ///
21 |
22 | public partial class TrainModel : Page
23 | {
24 | private readonly string projectName = string.Empty;
25 |
26 | public TrainModel(string name)
27 | {
28 | InitializeComponent();
29 |
30 | projectName = name;
31 | }
32 |
33 | private static TrainModel? _instance;
34 | public bool isTraining = false;
35 |
36 | public static TrainModel Instance
37 | {
38 | get
39 | {
40 | _instance ??= new TrainModel(string.Empty);
41 | return _instance;
42 | }
43 | }
44 |
45 | private void Grid_Loaded(object sender, RoutedEventArgs e)
46 | {
47 | if (File.Exists($"projects\\{projectName}\\datasets\\tags.tsv") && File.Exists($"projects\\{projectName}\\datasets\\test-tags.tsv"))
48 | {
49 | label1.Content = "Ready for train your model";
50 | button1.IsEnabled = true;
51 | }
52 | else
53 | {
54 | label1.Content = "Please prepare your datasets before training model";
55 | }
56 | }
57 |
58 | private async void Button1_Click(object sender, RoutedEventArgs e)
59 | {
60 | button1.IsEnabled = false;
61 | TrainModel.Instance.isTraining = true;
62 | label1.Content = "Training your model...";
63 |
64 | Window parentWindow = Window.GetWindow(this);
65 | parentWindow?.Hide();
66 |
67 | var loadingWindow = new LoadingWindow("Training your model...")
68 | {
69 | Owner = parentWindow
70 | };
71 | loadingWindow.Show();
72 |
73 | await Task.Run(() =>
74 | {
75 | try
76 | {
77 | if (!Directory.Exists($"projects\\{projectName}\\outputs"))
78 | {
79 | Directory.CreateDirectory($"projects\\{projectName}\\outputs");
80 | }
81 |
82 | CSharpML.ImageClassification imageClassification = new();
83 | CSharpML.ImageClassification.Train(projectName);
84 | }
85 | catch (Exception ex)
86 | {
87 | Dispatcher.Invoke(() =>
88 | {
89 | MessageBox.Show($"Error training model {ex}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
90 | });
91 | }
92 | });
93 |
94 | parentWindow?.Show();
95 | loadingWindow.Close();
96 |
97 | label1.Content = "Done!";
98 |
99 | var notificationManager = new NotificationManager();
100 |
101 | notificationManager.Show(new NotificationContent
102 | {
103 | Title = "Completed training of the model",
104 | Message = "Return to Trainer Studio to test your new model.",
105 | Type = NotificationType.Information
106 | });
107 |
108 | TrainModel.Instance.isTraining = false;
109 | button1.IsEnabled = true;
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/UserControls/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * UserControls/MainPage.xaml.cs: Back-end source code for home page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.UserControls.Pages;
10 | using Microsoft.Win32;
11 | using System.Diagnostics;
12 | using System.IO.Compression;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using MessageBox = ModernWpf.MessageBox;
16 |
17 | namespace Lithicsoft_Trainer_Studio.UserControls
18 | {
19 | ///
20 | /// Interaction logic for MainPage.xaml
21 | ///
22 | public partial class MainPage : UserControl
23 | {
24 | public MainPage()
25 | {
26 | InitializeComponent();
27 | }
28 |
29 | private void MainPage_Loaded(object sender, RoutedEventArgs e)
30 | {
31 | try
32 | {
33 | Main.Content = new Manager();
34 | }
35 | catch (Exception ex)
36 | {
37 | MessageBox.Show($"Error opening manager: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
38 | }
39 | }
40 |
41 | private void Button1_Click(object sender, RoutedEventArgs e)
42 | {
43 | try
44 | {
45 | Main.Content = new Creator();
46 | button4.IsEnabled = true;
47 | }
48 | catch (Exception ex)
49 | {
50 | MessageBox.Show($"Error opening creator: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
51 | }
52 | }
53 |
54 | private void Button4_Click(object sender, RoutedEventArgs e)
55 | {
56 | try
57 | {
58 | Main.Content = new Manager();
59 | button4.IsEnabled = false;
60 | }
61 | catch (Exception ex)
62 | {
63 | MessageBox.Show($"Error opening manager: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
64 | }
65 | }
66 |
67 | private void Button_Click(object sender, RoutedEventArgs e)
68 | {
69 | try
70 | {
71 | OpenFileDialog openFileDialog = new()
72 | {
73 | Filter = "Zip files (*.zip)|*.zip"
74 | };
75 | Nullable result = openFileDialog.ShowDialog();
76 | if (result == true)
77 | {
78 | string zipPath = openFileDialog.FileName;
79 | string extractPath = "projects";
80 | ZipFile.ExtractToDirectory(zipPath, extractPath);
81 | MessageBox.Show($"Imported '{openFileDialog.FileName}' successfully", "Import Project", MessageBoxButton.OK, MessageBoxImage.Information);
82 | }
83 |
84 | Main.Content = new Manager();
85 | }
86 | catch (Exception ex)
87 | {
88 | MessageBox.Show($"Error importing project: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
89 | }
90 | }
91 |
92 | private void Button_Click_1(object sender, RoutedEventArgs e)
93 | {
94 | try
95 | {
96 | System.Diagnostics.Process.Start(new ProcessStartInfo
97 | {
98 | FileName = "https://github.com/Lithicsoft/Lithicsoft-Trainer-Studio",
99 | UseShellExecute = true
100 | });
101 | }
102 | catch (Exception ex)
103 | {
104 | MessageBox.Show($"Error opening info: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Lithicsoft Trainer Studio.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <_LastSelectedProfileId>C:\Users\tansa\Source\Repos\TS-Source\Properties\PublishProfiles\FolderProfile.pubxml
5 |
6 |
7 |
8 | Designer
9 |
10 |
11 |
12 |
13 | Code
14 |
15 |
16 | Code
17 |
18 |
19 | Code
20 |
21 |
22 | Code
23 |
24 |
25 | Code
26 |
27 |
28 | Code
29 |
30 |
31 | Code
32 |
33 |
34 | Code
35 |
36 |
37 | Code
38 |
39 |
40 | Code
41 |
42 |
43 | Code
44 |
45 |
46 | Code
47 |
48 |
49 |
50 |
51 | Designer
52 |
53 |
54 | Designer
55 |
56 |
57 | Designer
58 |
59 |
60 | Designer
61 |
62 |
63 | Designer
64 |
65 |
66 | Designer
67 |
68 |
69 | Designer
70 |
71 |
72 | Designer
73 |
74 |
75 | Designer
76 |
77 |
78 | Designer
79 |
80 |
81 | Designer
82 |
83 |
84 | Designer
85 |
86 |
87 | Designer
88 |
89 |
90 | Designer
91 |
92 |
93 | Designer
94 |
95 |
96 | Designer
97 |
98 |
99 | Designer
100 |
101 |
102 | Designer
103 |
104 |
105 | Designer
106 |
107 |
108 |
--------------------------------------------------------------------------------
/Python/PY/ConfigModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Python/PY/ConfigModel.xaml.cs: Back-end source code for config model python page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.Collections.ObjectModel;
10 | using System.IO;
11 | using System.Windows;
12 | using System.Windows.Controls;
13 | using MessageBox = ModernWpf.MessageBox;
14 |
15 | namespace Lithicsoft_Trainer_Studio.Python.PY
16 | {
17 | ///
18 | /// Interaction logic for ConfigModel.xaml
19 | ///
20 | public partial class ConfigModel : Page
21 | {
22 | private readonly string projectName = string.Empty;
23 |
24 | public ConfigModel(string name)
25 | {
26 | InitializeComponent();
27 |
28 | projectName = name;
29 | }
30 |
31 | private ObservableCollection? items;
32 | private Dictionary? trainParameters;
33 |
34 | private void Page_Loaded(object sender, RoutedEventArgs e)
35 | {
36 | try
37 | {
38 | trainParameters = (Dictionary)DotEnv.Load($"projects\\{projectName}\\.env");
39 |
40 | items = [];
41 |
42 | foreach (var kvp in trainParameters)
43 | {
44 | items.Add(new VariableSelection { Variable = kvp.Key, Value = kvp.Value });
45 | }
46 |
47 | listView1.ItemsSource = items;
48 | }
49 | catch (Exception ex)
50 | {
51 | MessageBox.Show($"Error loading config: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
52 | Environment.Exit(1);
53 | }
54 | }
55 |
56 | private void Button_Click(object sender, RoutedEventArgs e)
57 | {
58 | try
59 | {
60 | if (items != null)
61 | {
62 | foreach (var item in items)
63 | {
64 | if (trainParameters != null && item.Variable != null && item.Value != null)
65 | {
66 | trainParameters[item.Variable] = item.Value;
67 | }
68 | }
69 | }
70 |
71 | if (trainParameters != null)
72 | {
73 | DotEnv.Save($"projects\\{projectName}\\.env", trainParameters);
74 | MessageBox.Show("All changes have been saved.", "Saving Config", MessageBoxButton.OK, MessageBoxImage.Information);
75 | }
76 | }
77 | catch (Exception ex)
78 | {
79 | MessageBox.Show($"Error saving config: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
80 | }
81 | }
82 |
83 | public class VariableSelection
84 | {
85 | public string? Variable { get; set; }
86 | public string? Value { get; set; }
87 | }
88 | }
89 |
90 | public static class DotEnv
91 | {
92 | public static IDictionary Load(string filePath)
93 | {
94 | var envDictionary = new Dictionary();
95 |
96 | foreach (var line in File.ReadAllLines(filePath))
97 | {
98 | if (string.IsNullOrWhiteSpace(line) || line.StartsWith('#'))
99 | continue;
100 |
101 | var parts = line.Split('=', 2);
102 | if (parts.Length != 2)
103 | continue;
104 |
105 | var key = parts[0].Trim();
106 | var value = parts[1].Trim();
107 |
108 | envDictionary[key] = value;
109 | }
110 |
111 | return envDictionary;
112 | }
113 |
114 | public static void Save(string filePath, IDictionary envDictionary)
115 | {
116 | var lines = new List();
117 |
118 | foreach (var kvp in envDictionary)
119 | {
120 | lines.Add($"{kvp.Key}={kvp.Value}");
121 | }
122 |
123 | File.WriteAllLines(filePath, lines);
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/CSharp/VP/TestModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/VP/TestModel.xaml.cs: Back-end source code for model tester value prediction page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Microsoft.ML;
10 | using Microsoft.ML.Data;
11 | using System.IO;
12 | using System.Windows;
13 | using MessageBox = ModernWpf.MessageBox;
14 | using Page = System.Windows.Controls.Page;
15 |
16 | namespace Lithicsoft_Trainer_Studio.CSharp.VP
17 | {
18 | ///
19 | /// Interaction logic for TestModel.xaml
20 | ///
21 | public partial class TestModel : Page
22 | {
23 | private readonly string projectName = string.Empty;
24 |
25 | public TestModel(string name)
26 | {
27 | InitializeComponent();
28 |
29 | projectName = name;
30 | }
31 |
32 | private MLContext? mlContext;
33 | private PredictionEngine? predictionEngine;
34 |
35 | private void Page_Loaded(object sender, RoutedEventArgs e)
36 | {
37 | if (File.Exists($"projects\\{projectName}\\outputs\\model.zip"))
38 | {
39 | button1.IsEnabled = true;
40 | ValueA.IsEnabled = true;
41 | ValueB.IsEnabled = true;
42 | ValueC.IsEnabled = true;
43 | ValueD.IsEnabled = true;
44 | }
45 | }
46 |
47 | readonly ModelOutput? prediction;
48 | private async void Button_Click(object sender, RoutedEventArgs e)
49 | {
50 | button1.IsEnabled = false;
51 |
52 | progressBar.Visibility = Visibility.Visible;
53 |
54 | var sampleInput = new ModelInput
55 | {
56 | A = float.Parse(ValueA.Text),
57 | B = float.Parse(ValueB.Text),
58 | C = float.Parse(ValueC.Text),
59 | D = float.Parse(ValueD.Text)
60 | };
61 |
62 | await Task.Run(() =>
63 | {
64 | try
65 | {
66 | InitModel();
67 |
68 | if (predictionEngine != null)
69 | {
70 | var prediction = predictionEngine.Predict(sampleInput);
71 | }
72 | }
73 | catch (Exception ex)
74 | {
75 | Dispatcher.Invoke(() =>
76 | {
77 | MessageBox.Show($"Error testing model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
78 | });
79 | }
80 | });
81 |
82 | progressBar.Visibility = Visibility.Hidden;
83 |
84 | if (prediction != null)
85 | {
86 | label1.Content = "Predict: " + prediction.Prediction;
87 | }
88 | button1.IsEnabled = true;
89 | }
90 |
91 | private void InitModel()
92 | {
93 | try
94 | {
95 | mlContext = new MLContext();
96 | ITransformer predictionPipeline = mlContext.Model.Load($"projects\\{projectName}\\outputs\\model.zip", out DataViewSchema predictionPipelineSchema);
97 | predictionEngine = mlContext.Model.CreatePredictionEngine(predictionPipeline);
98 | }
99 | catch (Exception ex)
100 | {
101 | MessageBox.Show($"Error loading model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
102 | }
103 | }
104 |
105 | public class ModelInput
106 | {
107 | [LoadColumn(0)]
108 | public float A { get; set; }
109 |
110 | [LoadColumn(1)]
111 | public float B { get; set; }
112 |
113 | [LoadColumn(2)]
114 | public float C { get; set; }
115 |
116 | [LoadColumn(3)]
117 | public float D { get; set; }
118 |
119 | [LoadColumn(4)]
120 | public float Prediction { get; set; }
121 | }
122 |
123 | public class ModelOutput
124 | {
125 | [ColumnName("Score")]
126 | public float Prediction { get; set; }
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/Python/PY/TrainModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Python/PY/TrainModel.xaml.cs: Back-end source code for model trainer image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using Notifications.Wpf;
11 | using System.Diagnostics;
12 | using System.IO;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using MessageBox = ModernWpf.MessageBox;
16 |
17 | namespace Lithicsoft_Trainer_Studio.Python.PY
18 | {
19 | ///
20 | /// Interaction logic for TrainModel.xaml
21 | ///
22 | public partial class TrainModel : Page
23 | {
24 | private readonly string projectName = string.Empty;
25 |
26 | public TrainModel(string name)
27 | {
28 | InitializeComponent();
29 |
30 | projectName = name;
31 | }
32 |
33 | private static TrainModel? _instance;
34 | public bool isTraining = false;
35 |
36 | public static TrainModel Instance
37 | {
38 | get
39 | {
40 | _instance ??= new TrainModel(string.Empty);
41 | return _instance;
42 | }
43 | }
44 |
45 | private void Grid_Loaded(object sender, RoutedEventArgs e)
46 | {
47 | if (Directory.Exists($"projects\\{projectName}\\datasets"))
48 | {
49 | label1.Content = "Ready for train your model";
50 | }
51 | else
52 | {
53 | label1.Content = "Load your datasets (if there is) before training model";
54 | }
55 | button1.IsEnabled = true;
56 | }
57 |
58 | private async void Button1_Click(object sender, RoutedEventArgs e)
59 | {
60 | button1.IsEnabled = false;
61 | TrainModel.Instance.isTraining = true;
62 | label1.Content = "Training your model...";
63 |
64 | Window parentWindow = Window.GetWindow(this);
65 | parentWindow?.Hide();
66 |
67 | var loadingWindow = new LoadingWindow("Training your model...")
68 | {
69 | Owner = parentWindow
70 | };
71 | loadingWindow.Show();
72 |
73 | await Task.Run(() =>
74 | {
75 | try
76 | {
77 | if (!Directory.Exists($"projects\\{projectName}\\outputs"))
78 | {
79 | Directory.CreateDirectory($"projects\\{projectName}\\outputs");
80 | }
81 |
82 | ProcessStartInfo start = new()
83 | {
84 | FileName = $"cmd.exe",
85 | Arguments = $"/K conda activate \"{projectName}\" & python \"{Path.Combine(Environment.CurrentDirectory, $"projects\\{projectName}\\trainer.py")}\" & conda deactivate & pause & exit",
86 | UseShellExecute = true,
87 | RedirectStandardOutput = false
88 | };
89 |
90 | using (var process = Process.Start(start))
91 | {
92 | if (process != null)
93 | {
94 | process.WaitForExit();
95 | }
96 | }
97 | }
98 | catch (Exception ex)
99 | {
100 | Dispatcher.Invoke(() =>
101 | {
102 | MessageBox.Show($"Error training model: {ex}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
103 | });
104 | }
105 | });
106 |
107 | parentWindow?.Show();
108 | loadingWindow.Close();
109 |
110 | label1.Content = "Done!";
111 |
112 | var notificationManager = new NotificationManager();
113 |
114 | notificationManager.Show(new NotificationContent
115 | {
116 | Title = "Completed training of the model",
117 | Message = "Return to Trainer Studio to test your new model.",
118 | Type = NotificationType.Information
119 | });
120 |
121 | TrainModel.Instance.isTraining = false;
122 | button1.IsEnabled = true;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/CSharp/IC/TestModel.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/IC/TestModel.xaml.cs: Back-end source code for model tester image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Microsoft.ML;
10 | using Microsoft.ML.Data;
11 | using Microsoft.Win32;
12 | using System.IO;
13 | using System.Windows;
14 | using System.Windows.Media.Imaging;
15 | using MessageBox = ModernWpf.MessageBox;
16 | using Page = System.Windows.Controls.Page;
17 |
18 | namespace Lithicsoft_Trainer_Studio.CSharp.IC
19 | {
20 | ///
21 | /// Interaction logic for TestModel.xaml
22 | ///
23 | public partial class TestModel : Page
24 | {
25 | private readonly string projectName = string.Empty;
26 |
27 | public TestModel(string name)
28 | {
29 | InitializeComponent();
30 |
31 | projectName = name;
32 | }
33 |
34 | private MLContext? mlContext;
35 | private PredictionEngine? predictionEngine;
36 |
37 | private void Page_Loaded(object sender, RoutedEventArgs e)
38 | {
39 | if (File.Exists($"projects\\{projectName}\\outputs\\model.zip"))
40 | {
41 | button1.IsEnabled = true;
42 | }
43 | }
44 |
45 | ImagePrediction? prediction;
46 | private async void Button_Click(object sender, RoutedEventArgs e)
47 | {
48 | button1.IsEnabled = false;
49 |
50 | OpenFileDialog openFileDialog = new()
51 | {
52 | Filter = "Image files (*.png, *.jpg, *.webp)|*.png;*.jpg;*.webp"
53 | };
54 | Nullable result = openFileDialog.ShowDialog();
55 |
56 | if (string.IsNullOrEmpty(openFileDialog.FileName))
57 | {
58 | button1.IsEnabled = true;
59 | return;
60 | }
61 |
62 | BitmapImage bitmap = new();
63 | bitmap.BeginInit();
64 | bitmap.UriSource = new Uri(openFileDialog.FileName, UriKind.Absolute);
65 | bitmap.EndInit();
66 |
67 | image1.Source = bitmap;
68 |
69 | progressBar.Visibility = Visibility.Visible;
70 |
71 | await Task.Run(() =>
72 | {
73 | try
74 | {
75 | if (result == true)
76 | {
77 | InitModel();
78 | var imageData = new ImageData()
79 | {
80 | ImagePath = openFileDialog.FileName
81 | };
82 |
83 | if (predictionEngine != null)
84 | {
85 | prediction = predictionEngine.Predict(imageData);
86 | }
87 | }
88 | }
89 | catch (Exception ex)
90 | {
91 | Dispatcher.Invoke(() =>
92 | {
93 | MessageBox.Show($"Error running model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
94 | });
95 | }
96 | });
97 |
98 | progressBar.Visibility = Visibility.Hidden;
99 |
100 | if (prediction != null)
101 | {
102 | label1.Content = "Predict: " + prediction.PredictedLabelValue;
103 | }
104 | button1.IsEnabled = true;
105 | }
106 |
107 | private void InitModel()
108 | {
109 | try
110 | {
111 | mlContext = new MLContext();
112 | ITransformer predictionPipeline = mlContext.Model.Load($"projects\\{projectName}\\outputs\\model.zip", out DataViewSchema predictionPipelineSchema);
113 | predictionEngine = mlContext.Model.CreatePredictionEngine(predictionPipeline);
114 | }
115 | catch (Exception ex)
116 | {
117 | MessageBox.Show($"Error loading model: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
118 | return;
119 | }
120 | }
121 |
122 | public class ImageData
123 | {
124 | [LoadColumn(0)]
125 | public string? ImagePath;
126 |
127 | [LoadColumn(1)]
128 | public string? Label;
129 | }
130 |
131 | public class ImagePrediction : ImageData
132 | {
133 | public float[]? Score;
134 |
135 | public string? PredictedLabelValue;
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/Python/PY/PrepareDataset.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * Python/PY/PrepareDataset.xaml.cs: Back-end source code for data prepare python page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using Microsoft.Win32;
11 | using System.Diagnostics;
12 | using System.IO;
13 | using System.IO.Compression;
14 | using System.Windows;
15 | using System.Windows.Controls;
16 | using System.Windows.Documents;
17 | using MessageBox = ModernWpf.MessageBox;
18 |
19 | namespace Lithicsoft_Trainer_Studio.Python.PY
20 | {
21 | ///
22 | /// Interaction logic for PrepareDataset.xaml
23 | ///
24 | public partial class PrepareDataset : Page
25 | {
26 | private readonly string projectName = string.Empty;
27 |
28 | public PrepareDataset(string name)
29 | {
30 | InitializeComponent();
31 |
32 | projectName = name;
33 |
34 | if (File.Exists($"projects\\{projectName}\\tree.txt"))
35 | {
36 | DocCode.Document.Blocks.Clear();
37 | DocCode.Document.Blocks.Add(new Paragraph(new Run(File.ReadAllText($"projects\\{projectName}\\tree.txt"))));
38 | }
39 | }
40 |
41 | private void Button_Click(object sender, RoutedEventArgs e)
42 | {
43 | try
44 | {
45 | OpenFileDialog openFileDialog = new()
46 | {
47 | Filter = "Zip files (*.zip)|*.zip"
48 | };
49 | Nullable result = openFileDialog.ShowDialog();
50 | if (!string.IsNullOrEmpty(openFileDialog.FileName))
51 | {
52 | textBox1.Text = openFileDialog.FileName;
53 | }
54 | }
55 | catch (Exception ex)
56 | {
57 | MessageBox.Show($"Error opening zip file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
58 | }
59 | }
60 |
61 | private async void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
62 | {
63 | await LoadDataset(textBox1.Text);
64 | }
65 |
66 | private async Task LoadDataset(string path)
67 | {
68 | button1.IsEnabled = false;
69 | textBox1.IsEnabled = false;
70 |
71 | Window parentWindow = Window.GetWindow(this);
72 | parentWindow?.Hide();
73 |
74 | var loadingWindow = new LoadingWindow("Preparing your dataset...")
75 | {
76 | Owner = parentWindow
77 | };
78 | loadingWindow.Show();
79 |
80 | await Task.Run(() =>
81 | {
82 | if (File.Exists(path))
83 | {
84 | try
85 | {
86 | if (Directory.Exists($"projects\\{projectName}\\datasets"))
87 | {
88 | Directory.Delete($"projects\\{projectName}\\datasets", true);
89 | }
90 | Directory.CreateDirectory($"projects\\{projectName}\\datasets");
91 | string extractPath = $"projects\\{projectName}\\datasets";
92 | ZipFile.ExtractToDirectory(path, extractPath);
93 |
94 | ProcessStartInfo start = new()
95 | {
96 | FileName = $"cmd.exe",
97 | Arguments = $"/K tree projects\\{projectName}\\datasets /F /A > projects\\{projectName}\\tree.txt & exit",
98 | UseShellExecute = false,
99 | RedirectStandardOutput = true,
100 | CreateNoWindow = true
101 | };
102 |
103 | using (var process = Process.Start(start))
104 | {
105 | if (process != null)
106 | {
107 | process.WaitForExit();
108 | }
109 | }
110 | }
111 | catch (Exception ex)
112 | {
113 | Dispatcher.Invoke(() =>
114 | {
115 | MessageBox.Show($"Error loading dataset: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
116 | });
117 | }
118 | }
119 | else
120 | {
121 | Dispatcher.Invoke(() =>
122 | {
123 | MessageBox.Show($"File not found!", "File Error", MessageBoxButton.OK, MessageBoxImage.Error);
124 | });
125 | }
126 | });
127 |
128 | if (File.Exists($"projects\\{projectName}\\tree.txt"))
129 | {
130 | DocCode.Document.Blocks.Clear();
131 | DocCode.Document.Blocks.Add(new Paragraph(new Run(File.ReadAllText($"projects\\{projectName}\\tree.txt"))));
132 | }
133 |
134 | parentWindow?.Show();
135 | loadingWindow.Close();
136 |
137 | button1.IsEnabled = true;
138 | textBox1.IsEnabled = true;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/CSharpML/ImageClassification.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharpML/ImageClassification.cs: CSharp trainer for image classification
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Microsoft.ML;
10 | using Microsoft.ML.Data;
11 | using System.IO;
12 | using System.Text;
13 |
14 | namespace Lithicsoft_Trainer_Studio.CSharpML
15 | {
16 | class ImageClassification
17 | {
18 | static string _assetsPath = Path.Combine(Environment.CurrentDirectory, ".");
19 | static string _imagesFolder = Path.Combine(_assetsPath, ".");
20 | static string _trainTagsTsv = Path.Combine(_imagesFolder, ".");
21 | static string _testTagsTsv = Path.Combine(_imagesFolder, ".");
22 | static string _inceptionTensorFlowModel = Path.Combine(_assetsPath, ".", ".");
23 |
24 | private static string projectName = string.Empty;
25 |
26 | public static void Train(string name)
27 | {
28 | projectName = name;
29 |
30 | _assetsPath = Path.Combine(Environment.CurrentDirectory, $"projects\\{projectName}");
31 | _imagesFolder = Path.Combine(_assetsPath, "datasets");
32 | _trainTagsTsv = Path.Combine(_imagesFolder, "tags.tsv");
33 | _testTagsTsv = Path.Combine(_imagesFolder, "test-tags.tsv");
34 | _inceptionTensorFlowModel = Path.Combine("inception", "tensorflow_inception_graph.pb");
35 |
36 | MLContext mlContext = new();
37 |
38 | GenerateModel(mlContext);
39 | }
40 |
41 | public static void DataPrepare(string rootPath, string projectName)
42 | {
43 | var directories = Directory.GetDirectories(rootPath);
44 |
45 | var tsvData = new StringBuilder();
46 |
47 | foreach (var directory in directories)
48 | {
49 | var label = Path.GetFileName(directory);
50 |
51 | var files = Directory.GetFiles(directory, "*.*");
52 |
53 | foreach (var file in files)
54 | {
55 | var extension = Path.GetExtension(file).ToLower();
56 | if (extension == ".png" || extension == ".jpg" || extension == ".webp")
57 | {
58 | var relativePath = Path.GetRelativePath(rootPath, file);
59 |
60 | tsvData.AppendLine($"{relativePath}\t{label}");
61 | }
62 | }
63 | }
64 |
65 | var tsvContent = tsvData.ToString();
66 | var tagsPath = Path.Combine("projects", projectName, "datasets", "tags.tsv");
67 | var testTagsPath = Path.Combine("projects", projectName, "datasets", "test-tags.tsv");
68 |
69 | File.WriteAllText(tagsPath, tsvContent);
70 | File.WriteAllText(testTagsPath, tsvContent);
71 | }
72 |
73 | public static ITransformer GenerateModel(MLContext mlContext)
74 | {
75 | EstimatorChain pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: _imagesFolder, inputColumnName: nameof(ImageData.ImagePath))
76 | .Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input"))
77 | .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean))
78 | .Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel).
79 | ScoreTensorFlowModel(outputColumnNames: ["softmax2_pre_activation"], inputColumnNames: ["input"], addBatchDimensionInput: true))
80 | .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
81 | .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
82 | .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel"))
83 | .AppendCacheCheckpoint(mlContext);
84 |
85 | IDataView trainingData = mlContext.Data.LoadFromTextFile(path: _trainTagsTsv, hasHeader: false);
86 |
87 | TransformerChain model = pipeline.Fit(trainingData);
88 |
89 | IDataView testData = mlContext.Data.LoadFromTextFile(path: _testTagsTsv, hasHeader: false);
90 | IDataView predictions = model.Transform(testData);
91 |
92 | mlContext.Data.CreateEnumerable(predictions, true);
93 |
94 | mlContext.MulticlassClassification.Evaluate(predictions,
95 | labelColumnName: "LabelKey",
96 | predictedLabelColumnName: "PredictedLabel");
97 |
98 | mlContext.Model.Save(model, trainingData.Schema, $"projects\\{projectName}\\outputs\\model.zip");
99 | using FileStream stream = File.Create($"projects\\{projectName}\\outputs\\onnx_model.onnx");
100 |
101 | return model;
102 | }
103 |
104 | private struct InceptionSettings
105 | {
106 | public const int ImageHeight = 224;
107 | public const int ImageWidth = 224;
108 | public const float Mean = 117;
109 | public const float Scale = 1;
110 | public const bool ChannelsLast = true;
111 | }
112 |
113 | public class ImageData
114 | {
115 | [LoadColumn(0)]
116 | public string? ImagePath;
117 |
118 | [LoadColumn(1)]
119 | public string? Label;
120 | }
121 |
122 | public class ImagePrediction : ImageData
123 | {
124 | public float[]? Score;
125 |
126 | public string? PredictedLabelValue;
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/UserControls/Startup.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * UserControls/Startup.xaml.cs: Back-end source code for launcher
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using System.IO;
10 | using System.IO.Compression;
11 | using System.Net;
12 | using System.Net.Http;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using MessageBox = ModernWpf.MessageBox;
16 |
17 | namespace Lithicsoft_Trainer_Studio.UserControls
18 | {
19 | ///
20 | /// Interaction logic for Startup.xaml
21 | ///
22 | public partial class Startup : UserControl
23 | {
24 | public Startup()
25 | {
26 | InitializeComponent();
27 | }
28 |
29 | public event EventHandler? UserControlClosed;
30 |
31 | private void Startup_Loaded(object sender, RoutedEventArgs e)
32 | {
33 | try
34 | {
35 | StartInitialization();
36 | }
37 | catch (Exception ex)
38 | {
39 | MessageBox.Show($"Error starting Trainer Studio: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
40 | }
41 | }
42 |
43 | private async void StartInitialization()
44 | {
45 | await InitializeAsync();
46 | await Task.Delay(1500);
47 | OnUserControlClosed();
48 | }
49 |
50 | private static async Task InitializeAsync()
51 | {
52 | CreateProjectsFolder();
53 | await CheckAndDownloadFilesAsync();
54 | }
55 |
56 | protected virtual void OnUserControlClosed()
57 | {
58 | UserControlClosed?.Invoke(this, EventArgs.Empty);
59 | }
60 |
61 | private static void CreateProjectsFolder()
62 | {
63 | if (!Directory.Exists("projects"))
64 | {
65 | Directory.CreateDirectory("projects");
66 | }
67 | }
68 |
69 | private static async Task CheckAndDownloadFilesAsync()
70 | {
71 | try
72 | {
73 |
74 | if (!Directory.Exists("inception"))
75 | {
76 | Directory.CreateDirectory("inception");
77 | }
78 |
79 | if (!File.Exists("inception\\tensorflow_inception_graph.pb"))
80 | {
81 | string zipFile = "inception\\inception5h.zip";
82 |
83 | using (HttpClient client = new())
84 | {
85 | try
86 | {
87 | HttpResponseMessage response = await client.GetAsync(new Uri("https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip"));
88 | response.EnsureSuccessStatusCode();
89 |
90 | using FileStream fs = new(zipFile, FileMode.Create, FileAccess.Write, FileShare.None);
91 | await response.Content.CopyToAsync(fs);
92 | }
93 | catch (WebException ex)
94 | {
95 | MessageBox.Show($"Error downloading file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
96 | Environment.Exit(1);
97 | }
98 | }
99 |
100 | try
101 | {
102 | string extractPath = "inception";
103 | await Task.Run(() => ZipFile.ExtractToDirectory(zipFile, extractPath));
104 | }
105 | catch (InvalidDataException ex)
106 | {
107 | MessageBox.Show($"Error extracting zip file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
108 | Environment.Exit(1);
109 | }
110 | }
111 |
112 | if (!File.Exists("sentiment_model\\saved_model.pb"))
113 | {
114 | string zipFile = "sentiment_model.zip";
115 |
116 | using (HttpClient client = new())
117 | {
118 | try
119 | {
120 | HttpResponseMessage response = await client.GetAsync(new Uri("https://github.com/dotnet/samples/blob/main/machine-learning/models/textclassificationtf/sentiment_model.zip?raw=true"));
121 | response.EnsureSuccessStatusCode();
122 |
123 | using FileStream fs = new(zipFile, FileMode.Create, FileAccess.Write, FileShare.None);
124 | await response.Content.CopyToAsync(fs);
125 | }
126 | catch (WebException ex)
127 | {
128 | MessageBox.Show($"Error downloading file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
129 | Environment.Exit(1);
130 | }
131 | }
132 |
133 | try
134 | {
135 | await Task.Run(() => ZipFile.ExtractToDirectory(zipFile, "."));
136 | }
137 | catch (InvalidDataException ex)
138 | {
139 | MessageBox.Show($"Error extracting zip file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
140 | Environment.Exit(1);
141 | }
142 | }
143 |
144 | string[] filesToDelete = [
145 | "inception\\inception5h.zip",
146 | "sentiment_model.zip",
147 | ];
148 |
149 | foreach (string filePath in filesToDelete)
150 | {
151 | if (File.Exists(filePath))
152 | {
153 | File.Delete(filePath);
154 | }
155 | }
156 | }
157 | catch (Exception ex)
158 | {
159 | MessageBox.Show($"Error starting studio: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
160 | Environment.Exit(1);
161 | }
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/CSharp/VP/PrepareDataset.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/VP/PrepareDataset.xaml.cs: Back-end source code for data prepare value prediction page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using Microsoft.Win32;
11 | using System.Diagnostics;
12 | using System.IO;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using System.Windows.Documents;
16 | using MessageBox = ModernWpf.MessageBox;
17 |
18 | namespace Lithicsoft_Trainer_Studio.CSharp.VP
19 | {
20 | ///
21 | /// Interaction logic for PrepareDataset.xaml
22 | ///
23 | public partial class PrepareDataset : Page
24 | {
25 | private readonly string projectName = string.Empty;
26 |
27 | public PrepareDataset(string name)
28 | {
29 | InitializeComponent();
30 |
31 | projectName = name;
32 |
33 | if (File.Exists($"projects\\{projectName}\\tree.txt"))
34 | {
35 | DocCode.Document.Blocks.Clear();
36 | DocCode.Document.Blocks.Add(new Paragraph(new Run(File.ReadAllText($"projects\\{projectName}\\tree.txt"))));
37 | }
38 | }
39 |
40 | private void Button_Click(object sender, RoutedEventArgs e)
41 | {
42 | try
43 | {
44 | OpenFileDialog openFileDialog = new()
45 | {
46 | Filter = "Csv files (*.csv)|*.csv"
47 | };
48 | Nullable result = openFileDialog.ShowDialog();
49 | if (!string.IsNullOrEmpty(openFileDialog.FileName))
50 | {
51 | textBox1.Text = openFileDialog.FileName;
52 | }
53 | }
54 | catch (Exception ex)
55 | {
56 | MessageBox.Show($"Error opening zip file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
57 | }
58 | }
59 |
60 | private async void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
61 | {
62 | await LoadDataset(textBox1.Text);
63 | }
64 |
65 | private async Task LoadDataset(string path)
66 | {
67 | button1.IsEnabled = false;
68 | textBox1.IsEnabled = false;
69 |
70 | Window parentWindow = Window.GetWindow(this);
71 | parentWindow?.Hide();
72 |
73 | var loadingWindow = new LoadingWindow("Preparing your dataset...")
74 | {
75 | Owner = parentWindow
76 | };
77 | loadingWindow.Show();
78 |
79 | await Task.Run(() =>
80 | {
81 | try
82 | {
83 | if (CheckCsvFormat(path))
84 | {
85 | Dispatcher.Invoke(() =>
86 | {
87 | MessageBox.Show("The csv structure is invalid", "Dataset Structure", MessageBoxButton.OK, MessageBoxImage.Error);
88 | });
89 | return;
90 | }
91 | }
92 | catch (Exception ex)
93 | {
94 | Dispatcher.Invoke(() =>
95 | {
96 | MessageBox.Show($"Error checking csv file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
97 | });
98 | return;
99 | }
100 |
101 | if (File.Exists(path))
102 | {
103 | try
104 | {
105 | if (Directory.Exists($"projects\\{projectName}\\datasets"))
106 | {
107 | Directory.Delete($"projects\\{projectName}\\datasets", true);
108 | }
109 | Directory.CreateDirectory($"projects\\{projectName}\\datasets");
110 | File.Copy(path, $"projects\\{projectName}\\datasets\\dataset.csv");
111 |
112 | ProcessStartInfo start = new()
113 | {
114 | FileName = $"cmd.exe",
115 | Arguments = $"/K tree projects\\{projectName}\\datasets /F /A > projects\\{projectName}\\tree.txt & exit",
116 | UseShellExecute = false,
117 | RedirectStandardOutput = true,
118 | CreateNoWindow = true
119 | };
120 |
121 | using (var process = Process.Start(start))
122 | {
123 | if (process != null)
124 | {
125 | process.WaitForExit();
126 | }
127 | }
128 | }
129 | catch (Exception ex)
130 | {
131 | Dispatcher.Invoke(() =>
132 | {
133 | MessageBox.Show($"Error loading dataset: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
134 | });
135 | }
136 | }
137 | else
138 | {
139 | Dispatcher.Invoke(() =>
140 | {
141 | MessageBox.Show($"File not found!", "File Error", MessageBoxButton.OK, MessageBoxImage.Error);
142 | });
143 | }
144 | });
145 |
146 | if (File.Exists($"projects\\{projectName}\\tree.txt"))
147 | {
148 | DocCode.Document.Blocks.Clear();
149 | DocCode.Document.Blocks.Add(new Paragraph(new Run(File.ReadAllText($"projects\\{projectName}\\tree.txt"))));
150 | }
151 |
152 | parentWindow?.Show();
153 | loadingWindow.Close();
154 |
155 | button1.IsEnabled = true;
156 | textBox1.IsEnabled = true;
157 | }
158 |
159 | private static bool CheckCsvFormat(string filePath)
160 | {
161 | var lines = File.ReadAllLines(filePath);
162 |
163 | if (lines.Length == 0)
164 | {
165 | return false;
166 | }
167 |
168 | foreach (var line in lines)
169 | {
170 | var columns = line.Split(',');
171 |
172 | if (columns.Length != 5)
173 | {
174 | return false;
175 | }
176 |
177 | for (int cloumn = 0; cloumn < columns.Length; cloumn++)
178 | {
179 | if (!float.TryParse(columns[cloumn], out _))
180 | {
181 | return false;
182 | }
183 | }
184 | }
185 |
186 | return true;
187 | }
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/CSharp/IC/PrepareDataset.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * CSharp/IC/PrepareDataset.xaml.cs: Back-end source code for data prepare image classification page
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using Microsoft.Win32;
11 | using System.Diagnostics;
12 | using System.IO;
13 | using System.IO.Compression;
14 | using System.Windows;
15 | using System.Windows.Controls;
16 | using System.Windows.Documents;
17 | using MessageBox = ModernWpf.MessageBox;
18 |
19 | namespace Lithicsoft_Trainer_Studio.CSharp.IC
20 | {
21 | ///
22 | /// Interaction logic for PrepareDataset.xaml
23 | ///
24 | public partial class PrepareDataset : Page
25 | {
26 | private readonly string projectName = string.Empty;
27 |
28 | public PrepareDataset(string name)
29 | {
30 | InitializeComponent();
31 |
32 | projectName = name;
33 |
34 | if (File.Exists($"projects\\{projectName}\\tree.txt"))
35 | {
36 | DocCode.Document.Blocks.Clear();
37 | DocCode.Document.Blocks.Add(new Paragraph(new Run(File.ReadAllText($"projects\\{projectName}\\tree.txt"))));
38 | }
39 | }
40 |
41 | private void Button_Click(object sender, RoutedEventArgs e)
42 | {
43 | try
44 | {
45 | OpenFileDialog openFileDialog = new()
46 | {
47 | Filter = "Zip files (*.zip)|*.zip"
48 | };
49 | Nullable result = openFileDialog.ShowDialog();
50 | if (!string.IsNullOrEmpty(openFileDialog.FileName))
51 | {
52 | textBox1.Text = openFileDialog.FileName;
53 | }
54 | }
55 | catch (Exception ex)
56 | {
57 | MessageBox.Show($"Error opening zip file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
58 | }
59 | }
60 |
61 | private async void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
62 | {
63 | await LoadDataset(textBox1.Text);
64 | }
65 |
66 | private async Task LoadDataset(string path)
67 | {
68 | button1.IsEnabled = false;
69 | textBox1.IsEnabled = false;
70 |
71 | Window parentWindow = Window.GetWindow(this);
72 | parentWindow?.Hide();
73 |
74 | var loadingWindow = new LoadingWindow("Preparing your dataset...")
75 | {
76 | Owner = parentWindow
77 | };
78 | loadingWindow.Show();
79 |
80 | await Task.Run(() =>
81 | {
82 | try
83 | {
84 | using ZipArchive archive = ZipFile.OpenRead(path);
85 | string[] strings = [".png", ".jpg", ".webp"];
86 | var validExtensions = strings;
87 |
88 | bool isValid = archive.Entries
89 | .Where(e =>
90 | !string.IsNullOrEmpty(e.FullName) &&
91 | !string.IsNullOrEmpty(Path.GetDirectoryName(e.FullName)) &&
92 | !string.IsNullOrEmpty(Path.GetExtension(e.FullName))
93 | )
94 | .GroupBy(e => Path.GetDirectoryName(e.FullName) ?? string.Empty)
95 | .All(g => g.Any(e => validExtensions.Contains(Path.GetExtension(e.FullName) ?? string.Empty)));
96 |
97 | if (!isValid)
98 | {
99 | Dispatcher.Invoke(() =>
100 | {
101 | MessageBox.Show("The zip structure is invalid", "Dataset Structure", MessageBoxButton.OK, MessageBoxImage.Error);
102 | });
103 | return;
104 | }
105 | }
106 | catch (Exception ex)
107 | {
108 | Dispatcher.Invoke(() =>
109 | {
110 | MessageBox.Show($"Error checking zip file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
111 | return;
112 | });
113 | }
114 |
115 | if (File.Exists(path))
116 | {
117 | try
118 | {
119 | if (Directory.Exists($"projects\\{projectName}\\datasets"))
120 | {
121 | Directory.Delete($"projects\\{projectName}\\datasets", true);
122 | }
123 | Directory.CreateDirectory($"projects\\{projectName}\\datasets");
124 | string extractPath = $"projects\\{projectName}\\datasets";
125 | ZipFile.ExtractToDirectory(path, extractPath);
126 | CSharpML.ImageClassification imageClassification = new();
127 | CSharpML.ImageClassification.DataPrepare($"projects\\{projectName}\\datasets", projectName);
128 |
129 | ProcessStartInfo start = new()
130 | {
131 | FileName = $"cmd.exe",
132 | Arguments = $"/K tree projects\\{projectName}\\datasets /F /A > projects\\{projectName}\\tree.txt & exit",
133 | UseShellExecute = false,
134 | RedirectStandardOutput = true,
135 | CreateNoWindow = true
136 | };
137 |
138 | using (var process = Process.Start(start))
139 | {
140 | if (process != null)
141 | {
142 | process.WaitForExit();
143 | }
144 | }
145 | }
146 | catch (Exception ex)
147 | {
148 | Dispatcher.Invoke(() =>
149 | {
150 | MessageBox.Show($"Error loading dataset: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
151 | return;
152 | });
153 | }
154 | }
155 | else
156 | {
157 | Dispatcher.Invoke(() =>
158 | {
159 | MessageBox.Show($"File not found!", "File Error", MessageBoxButton.OK, MessageBoxImage.Error);
160 | return;
161 | });
162 | }
163 | });
164 |
165 | if (File.Exists($"projects\\{projectName}\\tree.txt"))
166 | {
167 | DocCode.Document.Blocks.Clear();
168 | DocCode.Document.Blocks.Add(new Paragraph(new Run(File.ReadAllText($"projects\\{projectName}\\tree.txt"))));
169 | }
170 |
171 | parentWindow?.Show();
172 | loadingWindow.Close();
173 |
174 | button1.IsEnabled = true;
175 | textBox1.IsEnabled = true;
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.tlog
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | *.vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | *.dsw
302 | *.dsp
303 |
304 | # Visual Studio 6 technical files
305 | *.ncb
306 | *.aps
307 |
308 | # Visual Studio LightSwitch build output
309 | **/*.HTMLClient/GeneratedArtifacts
310 | **/*.DesktopClient/GeneratedArtifacts
311 | **/*.DesktopClient/ModelManifest.xml
312 | **/*.Server/GeneratedArtifacts
313 | **/*.Server/ModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paket/paket.exe
318 | paket-files/
319 |
320 | # FAKE - F# Make
321 | .fake/
322 |
323 | # CodeRush personal settings
324 | .cr/personal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__/
328 | *.pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools/**
332 | # !tools/packages.config
333 |
334 | # Tabs Studio
335 | *.tss
336 |
337 | # Telerik's JustMock configuration file
338 | *.jmconfig
339 |
340 | # BizTalk build output
341 | *.btp.cs
342 | *.btm.cs
343 | *.odx.cs
344 | *.xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover/
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun/
351 |
352 | # MSBuild Binary and Structured Log
353 | *.binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | *.nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor/
360 |
361 | # Local History for Visual Studio
362 | .localhistory/
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory/
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup/
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide/
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode/*
381 | !.vscode/settings.json
382 | !.vscode/tasks.json
383 | !.vscode/launch.json
384 | !.vscode/extensions.json
385 | *.code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history/
389 |
390 | # Windows Installer files from build outputs
391 | *.cab
392 | *.msi
393 | *.msix
394 | *.msm
395 | *.msp
396 |
397 | # JetBrains Rider
398 | *.sln.iml
399 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2024 Lithicsoft Organization.
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/UserControls/Pages/Creator.xaml.cs:
--------------------------------------------------------------------------------
1 | // License: Apache-2.0
2 | /*
3 | * UserControls/Pages/Creator.xaml.cs: Back-end source code for projects creator
4 | *
5 | * (C) Copyright 2024 Lithicsoft Organization
6 | * Author: Bui Nguyen Tan Sang
7 | */
8 |
9 | using Lithicsoft_Trainer_Studio.Utils;
10 | using System.Collections.ObjectModel;
11 | using System.ComponentModel;
12 | using System.Diagnostics;
13 | using System.IO;
14 | using System.IO.Compression;
15 | using System.Management;
16 | using System.Net;
17 | using System.Net.Http;
18 | using System.Runtime.CompilerServices;
19 | using System.Windows;
20 | using System.Windows.Controls;
21 | using MessageBox = ModernWpf.MessageBox;
22 |
23 | namespace Lithicsoft_Trainer_Studio.UserControls.Pages
24 | {
25 | ///
26 | /// Interaction logic for Creator.xaml
27 | ///
28 | public partial class Creator : Page
29 | {
30 | public Creator()
31 | {
32 | InitializeComponent();
33 | }
34 |
35 | public event EventHandler? PageClosed;
36 |
37 | private ViewModelType? viewModelType;
38 | private ViewModel? viewModel;
39 |
40 | private static Creator? _instance;
41 | public bool isCreating = false;
42 |
43 | private void Page_Loaded(object sender, RoutedEventArgs e)
44 | {
45 | viewModel = new ViewModel();
46 | viewModelType = new ViewModelType();
47 |
48 | DataContext = this;
49 |
50 | comboBox1.DataContext = viewModel;
51 | comboBox2.DataContext = viewModelType;
52 |
53 | comboBox1.ItemsSource = viewModel.ListOfLanguages;
54 | }
55 |
56 | public static Creator Instance
57 | {
58 | get
59 | {
60 | _instance ??= new Creator();
61 | return _instance;
62 | }
63 | }
64 |
65 | private async void Button1_Click(object sender, RoutedEventArgs e)
66 | {
67 |
68 | button1.IsEnabled = false;
69 | textBox1.IsEnabled = false;
70 | comboBox1.IsEnabled = false;
71 | comboBox2.IsEnabled = false;
72 | Creator.Instance.isCreating = true;
73 |
74 | Window parentWindow = Window.GetWindow(this);
75 | parentWindow?.Hide();
76 |
77 | var loadingWindow = new LoadingWindow("Creating Project...")
78 | {
79 | Owner = parentWindow
80 | };
81 | loadingWindow.Show();
82 |
83 | await Task.Delay(1000);
84 |
85 | string ProjectName = textBox1.Text.Replace("\"", "").Replace("&", "").Replace("|", "").Replace(";", "");
86 | string? ProjectLanguage = comboBox1.SelectedItem.ToString();
87 | string? ProjectType = comboBox2.SelectedItem.ToString();
88 |
89 | await Task.Run(async () =>
90 | {
91 | try
92 | {
93 | if (ProjectName != null && ProjectLanguage != null && ProjectType != null)
94 | {
95 | Directory.CreateDirectory($"projects\\{ProjectName}");
96 | await File.WriteAllLinesAsync($"projects\\{ProjectName}\\{ProjectName}.project", [ProjectLanguage, ProjectType]);
97 | Directory.CreateDirectory($"projects\\{ProjectName}\\outputs");
98 | }
99 |
100 | if (ProjectLanguage != "CSharp")
101 | {
102 | try
103 | {
104 | if (!string.IsNullOrEmpty(ProjectName) && !string.IsNullOrEmpty(ProjectLanguage) && !string.IsNullOrEmpty(ProjectType))
105 | {
106 | await PythonSetup(ProjectName, ProjectLanguage, ProjectType);
107 | }
108 | }
109 | catch (Exception ex)
110 | {
111 | Dispatcher.Invoke(() =>
112 | {
113 | MessageBox.Show($"Error installing dependencies package: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
114 | Environment.Exit(1);
115 | });
116 | }
117 | }
118 | }
119 | catch (Exception ex)
120 | {
121 | Dispatcher.Invoke(() =>
122 | {
123 | MessageBox.Show($"Error creating project: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
124 | });
125 | }
126 | });
127 |
128 | loadingWindow.Hide();
129 | if (ProjectName != null && ProjectLanguage != null && ProjectType != null)
130 | {
131 | Trainer trainer = new(ProjectName, ProjectLanguage, ProjectType);
132 | trainer.Show();
133 | }
134 |
135 | Creator.Instance.isCreating = false;
136 | }
137 |
138 | private static async Task PythonSetup(string ProjectName, string ProjectLanguage, string ProjectType)
139 | {
140 | if (!string.IsNullOrEmpty(ProjectName) && !string.IsNullOrEmpty(ProjectLanguage) && !string.IsNullOrEmpty(ProjectType))
141 | {
142 | await InstallPackageDependencies(ProjectName, ProjectLanguage, ProjectType);
143 | }
144 | }
145 |
146 | private static bool GetCheckForDiscreteGPU()
147 | {
148 | bool discreteGPUFound = false;
149 |
150 | try
151 | {
152 | ManagementObjectSearcher searcher = new("select * from Win32_VideoController");
153 | ManagementObjectCollection moc = searcher.Get();
154 |
155 | foreach (ManagementObject mo in moc.Cast())
156 | {
157 | string? adapterCompatibility = mo["AdapterCompatibility"]?.ToString();
158 | string? description = mo["Description"]?.ToString();
159 |
160 | if (adapterCompatibility != null &&
161 | (adapterCompatibility.Contains("NVIDIA") || adapterCompatibility.Contains("AMD")))
162 | {
163 | discreteGPUFound = true;
164 | string? gpuName = mo["Name"]?.ToString();
165 | }
166 | }
167 |
168 | if (!discreteGPUFound)
169 | {
170 | MessageBox.Show("No discrete GPU found, you will train your model with CPU", "No GPU Found! Using CPU", MessageBoxButton.OK, MessageBoxImage.Warning);
171 | }
172 | }
173 | catch (Exception ex)
174 | {
175 | MessageBox.Show($"Error checking gpu: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
176 | }
177 |
178 | return discreteGPUFound;
179 |
180 | }
181 |
182 | private static async Task InstallPackageDependencies(string ProjectName, string ProjectLanguage, string ProjectType)
183 | {
184 | ArgumentNullException.ThrowIfNull(ProjectName);
185 | ArgumentNullException.ThrowIfNull(ProjectLanguage);
186 | ArgumentNullException.ThrowIfNull(ProjectType);
187 |
188 | if (!string.IsNullOrEmpty(ProjectLanguage) && !string.IsNullOrEmpty(ProjectType))
189 | {
190 | await DownloadKitFiles(ProjectName, ProjectType, GetCheckForDiscreteGPU());
191 | }
192 |
193 | try
194 | {
195 | string[] kitRequirements = File.ReadAllLines(Path.Combine(Environment.CurrentDirectory, $"projects\\{ProjectName}\\requirements.txt"));
196 |
197 | ProcessStartInfo start = new()
198 | {
199 | FileName = $"cmd.exe",
200 | Arguments = $"/K conda create -n \"{ProjectName}\" {kitRequirements[0]} -y & conda activate {ProjectName} & conda install {kitRequirements[1]} -y & python -m pip install python-dotenv & conda deactivate & pause & exit",
201 | UseShellExecute = true,
202 | RedirectStandardOutput = false
203 | };
204 |
205 | using (var process = Process.Start(start))
206 | {
207 | if (process != null)
208 | {
209 | process.WaitForExit();
210 | }
211 | }
212 | }
213 | catch (Exception ex)
214 | {
215 | MessageBox.Show($"Error installing python packages: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
216 | return;
217 | }
218 | }
219 |
220 | static async Task> LoadDataFromWebAsync(string url)
221 | {
222 | using HttpClient client = new();
223 | string data = await client.GetStringAsync(url);
224 |
225 | Dictionary result = [];
226 |
227 | string[] lines = data.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries);
228 | foreach (string line in lines)
229 | {
230 | string[] parts = line.Split([':'], 2, StringSplitOptions.TrimEntries);
231 | if (parts.Length == 2)
232 | {
233 | result[parts[0]] = parts[1];
234 | }
235 | }
236 |
237 | return result;
238 | }
239 |
240 | private static async Task FileExistsAsync(string fileUri)
241 | {
242 | using HttpClient client = new();
243 | var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, fileUri));
244 | return response.IsSuccessStatusCode;
245 | }
246 |
247 | private static async Task DownloadKitFiles(string projectPath, string projectType, bool usingGPU)
248 | {
249 | try
250 | {
251 | Dictionary pythonTrainerKit = await LoadDataFromWebAsync("https://raw.githubusercontent.com/Lithicsoft/Lithicsoft-Trainer-Studio/refs/heads/main/dictionary.txt");
252 |
253 | using HttpClient client = new();
254 |
255 | async Task DownloadFileAsync(string sourceUrl, string destinationPath)
256 | {
257 | HttpResponseMessage response = await client.GetAsync(sourceUrl);
258 | response.EnsureSuccessStatusCode();
259 |
260 | using FileStream fs = new(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None);
261 | await response.Content.CopyToAsync(fs);
262 | }
263 |
264 | var baseUri = $"https://raw.githubusercontent.com/Lithicsoft/Lithicsoft-Trainer-Studio/main/{pythonTrainerKit[projectType]}/";
265 | string requirementsFile = usingGPU ? "requirements-gpu.txt" : "requirements-cpu.txt";
266 | string projectBasePath = $"projects\\{projectPath}\\";
267 |
268 | await DownloadFileAsync(baseUri + requirementsFile, projectBasePath + "requirements.txt");
269 |
270 | string[] filesToDownload = ["trainer.py", "tester.py", "source.zip", ".env"];
271 | foreach (var file in filesToDownload)
272 | {
273 | if (!await FileExistsAsync(baseUri + file))
274 | {
275 | continue;
276 | }
277 | await DownloadFileAsync(baseUri + file, projectBasePath + file);
278 | }
279 |
280 | if (File.Exists(projectBasePath + "src.zip"))
281 | {
282 | ZipFile.ExtractToDirectory(projectBasePath + "source.zip", projectBasePath + "source");
283 | }
284 | }
285 | catch (WebException ex)
286 | {
287 | MessageBox.Show($"Error downloading file: {ex.Message}", "Exception Error", MessageBoxButton.OK, MessageBoxImage.Error);
288 | Environment.Exit(1);
289 | }
290 | }
291 |
292 | private void CheckStation()
293 | {
294 | if (comboBox1.SelectedItem == null || comboBox2.SelectedItem == null || string.IsNullOrEmpty(textBox1.Text))
295 | {
296 | button1.IsEnabled = false;
297 | }
298 | else
299 | {
300 | button1.IsEnabled = true;
301 | }
302 | }
303 |
304 | private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
305 | {
306 | CheckStation();
307 | }
308 |
309 | private void ComboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
310 | {
311 | viewModelType?.UpdateListOfTypes(comboBox1);
312 |
313 | CheckStation();
314 | }
315 |
316 | private void ComboBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
317 | {
318 | CheckStation();
319 | }
320 |
321 | public class ViewModel
322 | {
323 | public ObservableCollection ListOfLanguages { get; private set; }
324 |
325 | public ViewModel()
326 | {
327 | ListOfLanguages =
328 | [
329 | "CSharp",
330 | "Python (TensorFlow)",
331 | "Python (PyTorch)"
332 | ];
333 | }
334 | }
335 |
336 | private static async Task LoadItemsFromFileAsync(string url, ObservableCollection items)
337 | {
338 | using HttpClient client = new();
339 | string data = await client.GetStringAsync(url);
340 |
341 | string[] lines = data.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries);
342 | foreach (string line in lines)
343 | {
344 | items.Add(line);
345 | }
346 | }
347 |
348 | public class ViewModelType : INotifyPropertyChanged
349 | {
350 | private ObservableCollection? _listOfTypes;
351 | public ObservableCollection? ListOfTypes
352 | {
353 | get { return _listOfTypes; }
354 | private set
355 | {
356 | _listOfTypes = value;
357 | OnPropertyChanged();
358 | }
359 | }
360 |
361 | public ViewModelType() => ListOfTypes = [];
362 |
363 | public async void UpdateListOfTypes(ComboBox comboBox1)
364 | {
365 | ObservableCollection items = [];
366 | bool createAble = false;
367 |
368 | if (comboBox1.SelectedItem != null)
369 | {
370 | string? selectedItem = comboBox1.SelectedItem.ToString();
371 |
372 | if (selectedItem == "CSharp")
373 | {
374 | items = ["Image Classification", "Value Prediction"];
375 | createAble = true;
376 | }
377 | else if (selectedItem == "Python (TensorFlow)")
378 | {
379 | await LoadItemsFromFileAsync("https://raw.githubusercontent.com/Lithicsoft/Lithicsoft-Trainer-Studio/refs/heads/main/tensorflow.txt", items);
380 | createAble = true;
381 | }
382 | else if (selectedItem == "Python (PyTorch)")
383 | {
384 | await LoadItemsFromFileAsync("https://raw.githubusercontent.com/Lithicsoft/Lithicsoft-Trainer-Studio/refs/heads/main/pytorch.txt", items);
385 | createAble = true;
386 | }
387 | }
388 |
389 | ListOfTypes = createAble ? items : [];
390 | }
391 |
392 | public event PropertyChangedEventHandler? PropertyChanged;
393 |
394 | protected void OnPropertyChanged([CallerMemberName] string? name = null)
395 | {
396 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
397 | }
398 | }
399 | }
400 | }
401 |
--------------------------------------------------------------------------------