Skip to content

Commit a9d344a

Browse files
authored
Merge pull request #2 from sdcb/ir-queue-raw-ir
0.5.1
2 parents 15c180d + 9a21d70 commit a9d344a

29 files changed

+639
-182
lines changed

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[*.cs]
2+
3+
# xUnit1004: Test methods should not be skipped
4+
dotnet_diagnostic.xUnit1004.severity = silent

build/00-common.linq

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ static void DotNetRun(string args) => Run("dotnet", args.Dump(), Encoding.GetEnc
2121
static void Run(string exe, string args, Encoding encoding) => Util.Cmd(exe, args, encoding);
2222
static ProjectVersion[] Projects = new[]
2323
{
24-
new ProjectVersion("Sdcb.OpenVINO", "0.4.5"),
25-
new ProjectVersion("Sdcb.OpenVINO.Extensions.OpenCvSharp4", "0.1.0"),
26-
new ProjectVersion("Sdcb.OpenVINO.PaddleOCR", "0.3.1"),
24+
new ProjectVersion("Sdcb.OpenVINO", "0.5.1"),
25+
new ProjectVersion("Sdcb.OpenVINO.Extensions.OpenCvSharp4", "0.2.0"),
26+
new ProjectVersion("Sdcb.OpenVINO.PaddleOCR", "0.5.1"),
2727
new ProjectVersion("Sdcb.OpenVINO.PaddleOCR.Models.Online", "0.2"),
2828
};
2929

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR.Tests/CrashTest.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ await Task.WhenAll(Enumerable.Range(0, threadCount).Select(i => Task.Run(() =>
112112
})));
113113
}
114114

115-
[Fact(Skip = "Crash test only")]
115+
[Fact(Skip = "Crash test only"), Obsolete("QueuedPaddleOcrAll")]
116116
public async Task QueuedTest()
117117
{
118-
using Mat src = Cv2.ImRead("./samples/vsext.png");
118+
using Mat src = Cv2.ImRead("./samples/vsext.png");
119119
//using Mat src = Cv2.ImDecode(await new HttpClient().GetByteArrayAsync("https://io.starworks.cc:88/paddlesharp/ocr/samples/xdr5450.webp"), ImreadModes.Color);
120120

121121
FullOcrModel model = await OnlineFullModels.ChineseV4.DownloadAsync();
@@ -130,4 +130,18 @@ public async Task QueuedTest()
130130

131131
await Task.WhenAll(Enumerable.Range(0, 100).Select(i => queued.Run(src)));
132132
}
133+
134+
[Fact]
135+
public async Task OcrIsThreadSafe()
136+
{
137+
using Mat src = Cv2.ImRead("./samples/vsext.png");
138+
using PaddleOcrAll ocr = new(await OnlineFullModels.ChineseV4.DownloadAsync());
139+
Task[] tasks = Enumerable.Range(0, 2).Select(tidx => Task.Run(() =>
140+
{
141+
ocr.Run(src);
142+
_console.WriteLine($"tid {tidx}: Good");
143+
})).ToArray();
144+
145+
await Task.WhenAll(tasks);
146+
}
133147
}

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR.Tests/OnlineClsTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public async Task ClsCPUBatch()
3737
ClsAsserts(cls, new[] { false, true }, new[] { src, src2 });
3838
}
3939

40-
[Fact]
40+
[Fact(Skip = "GPU too slow")]
4141
public async Task ClsGpu()
4242
{
4343
using Mat src = Cv2.ImRead("./samples/5ghz.jpg");
@@ -48,7 +48,7 @@ public async Task ClsGpu()
4848
ClsAsserts(cls, true, src);
4949
}
5050

51-
[Fact]
51+
[Fact(Skip = "GPU too slow")]
5252
public async Task ClsGpuBatch()
5353
{
5454
using Mat src = Cv2.ImRead("./samples/5ghz.jpg");
@@ -59,7 +59,7 @@ public async Task ClsGpuBatch()
5959
ClsAsserts(cls, new[] { false, true }, new[] { src, src2 });
6060
}
6161

