Compare commits

...

8 Commits

12 changed files with 120 additions and 65 deletions

View File

@ -117,6 +117,7 @@
<Compile Include="AppConstant.cs" /> <Compile Include="AppConstant.cs" />
<Compile Include="C3DeviceController.cs" /> <Compile Include="C3DeviceController.cs" />
<Compile Include="Camera.cs" /> <Compile Include="Camera.cs" />
<Compile Include="EngineApiController.cs" />
<Compile Include="Enums.cs" /> <Compile Include="Enums.cs" />
<Compile Include="IDoorControlAccess.cs" /> <Compile Include="IDoorControlAccess.cs" />
<Compile Include="ILane.cs" /> <Compile Include="ILane.cs" />

View File

@ -12,24 +12,36 @@ namespace AIParkingApplication
private LaneOut laneOut; private LaneOut laneOut;
private StatusBar statusBar; private StatusBar statusBar;
private Sidebar sidebar; private Sidebar sidebar;
private Config configOnWeb;
public AIParkingApplicationForm() public AIParkingApplicationForm(ApiController apiController, Config configOnWeb)
{ {
InitializeComponent(); InitializeComponent();
string serverBaseAddress = "http://localhost:80/"; this.apiController = apiController;
apiController = new ApiController(serverBaseAddress); this.configOnWeb = configOnWeb;
sidebar = new Sidebar(apiController); sidebar = new Sidebar(apiController);
sidebar.Location = new System.Drawing.Point(0, 0); sidebar.Location = new System.Drawing.Point(0, 0);
Controls.Add(sidebar); Controls.Add(sidebar);
c3Device = new C3DeviceController("192.168.1.200"); c3Device = new C3DeviceController("192.168.1.200");
laneIn = new LaneIn(1, @"C:\HS_test.mp4", @"C:\HS_test.mp4", c3Device, apiController, true, false, true); EngineApiController engineApiController = null;
try
{
engineApiController = new EngineApiController($"http://{this.configOnWeb.APIPath.ApiPlateRecognize.IP}:{this.configOnWeb.APIPath.ApiPlateRecognize.Port}");
}
catch (Exception)
{
MessageBox.Show("Cấu hình API Plate Recognize lỗi!", "Cấu hình API Engine lỗi!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
laneIn = new LaneIn(1, this.configOnWeb.CameraData1.StreamUrl, this.configOnWeb.CameraData2.StreamUrl, c3Device, this.apiController, engineApiController, true, false, true);
laneIn.BorderStyle = BorderStyle.FixedSingle; laneIn.BorderStyle = BorderStyle.FixedSingle;
laneIn.Location = new System.Drawing.Point(sidebar.Location.X + sidebar.Width + 20, 0); laneIn.Location = new System.Drawing.Point(sidebar.Location.X + sidebar.Width + 20, 0);
Controls.Add(laneIn); Controls.Add(laneIn);
laneOut = new LaneOut(2, @"C:\HS_test.mp4", @"C:\HS_test.mp4", c3Device, apiController, true, false, true); laneOut = new LaneOut(2, this.configOnWeb.CameraData3.StreamUrl, this.configOnWeb.CameraData4.StreamUrl, c3Device, this.apiController, engineApiController, true, false, true);
laneOut.BorderStyle = BorderStyle.FixedSingle; laneOut.BorderStyle = BorderStyle.FixedSingle;
laneOut.Location = new System.Drawing.Point(laneIn.Location.X + laneIn.Width + 20, 0); laneOut.Location = new System.Drawing.Point(laneIn.Location.X + laneIn.Width + 20, 0);
Controls.Add(laneOut); Controls.Add(laneOut);

View File

@ -359,7 +359,7 @@ namespace AIParkingApplication
public string Type { get; set; } public string Type { get; set; }
[JsonProperty("stream_url")] [JsonProperty("stream_url")]
public string Stream_url { get; set; } public string StreamUrl { get; set; }
[JsonProperty("minWidth")] [JsonProperty("minWidth")]
public double MinWidth { get; set; } public double MinWidth { get; set; }

View File

@ -9,5 +9,6 @@
#endregion #endregion
public const string CAMERA_FAILED_IMAGE_PATH = @"Images\CantConnectCamera.jpg"; public const string CAMERA_FAILED_IMAGE_PATH = @"Images\CantConnectCamera.jpg";
public const string DEFAULT_LOGO_IMAGE = @".\Images\ApplicationLogo.ico";
} }
} }

