Skip to content

Commit 5c2985d

Browse files
authored
add C# or NOT sample (#3)
1 parent 8008e43 commit 5c2985d

15 files changed

+728
-9
lines changed

CSharpOrNot/App.xaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Application xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
x:Class="Gradient.Samples.App">
4+
<Application.Styles>
5+
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
6+
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
7+
</Application.Styles>
8+
</Application>

CSharpOrNot/App.xaml.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Gradient.Samples {
2+
using Avalonia;
3+
using Avalonia.Markup.Xaml;
4+
5+
public class App : Application {
6+
public override void Initialize() {
7+
AvaloniaXamlLoader.Load(this);
8+
}
9+
}
10+
}

CSharpOrNot/BitmapTools.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
namespace Gradient.Samples {
2+
using System;
3+
using System.Drawing;
4+
using System.Drawing.Imaging;
5+
using System.Runtime.InteropServices;
6+
7+
static class BitmapTools {
8+
public static void ToBitmap(byte[] brightness, Bitmap target) {
9+
if (target.PixelFormat != PixelFormat.Format8bppIndexed)
10+
throw new NotSupportedException("The only supported pixel format is " + PixelFormat.Format8bppIndexed);
11+
12+
var bitmapData = target.LockBits(new Rectangle(new Point(), target.Size),
13+
ImageLockMode.WriteOnly,
14+
PixelFormat.Format8bppIndexed);
15+
16+
try {
17+
Marshal.Copy(source: brightness,
18+
startIndex: 0, length: bitmapData.Width * bitmapData.Height,
19+
destination: bitmapData.Scan0);
20+
} finally {
21+
target.UnlockBits(bitmapData);
22+
}
23+
}
24+
25+
// default .NET upscaling tries to interpolate, which we avoid here
26+
public static void Upscale(Bitmap source, Bitmap target) {
27+
if (target.Width % source.Width != 0 || target.Height % source.Height != 0)
28+
throw new ArgumentException();
29+
30+
int scaleY = target.Height / source.Height;
31+
int scaleX = target.Width / source.Width;
32+
33+
var sourceData = source.LockBits(new Rectangle(new Point(), source.Size),
34+
ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
35+
try {
36+
var targetData = target.LockBits(new Rectangle(new Point(), target.Size),
37+
ImageLockMode.WriteOnly,
38+
PixelFormat.Format8bppIndexed);
39+
40+
try {
41+
for (int sourceY = 0; sourceY < sourceData.Height; sourceY++)
42+
for (int sourceX = 0; sourceX < sourceData.Width; sourceX++) {
43+
byte brightness = Marshal.ReadByte(sourceData.Scan0,
44+
sourceY * sourceData.Width + sourceX);
45+
for (int targetY = sourceY * scaleY;
46+
targetY < (sourceY + 1) * scaleY;
47+
targetY++)
48+
for (int targetX = sourceX * scaleX;
49+
targetX < (sourceX + 1) * scaleX;
50+
targetX++)
51+
Marshal.WriteByte(targetData.Scan0,
52+
targetY * targetData.Width + targetX,
53+
brightness);
54+
}
55+
} finally {
56+
target.UnlockBits(targetData);
57+
}
58+
} finally {
59+
source.UnlockBits(sourceData);
60+
}
61+
}
62+
63+
public static void SetGreyscalePalette(Bitmap bitmap) {
64+
ColorPalette pal = bitmap.Palette;
65+
66+
for (int i = 0; i < 256; i++) {
67+
pal.Entries[i] = Color.FromArgb(255, i, i, i);
68+
}
69+
70+
bitmap.Palette = pal;
71+
}
72+
}
73+
}

CSharpOrNot/CSharpOrNot.cs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
namespace Gradient.Samples {
2+
using System;
3+
using System.Drawing;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
using numpy;
8+
using tensorflow;
9+
using tensorflow.keras;
10+
using tensorflow.keras.layers;
11+
12+
static class CSharpOrNot
13+
{
14+
public static Model CreateModel(int classCount) {
15+
var activation = tf.keras.activations.elu_fn;
16+
const int filterCount = 8;
17+
int[] resNetFilters = { filterCount, filterCount, filterCount };
18+
return new Sequential(new Layer[] {
19+
new Dropout(rate: 0.05),
20+
Conv2D.NewDyn(filters: filterCount, kernel_size: 5, padding: "same"),
21+
Activation.NewDyn(activation),
22+
new MaxPool2D(pool_size: 2),
23+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
24+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
25+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
26+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
27+
new MaxPool2D(),
28+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
29+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
30+
new MaxPool2D(),
31+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
32+
new ResNetBlock(kernelSize: 3, filters: resNetFilters, activation: activation),
33+
new AvgPool2D(pool_size: 2),
34+
new Flatten(),
35+
new Dense(units: classCount, activation: tf.nn.softmax_fn),
36+
});
37+
}
38+
39+
public const int Width = 64, Height = 64;
40+
public static readonly Size Size = new Size(Width, Height);
41+
// being opinionated here
42+
const string Tab = " ";
43+
const char Whitespace = '\u00FF';
44+
public static readonly string[] IncludeExtensions = {
45+
".cs",
46+
".py",
47+
".h",
48+
".cc",
49+
".c",
50+
".tcl",
51+
".java",
52+
".sh",
53+
};
54+
55+
public static ndarray<float> GreyscaleImageBytesToNumPy(byte[] inputs, int imageCount, int width, int height)
56+
=> (dynamic)inputs.Select(b => (float)b).ToArray().NumPyCopy()
57+
.reshape(new[] { imageCount, height, width, 1 }) / 255.0f;
58+
59+
public static string[] ReadCode(string filePath)
60+
=> File.ReadAllLines(filePath)
61+
.Select(line => line.Replace("\t", Tab))
62+
.Select(line => {
63+
var result = new StringBuilder(line.Length);
64+
// replace non-ASCII characters with underscore
65+
// also make all whitespace stand out
66+
foreach (char c in line) {
67+
result.Append(
68+
c <= 32 ? Whitespace
69+
: c >= 255 ? '_'
70+
: c);
71+
}
72+
return result.ToString();
73+
})
74+
.ToArray();
75+
76+
/// <summary>
77+
/// Copies a rectangular block of text into a byte array
78+
/// </summary>
79+
public static void RenderTextBlockToGreyscaleBytes(string[] lines,
80+
Point startingPoint, Size size,
81+
byte[] destination)
82+
{
83+
if (size.IsEmpty) throw new ArgumentException();
84+
if (destination.Length < size.Width * size.Height) throw new ArgumentException();
85+
if (startingPoint.Y == lines.Length) {
86+
Array.Fill(destination, (byte)Whitespace);
87+
return;
88+
}
89+
90+
for (int y = 0; y < size.Height; y++) {
91+
int sourceY = y + startingPoint.Y;
92+
int destOffset = y * size.Width;
93+
if (sourceY >= lines.Length) {
94+
Array.Fill(destination, (byte)255,
95+
startIndex: destOffset,
96+
count: size.Width*size.Height - destOffset);
97+
return;
98+
}
99+
100+
for (int x = 0; x < size.Width; x++) {
101+
int sourceX = x + startingPoint.X;
102+
if (sourceX >= lines[sourceY].Length) {
103+
Array.Fill(destination, (byte)255,
104+
startIndex: destOffset,
105+
count: size.Width - x);
106+
break;
107+
}
108+
109+
destination[destOffset] = (byte)lines[sourceY][sourceX];
110+
destOffset++;
111+
}
112+
}
113+
}
114+
}
115+
}

CSharpOrNot/CSharpOrNot.csproj

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
5+
<ApplicationIcon />
6+
<StartupObject />
7+
<RootNamespace>Gradient.Samples</RootNamespace>
8+
</PropertyGroup>
9+
<ItemGroup>
10+
<Compile Update="**\*.xaml.cs">
11+
<DependentUpon>%(Filename)</DependentUpon>
12+
</Compile>
13+
<AvaloniaResource Include="**\*.xaml">
14+
<SubType>Designer</SubType>
15+
</AvaloniaResource>
16+
</ItemGroup>
17+
<ItemGroup>
18+
<PackageReference Include="Avalonia" Version="0.8.0" />
19+
<PackageReference Include="Avalonia.Desktop" Version="0.8.0" />
20+
<PackageReference Include="ManyConsole.CommandLineUtils" Version="1.0.3-alpha" />
21+
<PackageReference Include="morelinq" Version="3.2.0" />
22+
</ItemGroup>
23+
<ItemGroup>
24+
<ProjectReference Include="..\ResNetBlock\ResNetBlock.csproj" />
25+
</ItemGroup>
26+
</Project>

CSharpOrNot/CSharpOrNotProgram.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace Gradient.Samples {
2+
using System;
3+
using System.Linq;
4+
using Avalonia;
5+
using Avalonia.Logging.Serilog;
6+
using Gradient;
7+
using ManyConsole.CommandLineUtils;
8+
using tensorflow;
9+
using tensorflow.core.protobuf.config_pb2;
10+
11+
static class CSharpOrNotProgram {
12+
public static int Main(string[] args) {
13+
GradientSetup.OptInToUsageDataCollection();
14+
GradientSetup.UseEnvironmentFromVariable();
15+
16+
dynamic config = config_pb2.ConfigProto();
17+
config.gpu_options.allow_growth = true;
18+
tf.keras.backend.set_session(Session.NewDyn(config: config));
19+
20+
return ConsoleCommandDispatcher.DispatchCommand(
21+
ConsoleCommandDispatcher.FindCommandsInSameAssemblyAs(typeof(CSharpOrNotProgram)),
22+
args, Console.Out);
23+
}
24+
25+
// Avalonia configuration, don't remove; also used by visual designer.
26+
public static AppBuilder BuildAvaloniaApp()
27+
=> AppBuilder.Configure<App>()
28+
.UsePlatformDetect()
29+
.LogToDebug();
30+
}
31+
}

CSharpOrNot/CSharpOrNotWindow.xaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Window xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
6+
x:Class="Gradient.Samples.CSharpOrNotWindow"
7+
Title="CSharpOrNot">
8+
<Grid RowDefinitions="Auto,*,Auto">
9+
<TextBlock Name="Language" FontSize="24" HorizontalAlignment="Center"/>
10+
<Grid ColumnDefinitions="3*,2*,2*" Grid.Row="1">
11+
<TextBox Name="CodeDisplay"
12+
FontFamily="Consolas,Monospace"
13+
AcceptsReturn="True"/>
14+
<Image Name="CodeImage" Grid.Column="1" Stretch="Uniform"/>
15+
<TextBlock Name="CodeWindow" Grid.Column="2"
16+
FontFamily="Consolas,Monospace"/>
17+
</Grid>
18+
<Button Name="OpenFileButton" Grid.Row="2" Click="OpenFileClick">Open File</Button>
19+
</Grid>
20+
</Window>

0 commit comments

Comments
 (0)