62-
[Fact]
62+
[Fact(Skip = "GPU too slow")]
6363
public async Task ClsGpuBatch10()
6464
{
6565
using Mat src = Cv2.ImRead("./samples/5ghz.jpg");

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR.Tests/OnlineModelsTest.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,34 @@ public async Task FastCheckOCR()
3939
_console.WriteLine("Detected all texts: \n" + result.Text);
4040
foreach (PaddleOcrResultRegion region in result.Regions)
4141
{
42-
_console.WriteLine($"Text: {region.Text}, Score: {region.Score}, RectCenter: {region.Rect.Center}, RectSize: {region.Rect.Size}, Angle: {region.Rect.Angle}");
42+
_console.WriteLine($"Text: {region.Text}, Score: {region.Score}, RectCenter: {region.Rect.Center}, RectSize: {region.Rect.Size}, Angle: {region.Rect.Angle}");
4343
}
4444
}
4545
}
4646
}
4747

48+
[Fact]
49+
public async Task NoRotateTest()
50+
{
51+
FullOcrModel model = await OnlineFullModels.EnglishV3.DownloadAsync();
52+
53+
byte[] sampleImageData = File.ReadAllBytes(@"./samples/vsext.png");
54+
55+
using (PaddleOcrAll all = new(model)
56+
{
57+
AllowRotateDetection = false,
58+
Enable180Classification = false,
59+
})
60+
{
61+
using (Mat src = Cv2.ImDecode(sampleImageData, ImreadModes.Color))
62+
{
63+
PaddleOcrResult result = all.Run(src);
64+
_console.WriteLine(result.Text);
65+
Assert.Contains("IDE", result.Text);
66+
}
67+
}
68+
}
69+
4870
[Fact]
4971
public async Task FastCheckOCRWith180Cls()
5072
{
@@ -76,7 +98,7 @@ public async Task FastCheckOCRWith180Cls()
7698
}
7799
}
78100

79-
[Fact]
101+
[Fact(Skip = "GPU too slow")]
80102
public async Task GPUFastCheckOCR()
81103
{
82104
FullOcrModel model = await OnlineFullModels.EnglishV3.DownloadAsync();

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR.Tests/OnlineRecTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public async Task RecCPUSmallerShape()
6060
RecAsserts(rec, src);
6161
}
6262

63-
[Fact]
63+
[Fact(Skip = "GPU too slow")]
6464
public async Task RecGpu()
6565
{
6666
using Mat src = Cv2.ImRead("./samples/5ghz.jpg");
@@ -69,7 +69,7 @@ public async Task RecGpu()
6969
RecAsserts(rec, src);
7070
}
7171