View File

@ -0,0 +1,40 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using OpenCvSharp;
namespace AIParkingApplication
{
public class EngineApiController
{
private HttpClient httpClientEngine;
public EngineApiController(string engineBaseAddress)
{
httpClientEngine = new HttpClient { BaseAddress = new Uri(engineBaseAddress), Timeout = TimeSpan.FromMilliseconds(5000) };
}
public async Task<OcrResult> SendEngineRequestAsync(Mat plateImage, PlateType plateType)
{
string plateImageBase64 = Convert.ToBase64String(plateImage.ToBytes());
try
{
var request = new PlateRequestEngineModel
{
Img64 = plateImageBase64,
Mode = plateType == PlateType.Square ? "square" : "long",
Display = "full"
};
HttpResponseMessage response = await httpClientEngine.PostAsJsonAsync("/get-from-frame", request);
response.EnsureSuccessStatusCode();
var ocrResult = await response.Content.ReadAsAsync<OcrResult>();
return ocrResult;
}
catch (Exception ex)
{
Console.WriteLine($"SendEngineRequest : {ex.Message}");
return new OcrResult();
}
}
}
}

View File

@ -26,6 +26,7 @@ namespace AIParkingApplication
string overviewStream, string overviewStream,
IDoorControlAccess doorControlAccess, IDoorControlAccess doorControlAccess,
ApiController apiController, ApiController apiController,
EngineApiController engineApiController,
bool isSupportSquarePlate = true, bool isSupportSquarePlate = true,
bool isSupportLongPlate = false, bool isSupportLongPlate = false,
bool isAutoOpenDoor = true, bool isAutoOpenDoor = true,
@ -33,7 +34,6 @@ namespace AIParkingApplication
{ {
InitializeComponent(); InitializeComponent();
this.doorId = doorId; this.doorId = doorId;
this.isSupportSquarePlate = isSupportSquarePlate; this.isSupportSquarePlate = isSupportSquarePlate;
this.isSupportLongPlate = isSupportLongPlate; this.isSupportLongPlate = isSupportLongPlate;
this.isAutoOpenDoor = isAutoOpenDoor; this.isAutoOpenDoor = isAutoOpenDoor;
@ -50,7 +50,7 @@ namespace AIParkingApplication
overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived; overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived;
overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed; overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed;
plateProcessor = new PlateProcessor(this.isSupportSquarePlate, this.isSupportLongPlate); plateProcessor = new PlateProcessor(engineApiController, this.isSupportSquarePlate, this.isSupportLongPlate);
} }
private async void C3Device_OnNewCardReceived(int doorId, string cardNumber) private async void C3Device_OnNewCardReceived(int doorId, string cardNumber)

View File

@ -26,6 +26,7 @@ namespace AIParkingApplication
string overviewStream, string overviewStream,
IDoorControlAccess doorControlAccess, IDoorControlAccess doorControlAccess,
ApiController apiController, ApiController apiController,
EngineApiController engineApiController,
bool isSupportSquarePlate = true, bool isSupportSquarePlate = true,
bool isSupportLongPlate = false, bool isSupportLongPlate = false,
bool isAutoOpenDoor = true, bool isAutoOpenDoor = true,
@ -33,7 +34,6 @@ namespace AIParkingApplication
{ {
InitializeComponent(); InitializeComponent();
this.doorId = doorId; this.doorId = doorId;
this.isSupportSquarePlate = isSupportSquarePlate; this.isSupportSquarePlate = isSupportSquarePlate;
this.isSupportLongPlate = isSupportLongPlate; this.isSupportLongPlate = isSupportLongPlate;
this.isAutoOpenDoor = isAutoOpenDoor; this.isAutoOpenDoor = isAutoOpenDoor;
@ -50,7 +50,7 @@ namespace AIParkingApplication
overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived; overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived;
overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed; overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed;
plateProcessor = new PlateProcessor(this.isSupportSquarePlate, this.isSupportLongPlate); plateProcessor = new PlateProcessor(engineApiController, this.isSupportSquarePlate, this.isSupportLongPlate);
} }
private async void C3Device_OnNewCardReceived(int doorId, string cardNumber) private async void C3Device_OnNewCardReceived(int doorId, string cardNumber)
@ -203,7 +203,7 @@ namespace AIParkingApplication
} }
else else
{ {
lblStatusInfo.UpdateLabel($"MỜI XE {plateStringEngine} QUA", Color.Red); lblStatusInfo.UpdateLabel($"MỜI XE {plateStringEngine} QUA", Color.Green);
} }
} }
} }

