Skip to content

Commit bd57389

Browse files
committed
simple WinForms app, that demonstrates detection (horribly slow)
1 parent 60d30bb commit bd57389

File tree

10 files changed

+370
-38
lines changed

10 files changed

+370
-38
lines changed

YOLOv4.sln

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,42 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YOLOv4", "src\YOLOv4.csproj
1818
EndProject
1919
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YOLOv4.Tests", "test\YOLOv4.Tests.csproj", "{241AC79D-0399-4B2A-9C01-07C609F74B69}"
2020
EndProject
21-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainV4", "samples\TrainV4\TrainV4.csproj", "{5299523B-B225-4A47-8C58-66D58B3547D2}"
21+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TrainV4", "samples\TrainV4\TrainV4.csproj", "{5299523B-B225-4A47-8C58-66D58B3547D2}"
22+
EndProject
23+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{4AA5CFE0-5A26-45D9-9748-FB3F89EDE83A}"
24+
EndProject
25+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DetectUI", "samples\DetectUI\DetectUI.csproj", "{D695A271-2BBA-4737-81E2-6A9BE0A8290E}"
2226
EndProject
2327
Global
2428
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2529
Debug|Any CPU = Debug|Any CPU
26-
Debug|x64 = Debug|x64
27-
Debug|x86 = Debug|x86
2830
Release|Any CPU = Release|Any CPU
29-
Release|x64 = Release|x64
30-
Release|x86 = Release|x86
3131
EndGlobalSection
3232
GlobalSection(ProjectConfigurationPlatforms) = postSolution
3333
{04BE1707-4235-44E6-AB58-48621D5160D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
3434
{04BE1707-4235-44E6-AB58-48621D5160D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
35-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Debug|x64.ActiveCfg = Debug|Any CPU
36-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Debug|x64.Build.0 = Debug|Any CPU
37-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Debug|x86.ActiveCfg = Debug|Any CPU
38-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Debug|x86.Build.0 = Debug|Any CPU
3935
{04BE1707-4235-44E6-AB58-48621D5160D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
4036
{04BE1707-4235-44E6-AB58-48621D5160D3}.Release|Any CPU.Build.0 = Release|Any CPU
41-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Release|x64.ActiveCfg = Release|Any CPU
42-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Release|x64.Build.0 = Release|Any CPU
43-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Release|x86.ActiveCfg = Release|Any CPU
44-
{04BE1707-4235-44E6-AB58-48621D5160D3}.Release|x86.Build.0 = Release|Any CPU
4537
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4638
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
47-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Debug|x64.ActiveCfg = Debug|Any CPU
48-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Debug|x64.Build.0 = Debug|Any CPU
49-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Debug|x86.ActiveCfg = Debug|Any CPU
50-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Debug|x86.Build.0 = Debug|Any CPU
5139
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Release|Any CPU.ActiveCfg = Release|Any CPU
5240
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Release|Any CPU.Build.0 = Release|Any CPU
53-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Release|x64.ActiveCfg = Release|Any CPU
54-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Release|x64.Build.0 = Release|Any CPU
55-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Release|x86.ActiveCfg = Release|Any CPU
56-
{241AC79D-0399-4B2A-9C01-07C609F74B69}.Release|x86.Build.0 = Release|Any CPU
5741
{5299523B-B225-4A47-8C58-66D58B3547D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5842
{5299523B-B225-4A47-8C58-66D58B3547D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
59-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Debug|x64.ActiveCfg = Debug|Any CPU
60-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Debug|x64.Build.0 = Debug|Any CPU
61-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Debug|x86.ActiveCfg = Debug|Any CPU
62-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Debug|x86.Build.0 = Debug|Any CPU
6343
{5299523B-B225-4A47-8C58-66D58B3547D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
6444
{5299523B-B225-4A47-8C58-66D58B3547D2}.Release|Any CPU.Build.0 = Release|Any CPU
65-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Release|x64.ActiveCfg = Release|Any CPU
66-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Release|x64.Build.0 = Release|Any CPU
67-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Release|x86.ActiveCfg = Release|Any CPU
68-
{5299523B-B225-4A47-8C58-66D58B3547D2}.Release|x86.Build.0 = Release|Any CPU
45+
{D695A271-2BBA-4737-81E2-6A9BE0A8290E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46+
{D695A271-2BBA-4737-81E2-6A9BE0A8290E}.Debug|Any CPU.Build.0 = Debug|Any CPU
47+
{D695A271-2BBA-4737-81E2-6A9BE0A8290E}.Release|Any CPU.ActiveCfg = Release|Any CPU
48+
{D695A271-2BBA-4737-81E2-6A9BE0A8290E}.Release|Any CPU.Build.0 = Release|Any CPU
6949
EndGlobalSection
7050
GlobalSection(SolutionProperties) = preSolution
7151
HideSolutionNode = FALSE
7252
EndGlobalSection
53+
GlobalSection(NestedProjects) = preSolution
54+
{5299523B-B225-4A47-8C58-66D58B3547D2} = {4AA5CFE0-5A26-45D9-9748-FB3F89EDE83A}
55+
{D695A271-2BBA-4737-81E2-6A9BE0A8290E} = {4AA5CFE0-5A26-45D9-9748-FB3F89EDE83A}
56+
EndGlobalSection
7357
GlobalSection(ExtensibilityGlobals) = postSolution
7458
SolutionGuid = {4D804A23-81D4-4FE4-9ADE-1110371610D4}
7559
EndGlobalSection

YOLOv4.sln.DotSettings

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Yolo/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

samples/DetectUI/DetectUI.csproj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
7+
<UseWindowsForms>true</UseWindowsForms>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\..\src\YOLOv4.csproj" />
16+
</ItemGroup>
17+
18+
</Project>

samples/DetectUI/Program.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using System.Threading.Tasks;
6+
using System.Windows.Forms;
7+
8+
namespace DetectUI {
9+
static class Program {
10+
/// <summary>
11+
/// The main entry point for the application.
12+
/// </summary>
13+
[STAThread]
14+
static void Main() {
15+
Application.SetHighDpiMode(HighDpiMode.SystemAware);
16+
Application.EnableVisualStyles();
17+
Application.SetCompatibleTextRenderingDefault(false);
18+
Application.Run(new YoloForm());
19+
}
20+
}
21+
}

samples/DetectUI/YoloForm.Designer.cs

Lines changed: 94 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/DetectUI/YoloForm.cs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
namespace DetectUI {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Data;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Windows.Forms;
8+
9+
using LostTech.Gradient;
10+
using LostTech.Gradient.Exceptions;
11+
using LostTech.TensorFlow;
12+
13+
using SixLabors.Fonts;
14+
using SixLabors.ImageSharp;
15+
using SixLabors.ImageSharp.Drawing;
16+
using SixLabors.ImageSharp.Drawing.Processing;
17+
using SixLabors.ImageSharp.PixelFormats;
18+
using SixLabors.ImageSharp.Processing;
19+
20+
using tensorflow;
21+
using tensorflow.core.protobuf.config_pb2;
22+
using tensorflow.datasets.ObjectDetection;
23+
using tensorflow.keras;
24+
using tensorflow.keras.applications;
25+
using tensorflow.keras.layers;
26+
using tensorflow.keras.models;
27+
28+
public partial class YoloForm : Form {
29+
Model model;
30+
// dynamic infer;
31+
bool loaded;
32+
public YoloForm() {
33+
this.InitializeComponent();
34+
35+
this.openPicDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
36+
37+
GradientEngine.UseEnvironmentFromVariable();
38+
TensorFlowSetup.Instance.EnsureInitialized();
39+
40+
// TODO: remove this after replacing tf.sigmoid in PostProcessBBBox
41+
tf.enable_eager_execution();
42+
tf.enable_v2_behavior();
43+
44+
dynamic config = config_pb2.ConfigProto.CreateInstance();
45+
config.gpu_options.allow_growth = true;
46+
tf.keras.backend.set_session(Session.NewDyn(config: config));
47+
}
48+
49+
private void openPic_Click(object sender, EventArgs e) {
50+
if (this.openPicDialog.ShowDialog(this) != DialogResult.OK)
51+
return;
52+
53+
using var image = Image.Load<Rgb24>(this.openPicDialog.FileName);
54+
55+
// TODO: use non-raw model. Raw is extremely slow
56+
ObjectDetectionResult[] detections = YOLO.DetectRaw(this.model,
57+
supportedSize: new Size(MS_COCO.InputSize, MS_COCO.InputSize),
58+
image: image);
59+
60+
image.Mutate(context => {
61+
var font = SystemFonts.CreateFont("Arial", 16);
62+
var textColor = Color.White;
63+
var boxPen = new Pen(Color.White, width: 4);
64+
foreach(var detection in detections) {
65+
string className = detection.Class < MS_COCO.ClassCount && detection.Class >= 0
66+
? MS_COCO.ClassNames[detection.Class] : "imaginary class";
67+
string text = $"{className}: {detection.Score:P0}";
68+
var box = Scale(detection.Box, image.Size());
69+
context.DrawText(text, font, textColor, TopLeft(box));
70+
var drawingBox = new RectangularPolygon(box);
71+
context.Draw(boxPen, drawingBox);
72+
}
73+
});
74+
75+
using var temp = new MemoryStream();
76+
image.SaveAsBmp(temp);
77+
temp.Position = 0;
78+
79+
this.pictureBox.Image = new System.Drawing.Bitmap(temp);
80+
81+
this.Text = string.Join(", ", detections.Select(d => MS_COCO.ClassNames[d.Class]));
82+
}
83+
84+
static PointF TopLeft(RectangleF rect) => new PointF(rect.Left, rect.Top);
85+
static RectangleF Scale(RectangleF rect, SizeF size)
86+
=> new RectangleF(x: rect.Left * size.Width, width: rect.Width * size.Width,
87+
y: rect.Top * size.Height, height: rect.Height * size.Height);
88+
89+
void LoadWeights() {
90+
while (!this.loaded) {
91+
string modelPath = Environment.GetEnvironmentVariable("DETECT_UI_WEIGHTS");
92+
if (modelPath is null) {
93+
if (this.openWeightsDirDialog.ShowDialog(this) != DialogResult.OK)
94+
continue;
95+
96+
modelPath = this.openWeightsDirDialog.SelectedPath;
97+
}
98+
99+
try {
100+
this.model = YOLO.CreateRaw(inputSize: MS_COCO.InputSize, classCount: MS_COCO.ClassCount);
101+
this.model.summary();
102+
this.model.load_weights(modelPath);
103+
//this.model = tf.saved_model.load_v2(modelDir, tags: tf.saved_model.SERVING);
104+
//this.infer = this.model.signatures["serving_default"];
105+
} catch (ValueError e) {
106+
this.Text = e.Message;
107+
continue;
108+
}
109+
this.loaded = true;
110+
this.Text = "YOLO " + modelPath;
111+
}
112+
113+
this.openPic.Enabled = true;
114+
}
115+
116+
private void YoloForm_Load(object sender, EventArgs e) {
117+
this.LoadWeights();
118+
}
119+
}
120+
}

samples/DetectUI/YoloForm.resx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<root>
2+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
3+
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
4+
<xsd:element name="root" msdata:IsDataSet="true">
5+
<xsd:complexType>
6+
<xsd:choice maxOccurs="unbounded">
7+
<xsd:element name="metadata">
8+
<xsd:complexType>
9+
<xsd:sequence>
10+
<xsd:element name="value" type="xsd:string" minOccurs="0" />
11+
</xsd:sequence>
12+
<xsd:attribute name="name" use="required" type="xsd:string" />
13+
<xsd:attribute name="type" type="xsd:string" />
14+
<xsd:attribute name="mimetype" type="xsd:string" />
15+
<xsd:attribute ref="xml:space" />
16+
</xsd:complexType>
17+
</xsd:element>
18+
<xsd:element name="assembly">
19+
<xsd:complexType>
20+
<xsd:attribute name="alias" type="xsd:string" />
21+
<xsd:attribute name="name" type="xsd:string" />
22+
</xsd:complexType>
23+
</xsd:element>
24+
<xsd:element name="data">
25+
<xsd:complexType>
26+
<xsd:sequence>
27+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
28+
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
29+
</xsd:sequence>
30+
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
31+
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
32+
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
33+
<xsd:attribute ref="xml:space" />
34+
</xsd:complexType>
35+
</xsd:element>
36+
<xsd:element name="resheader">
37+
<xsd:complexType>
38+
<xsd:sequence>
39+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
40+
</xsd:sequence>
41+
<xsd:attribute name="name" type="xsd:string" use="required" />
42+
</xsd:complexType>
43+
</xsd:element>
44+
</xsd:choice>
45+
</xsd:complexType>
46+
</xsd:element>
47+
</xsd:schema>
48+
<resheader name="resmimetype">
49+
<value>text/microsoft-resx</value>
50+
</resheader>
51+
<resheader name="version">
52+
<value>2.0</value>
53+
</resheader>
54+
<resheader name="reader">
55+
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
56+
</resheader>
57+
<resheader name="writer">
58+
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
59+
</resheader>
60+
</root>

0 commit comments

Comments
 (0)