-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathUtils.cs
executable file
·155 lines (137 loc) · 7.28 KB
/
Utils.cs
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using Microsoft.ML.OnnxRuntime.Tensors;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing;
namespace YOLO.Extentions
{
public static class Utils
{
public static Bitmap ResizeImage(Image image, int target_width, int target_height)
{
Bitmap output = new(target_width, target_height, image.PixelFormat);
var (w, h) = ((float)image.Width, (float)image.Height); // image width and height
var (xRatio, yRatio) = (target_width / w, target_height / h); // x, y ratios
float ratio = Math.Min(xRatio, yRatio); // ratio = resized / original
var (width, height) = ((int)(w * ratio), (int)(h * ratio)); // roi width and height
var (x, y) = ((int)((target_width * 0.5f) - (width * 0.5f)), (int)((target_height * 0.5f) - (height * 0.5f))); // roi x and y coordinates
using Graphics graphics = Graphics.FromImage(output);
graphics.Clear(Color.FromArgb(0, 0, 0, 0)); // clear canvas
graphics.SmoothingMode = SmoothingMode.None; // no smoothing
graphics.InterpolationMode = InterpolationMode.NearestNeighbor; // nn interpolation
graphics.PixelOffsetMode = PixelOffsetMode.Half; // half pixel offset
graphics.DrawImage(image, new Rectangle(x, y, width, height)); // draw scaled
return output;
}
//https://github.com/ivilson/Yolov7net/issues/17
public static Tensor<float> ExtractPixels2(Bitmap bitmap)
{
int pixelCount = bitmap.Width * bitmap.Height;
Rectangle rectangle = new(0, 0, bitmap.Width, bitmap.Height);
DenseTensor<float> tensor = new(new[] { 1, 3, bitmap.Height, bitmap.Width });
Span<byte> data;
BitmapData bitmapData;
if (bitmap.PixelFormat == PixelFormat.Format24bppRgb && bitmap.Width % 4 == 0)
{
bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
unsafe
{
data = new Span<byte>((void*)bitmapData.Scan0, bitmapData.Height * bitmapData.Stride);
}
ExtractPixelsRgb(tensor, data, pixelCount);
}
else
{
// force convert to 32 bit PArgb
bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
unsafe
{
data = new Span<byte>((void*)bitmapData.Scan0, bitmapData.Height * bitmapData.Stride);
}
ExtractPixelsArgb(tensor, data, pixelCount);
}
bitmap.UnlockBits(bitmapData);
return tensor;
}
public static void ExtractPixelsArgb(DenseTensor<float> tensor, Span<byte> data, int pixelCount)
{
Span<float> spanR = tensor.Buffer.Span;
Span<float> spanG = spanR[pixelCount..];
Span<float> spanB = spanG[pixelCount..];
int sidx = 0;
for (int i = 0; i < pixelCount; i++)
{
spanR[i] = data[sidx + 2] * 0.0039215686274509803921568627451f;
spanG[i] = data[sidx + 1] * 0.0039215686274509803921568627451f;
spanB[i] = data[sidx] * 0.0039215686274509803921568627451f;
sidx += 4;
}
}
public static void ExtractPixelsRgb(DenseTensor<float> tensor, Span<byte> data, int pixelCount)
{
Span<float> spanR = tensor.Buffer.Span;
Span<float> spanG = spanR[pixelCount..];
Span<float> spanB = spanG[pixelCount..];
int sidx = 0;
for (int i = 0; i < pixelCount; i++)
{
spanR[i] = data[sidx + 2] * 0.0039215686274509803921568627451f;
spanG[i] = data[sidx + 1] * 0.0039215686274509803921568627451f;
spanB[i] = data[sidx] * 0.0039215686274509803921568627451f;
sidx += 3;
}
}
public static float Clamp(float value, float min, float max)
{
return value < min ? min : value > max ? max : value;
}
public static Image DrawBoundingBox(Image image, List<YoloPrediction> predictions, int bounding_box_thickness, int font_size)
{
using Graphics graphics = Graphics.FromImage(image);
for (int i = 0; i < predictions.Count; i++)
{
float score = (float)Math.Round(predictions[i].Score, 2);
graphics.DrawRectangles(new(predictions[i].Label.Color, bounding_box_thickness), new[] { predictions[i].Rectangle });
graphics.DrawString($"{predictions[i].Label.Name} ({score})",
new("Consolas", font_size, GraphicsUnit.Pixel), new SolidBrush(predictions[i].Label.Color),
new PointF(predictions[i].Rectangle.X, predictions[i].Rectangle.Y));
}
return image;
}
public static Image DrawRotatedBoundingBox(Image image, List<OBBPrediction> predictions, int bounding_box_thickness, int font_size)
{
using Graphics graphics = Graphics.FromImage(image);
for (int i = 0; i < predictions.Count; i++)
{
float score = (float)Math.Round(predictions[i].Score, 2);
graphics.DrawPolygon(new(predictions[i].Label.Color, bounding_box_thickness), GetRotatedPoints(predictions[i]));
graphics.DrawString($"{predictions[i].Label.Name} ({score})",
new("Consolas", font_size, GraphicsUnit.Pixel), new SolidBrush(predictions[i].Label.Color),
new PointF(predictions[i].Rectangle.X, predictions[i].Rectangle.Y));
}
return image;
}
public static PointF[] GetRotatedPoints(OBBPrediction prediction)
{
PointF[] points = new PointF[]
{
new(prediction.Rectangle.X, prediction.Rectangle.Y),
new(prediction.Rectangle.X + prediction.Rectangle.Width, prediction.Rectangle.Y),
new(prediction.Rectangle.X + prediction.Rectangle.Width, prediction.Rectangle.Y + prediction.Rectangle.Height),
new(prediction.Rectangle.X, prediction.Rectangle.Y + prediction.Rectangle.Height)
};
OpenCvSharp.Point2f middle = new(prediction.Rectangle.X + prediction.Rectangle.Width * .5f,
prediction.Rectangle.Y + prediction.Rectangle.Height * .5f);
float cos_angle = (float)Math.Cos(prediction.Angle);
float sin_angle = (float)Math.Sin(prediction.Angle);
for (int i = 0; i < 4; i++)
{
float offset_x = middle.X - points[i].X;
float offset_y = middle.Y - points[i].Y;
float rotated_x = offset_x * cos_angle - offset_y * sin_angle;
float rotated_y = offset_x * sin_angle + offset_y * cos_angle;
points[i] = new(middle.X + rotated_x, middle.Y + rotated_y);
}
return points;
}
}
}