72-
[Fact]
72+
[Fact(Skip = "GPU too slow")]
7373
public async Task RecGpuLargerBatchShape()
7474
{
7575
using Mat src = Cv2.ImRead("./samples/5ghz.jpg");

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR/PaddleOcrClassifier.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Sdcb.OpenVINO.PaddleOCR;
1111
/// </summary>
1212
public class PaddleOcrClassifier : IDisposable
1313
{
14-
private readonly InferRequest _p;
14+
private readonly CompiledModel _compiledModel;
1515

1616
/// <summary>
1717
/// Rotation threshold value used to determine if the image should be rotated.
@@ -36,10 +36,11 @@ public class PaddleOcrClassifier : IDisposable
3636
/// </summary>
3737
/// <param name="model">The <see cref="ClassificationModel"/> to use.</param>
3838
/// <param name="device">The device the inference request, pass null to using model's DefaultDevice.</param>
39-
public PaddleOcrClassifier(ClassificationModel model, DeviceOptions? device = null)
39+
public PaddleOcrClassifier(ClassificationModel model,
40+
DeviceOptions? device = null)
4041
{
4142
Shape = model.Shape;
42-
_p = model.CreateInferRequest(device, prePostProcessing: (m, ppp) =>
43+
_compiledModel = model.CreateCompiledModel(device, prePostProcessing: (m, ppp) =>
4344
{
4445
using PreProcessInputInfo ppii = ppp.Inputs.Primary;
4546
ppii.TensorInfo.Layout = Layout.NHWC;
@@ -50,7 +51,7 @@ public PaddleOcrClassifier(ClassificationModel model, DeviceOptions? device = nu
5051
/// <summary>
5152
/// Releases all resources used by the <see cref="PaddleOcrClassifier"/> object.
5253
/// </summary>
53-
public void Dispose() => _p.Dispose();
54+
public void Dispose() => _compiledModel.Dispose();
5455

5556
/// <summary>
5657
/// Determines whether the image should be rotated by 180 degrees based on the threshold value.
@@ -103,23 +104,22 @@ private Ocr180DegreeClsResult[] BatchedShouldRotate180(Mat[] srcs)
103104
{
104105
using Mat final = PrepareAndStackImages(srcs);
105106

107+
using InferRequest ir = _compiledModel.CreateInferRequest();
106108
using (Tensor input = final.StackedAsTensor(srcs.Length))
107109
{
108-
_p.Inputs.Primary = input;
109-
_p.Run();
110+
ir.Inputs.Primary = input;
111+
ir.Run();
110112
}
111113

112-
using (Tensor output = _p.Outputs.Primary)
114+
using Tensor output = ir.Outputs.Primary;
115+
ReadOnlySpan<float> data = output.GetData<float>();
116+
Ocr180DegreeClsResult[] results = new Ocr180DegreeClsResult[data.Length / 2];
117+
for (int i = 0; i < results.Length; i++)
113118
{
114-
ReadOnlySpan<float> data = output.GetData<float>();
115-
Ocr180DegreeClsResult[] results = new Ocr180DegreeClsResult[data.Length / 2];
116-
for (int i = 0; i < results.Length; i++)
117-
{
118-
results[i] = new Ocr180DegreeClsResult(data[(i * 2)..((i + 1) * 2)], RotateThreshold);
119-
}
120-
121-
return results;
119+
results[i] = new Ocr180DegreeClsResult(data[(i * 2)..((i + 1) * 2)], RotateThreshold);
122120
}
121+
122+
return results;
123123
}
124124

125125
private Mat PrepareAndStackImages(Mat[] srcs)
@@ -135,7 +135,7 @@ private Mat PrepareAndStackImages(Mat[] srcs)
135135
{
136136
4 => src.CvtColor(ColorConversionCodes.RGBA2RGB),
137137
1 => src.CvtColor(ColorConversionCodes.GRAY2RGB),
138-
3 => src.WeakRef(),
138+
3 => src.FastClone(),
139139
var x => throw new Exception($"Unexpect src channel: {x}, allow: (1/3/4)")
140140
};
141141
return ResizePadding(channel3, Shape);
@@ -191,7 +191,7 @@ private static Mat ResizePadding(Mat src, NCHW shape)
191191
double whRatio = 1.0 * shape.Width / shape.Height;
192192
using Mat roi = 1.0 * srcSize.Width / srcSize.Height > whRatio ?
193193
src[0, srcSize.Height, 0, (int)Math.Floor(1.0 * srcSize.Height * whRatio)] :
194-
src.WeakRef();
194+
src.FastClone();
195195

196196
double scaleRate = 1.0 * shape.Height / srcSize.Height;
197197
Mat resized = roi.Resize(new Size(Math.Floor(roi.Width * scaleRate), shape.Height));

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR/PaddleOcrDetector.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ namespace Sdcb.OpenVINO.PaddleOCR;
1212
/// </summary>
1313
public class PaddleOcrDetector : IDisposable
1414
{
15-
/// <summary>Holds an instance of the InferRequest class.</summary>
16-
readonly InferRequest _p;
15+
readonly CompiledModel _compiledModel;
1716

1817
/// <summary>
1918
/// Gets or sets the maximum size for resizing the input image.
@@ -66,7 +65,9 @@ public class PaddleOcrDetector : IDisposable
6665
/// <para>If this property is null, network can work with image of any size and h/w ratio (dynamic).</para>
6766
/// <para>Otherwise, network works with fixed size image (static).</para>
6867
/// </param>
69-
public PaddleOcrDetector(DetectionModel model, DeviceOptions? options = null, Size? staticShapeSize = null)
68+
public PaddleOcrDetector(DetectionModel model,
69+
DeviceOptions? options = null,
70+
Size? staticShapeSize = null)
7071
{
7172
if (staticShapeSize != null)
7273
{
@@ -75,7 +76,7 @@ public PaddleOcrDetector(DetectionModel model, DeviceOptions? options = null, Si
7576
32 * Math.Ceiling(1.0 * staticShapeSize.Value.Height / 32));
7677
}
7778

78-
_p = model.CreateInferRequest(options, afterReadModel: m =>
79+
_compiledModel = model.CreateCompiledModel(options, afterReadModel: m =>
7980
{
8081
if (model.Version != ModelVersion.V4)
8182
{
@@ -104,7 +105,7 @@ public PaddleOcrDetector(DetectionModel model, DeviceOptions? options = null, Si
104105
/// </summary>
105106
public void Dispose()
106107
{
107-
_p.Dispose();
108+
_compiledModel.Dispose();
108109
}
109110

110111
/// <summary>
@@ -221,14 +222,15 @@ public unsafe Mat RunRaw(Mat src, out Size resizedSize)
221222
normalized = Normalize(padded);
222223
}
223224

225+
using InferRequest ir = _compiledModel.CreateInferRequest();
224226
using (Mat _ = normalized)
225227
using (Tensor input = normalized.AsTensor())
226228
{
227-
_p.Inputs.Primary = input;
228-
_p.Run();
229+
ir.Inputs.Primary = input;
230+
ir.Run();
229231
}
230232

231-
using (Tensor output = _p.Outputs[0])
233+
using (Tensor output = ir.Outputs[0])
232234
{
233235
Span<float> data = output.GetData<float>();
234236
NCHW shape = output.Shape.ToNCHW();
@@ -263,23 +265,23 @@ private static float GetScore(Point[] contour, Mat pred)
263265

264266
private static Mat MatResize(Mat src, int? maxSize)
265267
{
266-
if (maxSize == null) return src.WeakRef();
268+
if (maxSize == null) return src.FastClone();
267269

268270
Size size = src.Size();
269271
int longEdge = Math.Max(size.Width, size.Height);
270272
double scaleRate = 1.0 * maxSize.Value / longEdge;
271273

272274
return scaleRate < 1.0 ?
273275
src.Resize(Size.Zero, scaleRate, scaleRate) :
274-
src.WeakRef();
276+
src.FastClone();
275277
}
276278

277279
private static Mat MatResize(Mat src, Size maxSize)
278280
{
279281
Size srcSize = src.Size();
280282
if (srcSize == maxSize)
281283
{
282-
return src.WeakRef();
284+
return src.FastClone();
283285
}
284286

285287
double scale = Math.Min(maxSize.Width / (double)srcSize.Width, maxSize.Height / (double)srcSize.Height);
@@ -289,7 +291,7 @@ private static Mat MatResize(Mat src, Size maxSize)
289291

290292
if (scale == 1)
291293
{
292-
return src.WeakRef();
294+
return src.FastClone();
293295
}
294296
else
295297
{

projects/PaddleOCR/Sdcb.OpenVINO.PaddleOCR/PaddleOcrRecognizer.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
using OpenCvSharp;
2-
using Sdcb.OpenVINO.Natives;
32
using Sdcb.OpenVINO.Extensions.OpenCvSharp4;
43
using Sdcb.OpenVINO.PaddleOCR.Models;
54
using System;
65
using System.Linq;
7-
using System.Runtime.InteropServices;
86
using System.Text;
97

108
namespace Sdcb.OpenVINO.PaddleOCR;
@@ -14,7 +12,7 @@ namespace Sdcb.OpenVINO.PaddleOCR;
1412
/// </summary>
1513
public class PaddleOcrRecognizer : IDisposable
1614
{
17-
private readonly InferRequest _p;
15+
private readonly CompiledModel _compiledModel;
1816

1917
/// <summary>
2018
/// Recognization model being used for OCR.
@@ -53,12 +51,14 @@ public class PaddleOcrRecognizer : IDisposable
5351
/// The value will be rounded to the nearest upper multiple of 32. This parameter is useful for models that require a fixed shape input.
5452
/// Pass `null` if the model supports dynamic input shape.
5553
/// </param>
56-
public PaddleOcrRecognizer(RecognizationModel model, DeviceOptions? deviceOptions = null, int? staticShapeWidth = null)
54+
public PaddleOcrRecognizer(RecognizationModel model,
55+
DeviceOptions? deviceOptions = null,
56+
int? staticShapeWidth = null)
5757
{
5858
Model = model;
5959
StaticShapeWidth = staticShapeWidth.HasValue ? (int)(32 * Math.Ceiling(1.0 * staticShapeWidth.Value / 32)) : null;
6060

61-
_p = model.CreateInferRequest(deviceOptions, prePostProcessing: (m, ppp) =>
61+
_compiledModel = model.CreateCompiledModel(deviceOptions, prePostProcessing: (m, ppp) =>
6262
{
6363
using PreProcessInputInfo ppii = ppp.Inputs.Primary;
6464
ppii.TensorInfo.Layout = Layout.NHWC;
@@ -75,7 +75,7 @@ public PaddleOcrRecognizer(RecognizationModel model, DeviceOptions? deviceOption
7575
/// <summary>
7676
/// Releases all resources used by the current instance of the <see cref="PaddleOcrRecognizer"/> class.
7777
/// </summary>
78-
public void Dispose() => _p.Dispose();
78+
public void Dispose() => _compiledModel.Dispose();
7979

8080
/// <summary>
8181
/// Run OCR recognition on multiple images in batches.
@@ -136,14 +136,14 @@ private unsafe PaddleOcrRecognizerResult[] BatchedRun(Mat[] srcs)
136136
}));
137137

138138
using Mat final = PrepareAndStackImages(srcs, modelHeight, maxWidth);
139-
139+
using InferRequest ir = _compiledModel.CreateInferRequest();
140140
using (Tensor input = final.StackedAsTensor(srcs.Length))
141141
{
142-
_p.Inputs.Primary = input;
143-
_p.Run();
142+
ir.Inputs.Primary = input;
143+
ir.Run();
144144
}
145-
146-
using (Tensor output = _p.Outputs.Primary)
145+
146+
using (Tensor output = ir.Outputs.Primary)
147147
{
148148
IntPtr dataPtr = output.DangerousGetDataPtr();
149149
int dataLength = (int)output.Size;
@@ -218,7 +218,7 @@ private static unsafe Mat PrepareAndStackImages(Mat[] srcs, int modelHeight, int
218218
{
219219
4 => src.CvtColor(ColorConversionCodes.RGBA2RGB),
220220
1 => src.CvtColor(ColorConversionCodes.GRAY2RGB),
221-
3 => src.WeakRef(),
221+
3 => src.FastClone(),
222222
var x => throw new Exception($"Unexpect src channel: {x}, allow: (1/3/4)")
223223
};
224224
return ResizePadding(channel3, modelHeight, maxWidth);

0 commit comments

Comments
 (0)