1- using OpenCvSharp ;
1+ using OpenCvSharp ;
22using Sdcb . PaddleOCR . Models ;
33using Sdcb . PaddleOCR . Models . Local ;
4+ using Sdcb . PaddleOCR . Models . Online ;
5+ using System . Diagnostics ;
46using System . Runtime . InteropServices ;
57using Xunit ;
68using Xunit . Abstractions ;
79
810namespace Sdcb . PaddleOCR . Tests ;
911
10- public class OfflineModelsTest ( ITestOutputHelper console )
12+ public class ModelsTest ( ITestOutputHelper console )
1113{
1214 [ Fact ]
1315 public void FastCheckOCREnglishV3 ( )
@@ -136,4 +138,120 @@ public async Task QueuedOCR()
136138 }
137139 }
138140 }
141+
142+ [ Fact ]
143+ public async Task FastCheckOCR ( )
144+ {
145+ // EnglishV3 is not working in macos-arm64, so we use ChineseV5 instead: https://github.com/PaddlePaddle/Paddle/issues/72413
146+ // ----------------------
147+ // Error Message Summary:
148+ // ----------------------
149+ // NotFoundError: No allocator found for the place, Place(undefined:0)
150+ // [Hint: Expected iter != allocators.end(), but received iter == allocators.end().] (at /Users/runner/work/PaddleSharp/PaddleSharp/paddle-src/paddle/phi/core/memory/allocation/allocator_facade.cc:381)
151+ // [operator < matmul > error]
152+ // The active test run was aborted. Reason: Test host process crashed
153+ FullOcrModel model = await ( OnlineFullModels . ChineseV5 with { ClsModel = null } ) . DownloadAsync ( ) ;
154+
155+ // from: https://visualstudio.microsoft.com/wp-content/uploads/2021/11/Home-page-extension-visual-updated.png
156+ byte [ ] sampleImageData = File . ReadAllBytes ( @"./samples/vsext.png" ) ;
157+
158+ using ( PaddleOcrAll all = new ( model )
159+ {
160+ AllowRotateDetection = true ,
161+ Enable180Classification = false ,
162+ } )
163+ {
164+ // Load local file by following code:
165+ // using (Mat src2 = Cv2.ImRead(@"C:\test.jpg"))
166+ using ( Mat src = Cv2 . ImDecode ( sampleImageData , ImreadModes . Color ) )
167+ {
168+ Stopwatch sw = Stopwatch . StartNew ( ) ;
169+ PaddleOcrResult result = all . Run ( src ) ;
170+ console . WriteLine ( $ "lapsed={ sw . ElapsedMilliseconds } ms") ;
171+ console . WriteLine ( "Detected all texts: \n " + result . Text ) ;
172+ foreach ( PaddleOcrResultRegion region in result . Regions )
173+ {
174+ console . WriteLine ( $ "Text: { region . Text } , Score: { region . Score } , RectCenter: { region . Rect . Center } , RectSize: { region . Rect . Size } , Angle: { region . Rect . Angle } ") ;
175+ }
176+ }
177+ }
178+ }
179+
180+ [ Fact ]
181+ public async Task V4DetOnly ( )
182+ {
183+ DetectionModel detModel = await OnlineDetectionModel . ChineseV4 . DownloadAsync ( ) ;
184+
185+ using ( Mat src = Cv2 . ImRead ( @"./samples/5ghz.jpg" ) )
186+ using ( PaddleOcrDetector r = new ( detModel ) )
187+ {
188+ Stopwatch sw = Stopwatch . StartNew ( ) ;
189+ RotatedRect [ ] rects = r . Run ( src ) ;
190+ console . WriteLine ( $ "elapsed={ sw . ElapsedMilliseconds } ms") ;
191+ console . WriteLine ( $ "Detected { rects . Length } rects.") ;
192+ }
193+ }
194+
195+ [ Fact ]
196+ public async Task V4RecOnly ( )
197+ {
198+ RecognizationModel recModel = await LocalDictOnlineRecognizationModel . ChineseV4 . DownloadAsync ( ) ;
199+
200+ using ( Mat src = Cv2 . ImRead ( @"./samples/5ghz.jpg" ) )
201+ using ( PaddleOcrRecognizer r = new ( recModel ) )
202+ {
203+ Stopwatch sw = Stopwatch . StartNew ( ) ;
204+ PaddleOcrRecognizerResult result = r . Run ( src ) ;
205+ console . WriteLine ( $ "elapsed={ sw . ElapsedMilliseconds } ms") ;
206+ console . WriteLine ( result . ToString ( ) ) ;
207+ Assert . True ( result . Score > 0.9 ) ;
208+ }
209+ }
210+
211+ [ Fact ]
212+ public void SingleCharRecognitionTest ( )
213+ {
214+ console . WriteLine (
215+ $ "Running SingleChar test on { RuntimeInformation . OSDescription } ({ RuntimeInformation . OSArchitecture } )") ;
216+
217+ FullOcrModel model = LocalFullModels . ChineseV5 ;
218+ byte [ ] sampleImageData = File . ReadAllBytes ( @"./samples/vsext.png" ) ;
219+
220+ using PaddleOcrAll all = new ( model )
221+ {
222+ AllowRotateDetection = true ,
223+ Enable180Classification = false ,
224+ } ;
225+
226+ using Mat src = Cv2 . ImDecode ( sampleImageData , ImreadModes . Color ) ;
227+ PaddleOcrResult result = all . Run ( src ) ;
228+ console . WriteLine ( "Detected all texts: \n " + result . Text ) ;
229+
230+ Assert . NotEmpty ( result . Regions ) ;
231+
232+ foreach ( PaddleOcrResultRegion region in result . Regions )
233+ {
234+ console . WriteLine ( $ "Text: { region . Text } , Score: { region . Score } ") ;
235+ console . WriteLine ( $ "OcrRecognizerResultSingleChars count: { region . OcrRecognizerResultSingleChars . Count } ") ;
236+
237+ // Verify single characters exist
238+ Assert . NotEmpty ( region . OcrRecognizerResultSingleChars ) ;
239+
240+ // Verify indices are properly set and sequential
241+ for ( int i = 0 ; i < region . OcrRecognizerResultSingleChars . Count ; i ++ )
242+ {
243+ OcrRecognizerResultSingleChar singleChar = region . OcrRecognizerResultSingleChars [ i ] ;
244+ Assert . Equal ( i , singleChar . Index ) ;
245+ Assert . NotNull ( singleChar . Character ) ;
246+ Assert . True ( singleChar . Score > 0 , $ "Character '{ singleChar . Character } ' should have a positive score") ;
247+
248+ console . WriteLine (
249+ $ " Char[{ singleChar . Index } ]: '{ singleChar . Character } ', Score: { singleChar . Score : F3} ") ;
250+ }
251+
252+ // Verify the concatenated single characters match the full text
253+ string reconstructedText = string . Join ( "" , region . OcrRecognizerResultSingleChars . Select ( c => c . Character ) ) ;
254+ Assert . Equal ( region . Text , reconstructedText ) ;
255+ }
256+ }
139257}
0 commit comments