View File

@ -34,8 +34,8 @@
this.lblUsername = new System.Windows.Forms.Label(); this.lblUsername = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox(); this.txtPassword = new System.Windows.Forms.TextBox();
this.lblPassword = new System.Windows.Forms.Label(); this.lblPassword = new System.Windows.Forms.Label();
this.lblServerAddress = new System.Windows.Forms.TextBox(); this.txtServerAddress = new System.Windows.Forms.TextBox();
this.lblServerIP = new System.Windows.Forms.Label(); this.lblServerAddress = new System.Windows.Forms.Label();
this.btnLogin = new System.Windows.Forms.Button(); this.btnLogin = new System.Windows.Forms.Button();
this.btnExit = new System.Windows.Forms.Button(); this.btnExit = new System.Windows.Forms.Button();
this.lblLoginStatus = new System.Windows.Forms.Label(); this.lblLoginStatus = new System.Windows.Forms.Label();
@ -44,7 +44,6 @@
// //
// pictureBoxImageLogo // pictureBoxImageLogo
// //
this.pictureBoxImageLogo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pictureBoxImageLogo.Location = new System.Drawing.Point(12, 14); this.pictureBoxImageLogo.Location = new System.Drawing.Point(12, 14);
this.pictureBoxImageLogo.Name = "pictureBoxImageLogo"; this.pictureBoxImageLogo.Name = "pictureBoxImageLogo";
this.pictureBoxImageLogo.Size = new System.Drawing.Size(185, 185); this.pictureBoxImageLogo.Size = new System.Drawing.Size(185, 185);
@ -87,22 +86,22 @@
this.lblPassword.TabIndex = 2; this.lblPassword.TabIndex = 2;
this.lblPassword.Text = "Mật khẩu"; this.lblPassword.Text = "Mật khẩu";
// //
// txtServerAddress
//
this.txtServerAddress.Location = new System.Drawing.Point(294, 90);
this.txtServerAddress.Name = "txtServerAddress";
this.txtServerAddress.Size = new System.Drawing.Size(227, 20);
this.txtServerAddress.TabIndex = 1;
this.txtServerAddress.Text = "http://localhost:80/";
//
// lblServerAddress // lblServerAddress
// //
this.lblServerAddress.Location = new System.Drawing.Point(294, 90); this.lblServerAddress.AutoSize = true;
this.lblServerAddress.Location = new System.Drawing.Point(214, 93);
this.lblServerAddress.Name = "lblServerAddress"; this.lblServerAddress.Name = "lblServerAddress";
this.lblServerAddress.Size = new System.Drawing.Size(227, 20); this.lblServerAddress.Size = new System.Drawing.Size(48, 13);
this.lblServerAddress.TabIndex = 1; this.lblServerAddress.TabIndex = 2;
this.lblServerAddress.Text = "localhost"; this.lblServerAddress.Text = "Máy chủ";
//
// lblServerIP
//
this.lblServerIP.AutoSize = true;
this.lblServerIP.Location = new System.Drawing.Point(214, 93);
this.lblServerIP.Name = "lblServerIP";
this.lblServerIP.Size = new System.Drawing.Size(48, 13);
this.lblServerIP.TabIndex = 2;
this.lblServerIP.Text = "Máy chủ";
// //
// btnLogin // btnLogin
// //
@ -141,10 +140,10 @@
this.Controls.Add(this.lblLoginStatus); this.Controls.Add(this.lblLoginStatus);
this.Controls.Add(this.btnExit); this.Controls.Add(this.btnExit);
this.Controls.Add(this.btnLogin); this.Controls.Add(this.btnLogin);
this.Controls.Add(this.lblServerIP); this.Controls.Add(this.lblServerAddress);
this.Controls.Add(this.lblPassword); this.Controls.Add(this.lblPassword);
this.Controls.Add(this.lblUsername); this.Controls.Add(this.lblUsername);
this.Controls.Add(this.lblServerAddress); this.Controls.Add(this.txtServerAddress);
this.Controls.Add(this.txtPassword); this.Controls.Add(this.txtPassword);
this.Controls.Add(this.txtUsername); this.Controls.Add(this.txtUsername);
this.Controls.Add(this.pictureBoxImageLogo); this.Controls.Add(this.pictureBoxImageLogo);
@ -168,8 +167,8 @@
private System.Windows.Forms.Label lblUsername; private System.Windows.Forms.Label lblUsername;
private System.Windows.Forms.TextBox txtPassword; private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Label lblPassword; private System.Windows.Forms.Label lblPassword;
private System.Windows.Forms.TextBox lblServerAddress; private System.Windows.Forms.TextBox txtServerAddress;
private System.Windows.Forms.Label lblServerIP; private System.Windows.Forms.Label lblServerAddress;
private System.Windows.Forms.Button btnLogin; private System.Windows.Forms.Button btnLogin;
private System.Windows.Forms.Button btnExit; private System.Windows.Forms.Button btnExit;
private System.Windows.Forms.Label lblLoginStatus; private System.Windows.Forms.Label lblLoginStatus;

