diff --git a/AIParkingApplication/AIParkingApplicationForm.Designer.cs b/AIParkingApplication/AIParkingApplicationForm.Designer.cs index 97f44be..5b3fa77 100644 --- a/AIParkingApplication/AIParkingApplicationForm.Designer.cs +++ b/AIParkingApplication/AIParkingApplicationForm.Designer.cs @@ -34,7 +34,7 @@ // // btnStopLaneIn // - this.btnStopLaneIn.Location = new System.Drawing.Point(840, 205); + this.btnStopLaneIn.Location = new System.Drawing.Point(1221, 88); this.btnStopLaneIn.Name = "btnStopLaneIn"; this.btnStopLaneIn.Size = new System.Drawing.Size(75, 23); this.btnStopLaneIn.TabIndex = 0; @@ -44,7 +44,7 @@ // // btnStartLaneIn // - this.btnStartLaneIn.Location = new System.Drawing.Point(840, 246); + this.btnStartLaneIn.Location = new System.Drawing.Point(1221, 129); this.btnStartLaneIn.Name = "btnStartLaneIn"; this.btnStartLaneIn.Size = new System.Drawing.Size(75, 23); this.btnStartLaneIn.TabIndex = 0; diff --git a/AIParkingApplication/AIParkingApplicationForm.cs b/AIParkingApplication/AIParkingApplicationForm.cs index 2519911..028dd99 100644 --- a/AIParkingApplication/AIParkingApplicationForm.cs +++ b/AIParkingApplication/AIParkingApplicationForm.cs @@ -8,6 +8,7 @@ namespace AIParkingApplication private ApiController apiController; private IDoorControlAccess c3Device; private LaneIn laneIn; + private LaneOut laneOut; public AIParkingApplicationForm() { @@ -17,23 +18,22 @@ namespace AIParkingApplication c3Device = new C3DeviceController("192.168.1.200"); laneIn = new LaneIn(1, @"C:\HS_test.mp4", @"C:\HS_test.mp4", c3Device, apiController, true, false, true); Controls.Add(laneIn); - //laneOut.Location = new System.Drawing.Point(550, 0); - //Controls.Add(laneOut); - //LaneIn laneIn1 = new LaneIn(@"C:\HS_test.mp4", @"C:\HS_test.mp4", c3Device, true, false, false); - //laneIn1.Location = new System.Drawing.Point(550, 0); - //Controls.Add(laneIn1); - //laneIn1.Start(); + laneOut = new LaneOut(2, @"C:\HS_test.mp4", @"C:\HS_test.mp4", c3Device, apiController, true, false, true); + laneOut.Location = new System.Drawing.Point(450, 0); + Controls.Add(laneOut); } private void btnStopLaneIn_Click(object sender, System.EventArgs e) { laneIn.Stop(); + laneOut.Stop(); } private void btnStartLaneIn_Click(object sender, System.EventArgs e) { laneIn.Start(); + laneOut.Start(); } } } diff --git a/AIParkingApplication/LaneOut.cs b/AIParkingApplication/LaneOut.cs index 3a1ae95..240d23e 100644 --- a/AIParkingApplication/LaneOut.cs +++ b/AIParkingApplication/LaneOut.cs @@ -1,12 +1,214 @@ -using System.Windows.Forms; +using OpenCvSharp; +using OpenCvSharp.Extensions; +using System; +using System.Drawing; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; namespace AIParkingApplication { - public partial class LaneOut : UserControl + public partial class LaneOut : UserControl, ILane { - public LaneOut() + private Camera overviewCamera; + private Camera plateCamera; + private PlateProcessor plateProcessor; + private int doorId; + private bool isSupportSquarePlate; + private bool isSupportLongPlate; + private bool isAutoOpenDoor; + private bool isRetryMode; + private IDoorControlAccess doorControlAccess; + private ApiController apiController; + + public LaneOut(int doorId, + string plateStream, + string overviewStream, + IDoorControlAccess doorControlAccess, + ApiController apiController, + bool isSupportSquarePlate = true, + bool isSupportLongPlate = false, + bool isAutoOpenDoor = true, + bool isRetryMode = false) { InitializeComponent(); + this.doorId = doorId; + + this.isSupportSquarePlate = isSupportSquarePlate; + this.isSupportLongPlate = isSupportLongPlate; + this.isAutoOpenDoor = isAutoOpenDoor; + this.isRetryMode = isRetryMode; + overviewCamera = new Camera(overviewStream); + plateCamera = new Camera(plateStream); + this.apiController = apiController; + this.doorControlAccess = doorControlAccess; + this.doorControlAccess.OnNewCardReceived += C3Device_OnNewCardReceived; + + plateCamera.OnVideoFrameReceived += PlateCameraOnVideoFrameReceived; + plateCamera.OnOpenVideoStreamFailed += PlateCamera_OnOpenVideoStreamFailed; + + overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived; + overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed; + + plateProcessor = new PlateProcessor(this.isSupportSquarePlate, this.isSupportLongPlate); + } + + private async void C3Device_OnNewCardReceived(int doorId, string cardNumber) + { + ClearPlateAndOverviewImage(); + var cardInfoResult = await apiController.GetCardInformation(cardNumber); + if (!cardInfoResult.IsValid) + { + lblStatusInfo.UpdateLabel("THẺ KHÔNG HỢP LỆ", Color.Purple); + return; + } + + if (cardInfoResult.Direction != "in") + { + lblStatusInfo.UpdateLabel("THẺ ĐÃ ĐƯỢC SỬ DỤNG", Color.Red); + return; + } + + plateCamera.RequestCaptureOneFrame(); + overviewCamera.RequestCaptureOneFrame(); + await Task.Delay(200); + + var plateVideoFrame = plateCamera.CurrentFrame; + FinalPlateResult result = await ProcessFrameImage(plateProcessor, plateVideoFrame, isRetryMode); + pictureBoxPlateImage.UpdateImage(result.PlateImage.ToBitmap()); + + var overviewVideoFrame = overviewCamera.CurrentFrame; + pictureBoxOverviewImage.UpdateImage(overviewVideoFrame.ToBitmap()); + + var cardInformation = await apiController.GetCardInformation(cardNumber); + ShowCardInfoOnUI(cardNumber, result.PlateString, cardInformation.CardType, DateTime.Now.ToString(AppConstant.DATETIME_FORMAT)); + + var saveLogResult = await apiController.SaveLog(LaneDirection.In, cardInformation.CardRealID.ToString(), "1", result.PlateType, DateTime.Now.ToString(AppConstant.DATETIME_FORMAT), result.PlateString, result.PlateImage, result.PlateImage, result.PlateImage, overviewVideoFrame); + if (saveLogResult.Status) + { + if (isAutoOpenDoor && this.doorId == doorId) + { + OpenDoor(doorId); + } + } + else + { + lblStatusInfo.UpdateLabel("KHÔNG CÓ KẾT NỐI ĐẾN MÁY CHỦ", Color.Red); + } + } + + private void PlateCamera_OnOpenVideoStreamFailed(Mat videoFrame) + { + pictureBoxPlateVideo.UpdateImage(videoFrame.ToBitmap()); + } + + private void OverviewCamera_OnOpenVideoStreamFailed(Mat videoFrame) + { + pictureBoxOverviewVideo.UpdateImage(videoFrame.ToBitmap()); + } + + private void ClearPlateAndOverviewImage() + { + pictureBoxPlateImage.UpdateImage(null); + pictureBoxOverviewImage.UpdateImage(null); + } + + private void OpenDoor(int doorId) + { + if (doorControlAccess.OpenDoor(doorId).HasError) + { + lblStatusInfo.UpdateLabel("KHÔNG THỂ MỞ CỬA", Color.Red); + } + } + + private async Task ProcessFrameImage(PlateProcessor plateProcessor, Mat frame, bool isRetryMode) + { + try + { + Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720)); + FinalPlateResult finalPlateResult = await plateProcessor.ProcessPlate(frame); + + if (isRetryMode && !plateProcessor.IsPlateStringValid(finalPlateResult.PlateString)) + { + Console.WriteLine("ProcessFrameImage Retry Mode"); + Thread.Sleep(1000); + overviewCamera.RequestCaptureOneFrame(); + finalPlateResult = await plateProcessor.ProcessPlate(frame); + } + return finalPlateResult; + } + catch (Exception ex) + { + Console.WriteLine($"ProcessFrameImage\texMessage: {ex.Message}"); + return new FinalPlateResult + { + PlateImage = frame, + PlateString = string.Empty, + PlateType = PlateType.Square + }; + } + } + + public void Stop() + { + plateCamera.Stop(); + overviewCamera.Stop(); + } + + public void Start() + { + plateCamera.Start(); + overviewCamera.Start(); + } + + private void ShowCardInfoOnUI(string cardNumber, string plateString, string cardType, string cardTime) + { + lblCardNumber.UpdateLabel($"Số thẻ: {cardNumber}"); + lblPlateString.UpdateLabel($"Biển số: {plateString}"); + lblCardType.UpdateLabel($"Loại thẻ: {cardType}"); + lblCardTime.UpdateLabel($"Thời gian: {cardTime}"); + lblStatusInfo.UpdateLabel(string.IsNullOrEmpty(plateString) ? "KHÔNG NHẬN DIỆN ĐƯỢC BIỂN SỐ" : $"MỜI XE {plateString} VÀO", string.IsNullOrEmpty(plateString) ? Color.Red : Color.Green); + } + + private void OverviewCameraOnVideoFrameReceived(Mat videoFrame) + { + try + { + pictureBoxOverviewVideo.UpdateImage(videoFrame.ToBitmap()); + } + catch (Exception ex) + { + Console.WriteLine($"{Util.GetCurrentMethodName()}\texMessage: {ex.Message}"); + } + } + + private void PlateCameraOnVideoFrameReceived(Mat videoFrame) + { + try + { + pictureBoxPlateVideo.UpdateImage(videoFrame.ToBitmap()); + } + catch (Exception ex) + { + Console.WriteLine($"{Util.GetCurrentMethodName()}\texMessage: {ex.Message}"); + } + } + + private void ConnectToDoorAccessControl() + { + if (!this.doorControlAccess.Connect().HasError) + { + _ = this.doorControlAccess.GetLogToReceiveNewCard(); + } + else + { + lblStatusInfo.UpdateLabel("KHÔNG THỂ KẾT NỐI TỚI C3200", Color.Purple); + } + } + + private void LaneIn_Load(object sender, EventArgs e) + { + ConnectToDoorAccessControl(); } } }