using OpenCvSharp; using OpenCvSharp.Extensions; using System; using System.Drawing; using System.IO; using System.Threading.Tasks; namespace AIParkingApplication { public class PlateProcessor { private bool isSupportSquarePlate; private bool isSupportLongPlate; private PlateDetector squarePlateDetector; private PlateDetector longPlateDetector; public PlateProcessor(bool isSupportSquarePlate = true, bool isSupportLongPlate = false) { this.isSupportSquarePlate = isSupportSquarePlate; this.isSupportLongPlate = isSupportLongPlate; if (this.isSupportSquarePlate) { squarePlateDetector = new PlateDetector(PlateType.Square, PlateDetectorConstant.MIN_SIZE_DEFAULT_SQUARE_PLATE, PlateDetectorConstant.MAX_SIZE_DEFAULT_SQUARE_PLATE, PlateDetectorConstant.SCALE_FACTOR_DEFAULT_SQUARE_PLATE, PlateDetectorConstant.MIN_NEIGHBORS_DEFAULT_SQUARE_PLATE); } if (this.isSupportLongPlate) { longPlateDetector = new PlateDetector(PlateType.Long, PlateDetectorConstant.MIN_SIZE_DEFAULT_LONG_PLATE, PlateDetectorConstant.MAX_SIZE_DEFAULT_LONG_PLATE, PlateDetectorConstant.SCALE_FACTOR_DEFAULT_LONG_PLATE, PlateDetectorConstant.MIN_NEIGHBORS_DEFAULT_LONG_PLATE); } } private async Task DetectPlateAndDoOcrEngineAsync(PlateType plateType, Mat frame) { Mat plateDetected = plateType == PlateType.Square ? squarePlateDetector.DetectPlate(frame) : longPlateDetector.DetectPlate(frame); //TODO: Check if plateDetected empty OcrResult plateOcrResultFromEngine = await Util.SendEngineRequestAsync(plateDetected, plateType); Mat finalPlateImage; if (!string.IsNullOrEmpty(plateOcrResultFromEngine.PlateString) && !string.IsNullOrEmpty(plateOcrResultFromEngine.PlateImageBase64)) { byte[] imageData = Convert.FromBase64String(plateOcrResultFromEngine.PlateImageBase64); using (var ms = new MemoryStream(imageData)) { Bitmap image = new Bitmap(ms); finalPlateImage = BitmapConverter.ToMat(image); } } else { finalPlateImage = plateDetected; } return new FinalPlateResult { PlateString = plateOcrResultFromEngine.PlateString, PlateImage = finalPlateImage, PlateType = plateType }; } public async Task ProcessPlate(Mat frame) { try { FinalPlateResult plateResult; if (isSupportLongPlate) { plateResult = await DetectPlateAndDoOcrEngineAsync(PlateType.Long, frame); if (!IsPlateStringValid(plateResult.PlateString)) { plateResult = await DetectPlateAndDoOcrEngineAsync(PlateType.Square, frame); } } else { Console.WriteLine("Recall Square Plates"); plateResult = await DetectPlateAndDoOcrEngineAsync(PlateType.Square, frame); } return plateResult; } catch (Exception ex) { Console.WriteLine($"{Util.GetCurrentMethodName()}\texMessage: {ex.Message}"); return new FinalPlateResult { PlateString = string.Empty, PlateImage = frame, PlateType = PlateType.Square }; } } //TODO: Complete this private string NormalizePlateString(string plateString) { return plateString; } public bool IsPlateStringValid(string plateString, int minPlateStringLength = 5) { bool isValid = !string.IsNullOrEmpty(plateString) && plateString.Length > minPlateStringLength; return isValid; } } public class FinalPlateResult { public string PlateString { get; set; } public Mat PlateImage { get; set; } public PlateType PlateType { get; set; } } }