View File

@ -1,25 +1,41 @@
using System.Drawing; using System.Drawing;
using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
namespace AIParkingApplication namespace AIParkingApplication
{ {
public partial class LoginForm : Form public partial class LoginForm : Form
{ {
private const string serverBaseAddress = "http://localhost:80/";
private ApiController apiController; private ApiController apiController;
public LoginForm() public LoginForm()
{ {
InitializeComponent(); InitializeComponent();
pictureBoxImageLogo.Image = new Bitmap(@".\Images\ApplicationLogo.ico"); if (File.Exists(AppConstant.DEFAULT_LOGO_IMAGE))
{
pictureBoxImageLogo.Image = new Bitmap(AppConstant.DEFAULT_LOGO_IMAGE);
}
txtUsername.Focus();
lblLoginStatus.Text = string.Empty; lblLoginStatus.Text = string.Empty;
apiController = new ApiController(serverBaseAddress);
this.AcceptButton = btnLogin; this.AcceptButton = btnLogin;
} }
private async void Login() private async void Login()
{ {
if (string.IsNullOrEmpty(txtServerAddress.Text))
{
lblLoginStatus.Text = "Địa chỉ server không được để trống!";
return;
}
if (!Util.IsUrlValid(txtServerAddress.Text))
{
lblLoginStatus.Text = "Địa chỉ server không đúng định dạng: \r\n http://localhost:80 hoặc http://192.168.1.2:80";
return;
}
apiController = new ApiController(txtServerAddress.Text);
lblLoginStatus.Text = string.Empty; lblLoginStatus.Text = string.Empty;
string username = txtUsername.Text; string username = txtUsername.Text;
string password = txtPassword.Text; string password = txtPassword.Text;
@ -28,10 +44,11 @@ namespace AIParkingApplication
lblLoginStatus.Text = "Tên tài khoản hoặc mật khẩu không được để trống!"; lblLoginStatus.Text = "Tên tài khoản hoặc mật khẩu không được để trống!";
return; return;
} }
var loginResult = await apiController.Login(new LoginModel { Username = username, Password = password }); var loginResult = await apiController.Login(new LoginModel { Username = username, Password = password });
if (loginResult.IsLoginSuccess) if (loginResult.IsLoginSuccess)
{ {
new AIParkingApplicationForm().Show(); new AIParkingApplicationForm(apiController, loginResult.LoginData).Show();
Hide(); Hide();
} }
else else

View File

@ -2,7 +2,6 @@
using OpenCvSharp.Extensions; using OpenCvSharp.Extensions;
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AIParkingApplication namespace AIParkingApplication
@ -13,11 +12,13 @@ namespace AIParkingApplication
private bool isSupportLongPlate; private bool isSupportLongPlate;
private PlateDetector squarePlateDetector; private PlateDetector squarePlateDetector;
private PlateDetector longPlateDetector; private PlateDetector longPlateDetector;
private EngineApiController engineApiController;
public PlateProcessor(bool isSupportSquarePlate = true, bool isSupportLongPlate = false) public PlateProcessor(EngineApiController engineApiController, bool isSupportSquarePlate = true, bool isSupportLongPlate = false)
{ {
this.isSupportSquarePlate = isSupportSquarePlate; this.isSupportSquarePlate = isSupportSquarePlate;
this.isSupportLongPlate = isSupportLongPlate; this.isSupportLongPlate = isSupportLongPlate;
this.engineApiController = engineApiController;
if (this.isSupportSquarePlate) if (this.isSupportSquarePlate)
{ {
@ -35,7 +36,7 @@ namespace AIParkingApplication
Mat plateDetected = plateType == PlateType.Square ? squarePlateDetector.DetectPlate(frame) : longPlateDetector.DetectPlate(frame); Mat plateDetected = plateType == PlateType.Square ? squarePlateDetector.DetectPlate(frame) : longPlateDetector.DetectPlate(frame);
//TODO: Check if plateDetected empty //TODO: Check if plateDetected empty
OcrResult plateOcrResultFromEngine = await Util.SendEngineRequestAsync(plateDetected, plateType); OcrResult plateOcrResultFromEngine = await engineApiController.SendEngineRequestAsync(plateDetected, plateType);
Mat finalPlateImage; Mat finalPlateImage;
if (!string.IsNullOrEmpty(plateOcrResultFromEngine.PlateString) && !string.IsNullOrEmpty(plateOcrResultFromEngine.PlateImageBase64)) if (!string.IsNullOrEmpty(plateOcrResultFromEngine.PlateString) && !string.IsNullOrEmpty(plateOcrResultFromEngine.PlateImageBase64))
{ {

View File

@ -9,7 +9,7 @@ namespace AIParkingApplication
{ {
private Statistic statistic; private Statistic statistic;
public Sidebar(ApiController apiController, string logoImagePath = @".\Images\ApplicationLogo.ico") public Sidebar(ApiController apiController, string logoImagePath = AppConstant.DEFAULT_LOGO_IMAGE)
{ {
InitializeComponent(); InitializeComponent();
if (File.Exists(logoImagePath)) if (File.Exists(logoImagePath))

View File

@ -6,6 +6,7 @@ using System.Drawing;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -13,8 +14,6 @@ namespace AIParkingApplication
{ {
public static class Util public static class Util
{ {
private static HttpClient httpClientEngine = new HttpClient { BaseAddress = new Uri("http://localhost:8080/"), Timeout = TimeSpan.FromMilliseconds(5000) };
public static bool IsPingable(string destinationIPAddress, out long pingTime, int timeOut = UtilConstant.PING_TIMEOUT_MS) public static bool IsPingable(string destinationIPAddress, out long pingTime, int timeOut = UtilConstant.PING_TIMEOUT_MS)
{ {
var pingTask = Task.Factory.StartNew(async () => var pingTask = Task.Factory.StartNew(async () =>
@ -55,29 +54,6 @@ namespace AIParkingApplication
return sf.GetMethod().Name; return sf.GetMethod().Name;
} }
public static async Task<OcrResult> SendEngineRequestAsync(Mat plateImage, PlateType plateType)
{
string plateImageBase64 = Convert.ToBase64String(plateImage.ToBytes());
try
{
var request = new PlateRequestEngineModel
{
Img64 = plateImageBase64,
Mode = plateType == PlateType.Square ? "square" : "long",
Display = "full"
};
HttpResponseMessage response = await httpClientEngine.PostAsJsonAsync("/get-from-frame", request);
response.EnsureSuccessStatusCode();
var ocrResult = await response.Content.ReadAsAsync<OcrResult>();
return ocrResult;
}
catch (Exception ex)
{
Console.WriteLine($"SendEngineRequest : {ex.Message}");
return new OcrResult();
}
}
public static void UpdateImage(this PictureBox pictureBox, Bitmap image) public static void UpdateImage(this PictureBox pictureBox, Bitmap image)
{ {
if (pictureBox.IsDisposed) if (pictureBox.IsDisposed)
@ -168,6 +144,14 @@ namespace AIParkingApplication
//process.Close(); //process.Close();
} }
} }
public static bool IsUrlValid(string url)
{
string pattern = @"^(http|https|ftp|)\://|[a-zA-Z0-9\-\.]+\.[a-zA-Z](:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&amp;%\$#\=~])*[^\.\,\)\(\s]$";
Regex reg = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
return reg.IsMatch(url);
}
} }
public class PlateRequestEngineModel public class PlateRequestEngineModel