Add class PlateProcessor. Update Event PlateCamera_OnOneVideoFrameRequested. PlateDetector add method: ExtendPlateRect
This commit is contained in:
parent
1cd0195fe7
commit
8b2319fe81
|
@ -92,6 +92,7 @@
|
||||||
<DependentUpon>LaneOut.cs</DependentUpon>
|
<DependentUpon>LaneOut.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="PlateDetector.cs" />
|
<Compile Include="PlateDetector.cs" />
|
||||||
|
<Compile Include="PlateProcessor.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Util.cs" />
|
<Compile Include="Util.cs" />
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using OpenCvSharp;
|
using OpenCvSharp;
|
||||||
using OpenCvSharp.Extensions;
|
using OpenCvSharp.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
@ -12,18 +10,20 @@ namespace AIParkingApplication
|
||||||
{
|
{
|
||||||
private Camera overviewCamera;
|
private Camera overviewCamera;
|
||||||
private Camera plateCamera;
|
private Camera plateCamera;
|
||||||
private PlateDetector squarePlateDetector;
|
private PlateProcessor plateProcessor;
|
||||||
|
|
||||||
public LaneIn()
|
public LaneIn()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
string overviewCameraVideo = @"rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"; //@"C:\HS_test.mp4"
|
string overviewCameraVideo = @"rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"; //@"C:\HS_test.mp4"
|
||||||
string plateCameraVideo = @"C:\HS_test.mp4";
|
string plateCameraVideo = @"C:\HS_test.mp4";
|
||||||
|
//string plateCameraVideo = @"C:\CongRa_1.mp4";
|
||||||
|
|
||||||
overviewCamera = new Camera(overviewCameraVideo);
|
overviewCamera = new Camera(overviewCameraVideo);
|
||||||
plateCamera = new Camera(plateCameraVideo);
|
plateCamera = new Camera(plateCameraVideo);
|
||||||
|
|
||||||
plateCamera.OnVideoFrameReceived += PlateCameraOnVideoFrameReceived;
|
plateCamera.OnVideoFrameReceived += PlateCameraOnVideoFrameReceived;
|
||||||
plateCamera.OnOneVideoFrameRequested += PlateCamera_OnOneVideoFrameRequested; ;
|
plateCamera.OnOneVideoFrameRequested += PlateCamera_OnOneVideoFrameRequested;
|
||||||
|
|
||||||
overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived;
|
overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived;
|
||||||
overviewCamera.OnOneVideoFrameRequested += OverviewCamera_OnOneVideoFrameRequested;
|
overviewCamera.OnOneVideoFrameRequested += OverviewCamera_OnOneVideoFrameRequested;
|
||||||
|
@ -31,7 +31,7 @@ namespace AIParkingApplication
|
||||||
overviewCamera.Startcapture();
|
overviewCamera.Startcapture();
|
||||||
plateCamera.Startcapture();
|
plateCamera.Startcapture();
|
||||||
|
|
||||||
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);
|
plateProcessor = new PlateProcessor(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OverviewCamera_OnOneVideoFrameRequested(Mat videoFrame)
|
private void OverviewCamera_OnOneVideoFrameRequested(Mat videoFrame)
|
||||||
|
@ -47,38 +47,17 @@ namespace AIParkingApplication
|
||||||
{
|
{
|
||||||
Task.Factory.StartNew(new Action(async () =>
|
Task.Factory.StartNew(new Action(async () =>
|
||||||
{
|
{
|
||||||
//TODO: check size before resizing
|
var finalPlateResult = await plateProcessor.ProcessPlate(videoFrame);
|
||||||
Cv2.Resize(videoFrame, videoFrame, new OpenCvSharp.Size(1280, 720));
|
|
||||||
Mat result = squarePlateDetector.DetectPlate(videoFrame);
|
|
||||||
|
|
||||||
//TODO: check size before resizing
|
|
||||||
Cv2.Resize(result, result, new OpenCvSharp.Size(272, 272));
|
|
||||||
OcrResult ocrResult = await Util.SendEngineRequestAsync(result, PlateType.Square);
|
|
||||||
|
|
||||||
//TODO: Exception Here
|
|
||||||
Bitmap resultPlateImage;
|
|
||||||
if (!string.IsNullOrEmpty(ocrResult.Ocr) && !string.IsNullOrEmpty(ocrResult.Plate))
|
|
||||||
{
|
|
||||||
var imageData = Convert.FromBase64String(ocrResult.Plate);
|
|
||||||
using (var ms = new MemoryStream(imageData))
|
|
||||||
{
|
|
||||||
resultPlateImage = new Bitmap(ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resultPlateImage = result.ToBitmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
lblPlateString.Invoke(new Action(() =>
|
lblPlateString.Invoke(new Action(() =>
|
||||||
{
|
{
|
||||||
lblPlateString.Text = ocrResult.Ocr;
|
lblPlateString.Text = finalPlateResult.PlateString;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
pictureBoxPlateImage.Invoke(new Action(() =>
|
pictureBoxPlateImage.Invoke(new Action(() =>
|
||||||
{
|
{
|
||||||
pictureBoxPlateImage.Image?.Dispose();
|
pictureBoxPlateImage.Image?.Dispose();
|
||||||
pictureBoxPlateImage.Image = resultPlateImage;
|
pictureBoxPlateImage.Image = finalPlateResult.PlateImage;
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -103,8 +82,8 @@ namespace AIParkingApplication
|
||||||
|
|
||||||
private void CaptureAllCamera()
|
private void CaptureAllCamera()
|
||||||
{
|
{
|
||||||
this.plateCamera.RequestCaptureOneFrame();
|
plateCamera.RequestCaptureOneFrame();
|
||||||
this.overviewCamera.RequestCaptureOneFrame();
|
overviewCamera.RequestCaptureOneFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void button1_Click(object sender, EventArgs e)
|
private void button1_Click(object sender, EventArgs e)
|
||||||
|
|
|
@ -38,11 +38,31 @@ namespace AIParkingApplication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Rect ExtendPlateRect(Rect plateRect, int extendWidth = 50, int extendHeigh = 50) //TODO: 50 for plate square.
|
||||||
|
{
|
||||||
|
int newX = plateRect.X - extendWidth;
|
||||||
|
int newY = plateRect.Y - extendHeigh;
|
||||||
|
int newWidth = plateRect.Width + extendWidth * 2;
|
||||||
|
int newHeigh = plateRect.Height + extendHeigh * 2;
|
||||||
|
return new Rect(newX, newY, newWidth, newHeigh);
|
||||||
|
}
|
||||||
|
|
||||||
private Mat GetBiggestPlate(Rect[] plateRects, Mat frame)
|
private Mat GetBiggestPlate(Rect[] plateRects, Mat frame)
|
||||||
{
|
{
|
||||||
Rect biggestPlateRect = plateRects.OrderByDescending(x => x.Width).FirstOrDefault();
|
Rect biggestPlateRect = plateRects.OrderByDescending(x => x.Width).FirstOrDefault();
|
||||||
|
Console.WriteLine("===================================================");
|
||||||
|
for (int i = 0; i < plateRects.Length; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{i}\t{plateRects[i].Width}\t{plateRects[i].Height}");
|
||||||
|
}
|
||||||
Console.WriteLine($"GetBiggestPlate - Width: {biggestPlateRect.Width}\tHeight: {biggestPlateRect.Height}");
|
Console.WriteLine($"GetBiggestPlate - Width: {biggestPlateRect.Width}\tHeight: {biggestPlateRect.Height}");
|
||||||
Mat plateImage = frame[biggestPlateRect];
|
|
||||||
|
Rect extendedRect = ExtendPlateRect(biggestPlateRect);
|
||||||
|
//TODO: check oversize frame
|
||||||
|
Mat plateImage = frame[extendedRect];
|
||||||
|
//Cv2.ImShow("Old", frame[biggestPlateRect]);
|
||||||
|
//Cv2.ImShow("New", frame[extendedRect]);
|
||||||
|
//Cv2.WaitKey();
|
||||||
return plateImage;
|
return plateImage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +77,7 @@ namespace AIParkingApplication
|
||||||
{
|
{
|
||||||
public const double SCALE_FACTOR_DEFAULT_SQUARE_PLATE = 1.03;
|
public const double SCALE_FACTOR_DEFAULT_SQUARE_PLATE = 1.03;
|
||||||
public static int MIN_NEIGHBORS_DEFAULT_SQUARE_PLATE = 2;
|
public static int MIN_NEIGHBORS_DEFAULT_SQUARE_PLATE = 2;
|
||||||
public static Size MIN_SIZE_DEFAULT_SQUARE_PLATE = new Size(80, 75);
|
public static Size MIN_SIZE_DEFAULT_SQUARE_PLATE = new Size(105, 100);
|
||||||
public static Size MAX_SIZE_DEFAULT_SQUARE_PLATE = new Size(450, 400);
|
public static Size MAX_SIZE_DEFAULT_SQUARE_PLATE = new Size(450, 400);
|
||||||
|
|
||||||
public static double SCALE_FACTOR_DEFAULT_LONG_PLATE = 1.5;
|
public static double SCALE_FACTOR_DEFAULT_LONG_PLATE = 1.5;
|
||||||
|
|
101
AIParkingApplication/PlateProcessor.cs
Normal file
101
AIParkingApplication/PlateProcessor.cs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
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<FinalPlateResult> DetectPlateAndDoOcrEngineAsync(PlateType plateType, Mat frame)
|
||||||
|
{
|
||||||
|
//TODO: check size before resizing
|
||||||
|
//Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
|
||||||
|
Mat plateDetected = plateType == PlateType.Square ? squarePlateDetector.DetectPlate(frame) : longPlateDetector.DetectPlate(frame);
|
||||||
|
//Cv2.ImShow("dasdas", plateDetected);
|
||||||
|
//Cv2.WaitKey(1);
|
||||||
|
//if (plateType == PlateType.Square)
|
||||||
|
//{
|
||||||
|
// //TODO: check size before resizing
|
||||||
|
// Cv2.Resize(plateDetected, plateDetected, new OpenCvSharp.Size(272, 272));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//TODO: check size before resizing
|
||||||
|
Cv2.Resize(plateDetected, plateDetected, new OpenCvSharp.Size(272, 272));
|
||||||
|
|
||||||
|
//TODO: Check if plateDetected empty
|
||||||
|
OcrResult plateOcrResultFromEngine = await Util.SendEngineRequestAsync(plateDetected, plateType);
|
||||||
|
Bitmap finalPlateImage;
|
||||||
|
if (!string.IsNullOrEmpty(plateOcrResultFromEngine.Ocr) && !string.IsNullOrEmpty(plateOcrResultFromEngine.Plate))
|
||||||
|
{
|
||||||
|
byte[] imageData = Convert.FromBase64String(plateOcrResultFromEngine.Plate);
|
||||||
|
using (var ms = new MemoryStream(imageData))
|
||||||
|
{
|
||||||
|
finalPlateImage = new Bitmap(ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
finalPlateImage = plateDetected.ToBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FinalPlateResult
|
||||||
|
{
|
||||||
|
PlateString = plateOcrResultFromEngine.Ocr,
|
||||||
|
PlateImage = finalPlateImage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FinalPlateResult> ProcessPlate(Mat frame)
|
||||||
|
{
|
||||||
|
//TODO: check size before resizing
|
||||||
|
Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
|
||||||
|
FinalPlateResult plateResult;
|
||||||
|
|
||||||
|
if (isSupportLongPlate)
|
||||||
|
{
|
||||||
|
plateResult = await DetectPlateAndDoOcrEngineAsync(PlateType.Long, frame);
|
||||||
|
if (string.IsNullOrEmpty(plateResult.PlateString))
|
||||||
|
{
|
||||||
|
plateResult = await DetectPlateAndDoOcrEngineAsync(PlateType.Square, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Recall Square Plates");
|
||||||
|
plateResult = await DetectPlateAndDoOcrEngineAsync(PlateType.Square, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plateResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FinalPlateResult
|
||||||
|
{
|
||||||
|
public string PlateString { get; set; }
|
||||||
|
public Bitmap PlateImage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user