123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Threading;
- using System.IO;
- using System.Globalization;
- using System.Runtime.InteropServices;
- namespace VzClientSDKDemo
- {
- public partial class RuleCfg_Form : Form
- {
- private int lpr_handle_ = 0;
- private uint IMG_SIZE = 1920 * 1080;
- private byte[] pic_data_ = new byte[1920*1080];
- private IntPtr img_buf_ptr_;
- private GCHandle img_object_;
- private System.Timers.Timer draw_rule_timer_;
- public static Mutex mutex_rule_ = new Mutex();
- private const int LOOP_POINT_COUNT = 4;
- private Graphics g_box_;
- private Point[] loop_point_array_ = new Point[LOOP_POINT_COUNT];
- private Pen pen_loop_ = new Pen(Color.LightCoral, 2);
- private uint graph_width_ = 1280;
- private uint graph_heigh_ = 720;
- private const int BOUND_VALUE = 5;
- private const int SELE_BOUND_VALUE = 8;
- private const int CONTROL_BORDER = 2;
- private VzClientSDK.VZ_LPRC_VIRTUAL_LOOPS loops_ = new VzClientSDK.VZ_LPRC_VIRTUAL_LOOPS();
- private int active_pt_index_ = -1;
- private double zoom_x_rate = 0.0;
- private double zoom_y_rate = 0.0;
- private bool mouse_down_ = false;
- private Point pt_mouse_down_ = new Point();
- private Point pt_prev_ = new Point();
- private bool select_loop_ = false;
- public void SetLPRHandle(int handle)
- {
- lpr_handle_ = handle;
- }
- public RuleCfg_Form()
- {
- InitializeComponent();
- }
- private void RuleCfg_Form_Load(object sender, EventArgs e)
- {
- // 开启获取实时解码数据
- if (lpr_handle_ > 0)
- {
- VzClientSDK.VzLPRClient_StartRealPlayDecData(lpr_handle_);
- }
- img_object_ = GCHandle.Alloc(pic_data_, GCHandleType.Pinned);
- img_buf_ptr_ = img_object_.AddrOfPinnedObject();
- draw_rule_timer_ = new System.Timers.Timer(80);
- draw_rule_timer_.Elapsed += drawTimer_Elapsed;
- draw_rule_timer_.AutoReset = true;
- draw_rule_timer_.Enabled = true;
- g_box_ = picBoxVideo.CreateGraphics();
- LoadRuleParam();
- }
- private void LoadRuleParam()
- {
- if (lpr_handle_ > 0)
- {
- // 加载虚拟线圈的规则
- int ret = VzClientSDK.VzLPRClient_GetVirtualLoop(lpr_handle_, ref loops_);
- if (loops_.uNumVirtualLoop > 0)
- {
- LoadLoopParam();
- uint x = 0, y = 0;
- for( int i = 0; i < LOOP_POINT_COUNT; i++ )
- {
- x = loops_.struLoop[0].struVertex[i].X_1000 * graph_width_ / 1000;
- y = loops_.struLoop[0].struVertex[i].Y_1000 * graph_heigh_ / 1000;
- loop_point_array_[i] = new Point((int)x, (int)y);
- }
- zoom_x_rate = (double)picBoxVideo.Width / (double)graph_width_;
- zoom_y_rate = (double)picBoxVideo.Height / (double)graph_heigh_;
- }
- else
- {
- EnableLoopParamCtrl(false);
- }
- }
- }
- private void drawTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
- {
- mutex_rule_.WaitOne();
- int nBufSize = VzClientSDK.VzLPRClient_GetJpegStreamFromRealPlayDec(lpr_handle_, img_buf_ptr_, IMG_SIZE, 100);
- if (nBufSize > 0)
- {
- // 显示图像到界面
- MemoryStream ms = new MemoryStream(pic_data_);
- Bitmap bitmap = new Bitmap(ms);
- Graphics g = Graphics.FromImage(bitmap);
- if ( loops_.uNumVirtualLoop == 1 )
- {
- g.DrawPolygon(pen_loop_, loop_point_array_);
- if (graph_width_ != bitmap.Width || graph_heigh_ != bitmap.Height)
- {
- graph_width_ = (uint)bitmap.Width;
- graph_heigh_ = (uint)bitmap.Height;
- zoom_x_rate = (double)picBoxVideo.Width / (double)graph_width_;
- zoom_y_rate = (double)picBoxVideo.Height / (double)graph_heigh_;
- ReloadLoop( );
- }
- for( int i = 0; i < LOOP_POINT_COUNT; i++ )
- {
- if ( i == active_pt_index_ )
- {
- g.DrawRectangle(Pens.LightGreen, loop_point_array_[i].X - SELE_BOUND_VALUE, loop_point_array_[i].Y - SELE_BOUND_VALUE, SELE_BOUND_VALUE * 2, SELE_BOUND_VALUE * 2);
- }
- else
- {
- g.DrawRectangle(Pens.LightYellow, loop_point_array_[i].X - BOUND_VALUE, loop_point_array_[i].Y - BOUND_VALUE, BOUND_VALUE * 2, BOUND_VALUE * 2);
- }
- }
- }
- Rectangle rc_dest = new Rectangle(0, 0, picBoxVideo.Width, picBoxVideo.Height);
- Rectangle rc_src = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
- g_box_.DrawImage(bitmap, rc_dest, rc_src, GraphicsUnit.Pixel);
- }
- mutex_rule_.ReleaseMutex();
- }
- private void ReloadLoop( )
- {
- for (int i = 0; i < LOOP_POINT_COUNT; i++)
- {
- loop_point_array_[i].X = (int)(loops_.struLoop[0].struVertex[i].X_1000 * graph_width_ / 1000);
- loop_point_array_[i].Y = (int)(loops_.struLoop[0].struVertex[i].Y_1000 * graph_heigh_ / 1000);
- }
- }
- private void RuleCfg_Form_FormClosed(object sender, FormClosedEventArgs e)
- {
- draw_rule_timer_.Enabled = false;
- draw_rule_timer_.Stop();
- VzClientSDK.VzLPRClient_StopRealPlayDecData(lpr_handle_);
- if (img_object_.IsAllocated)
- {
- img_object_.Free();
- }
- }
- private int Point2PointDist(Point pt_start, Point pt_end)
- {
- double dbDist = (pt_start.X - pt_end.X) * (pt_start.X - pt_end.X) + (pt_start.Y - pt_end.Y) * (pt_start.Y - pt_end.Y);
- int nDist = (int)Math.Sqrt(dbDist);
- return nDist;
- }
- private int GetPointIndex(Point pt, int max_dist)
- {
- int index = -1;
- int dist = 0;
-
- for( int i = 0; i < LOOP_POINT_COUNT; i++ )
- {
- dist = Point2PointDist(pt, loop_point_array_[i]);
- if (dist <= max_dist)
- {
- max_dist = dist;
- index = i;
- }
- }
- return index;
- }
- private Point PointToImgPoint(Point pt)
- {
- Point pt_img = new Point();
- pt_img.X = GetImgX(pt.X);
- pt_img.Y = GetImgY(pt.Y);
- return pt_img;
- }
- private int GetImgX(int x)
- {
- int img_x = x;
- if( zoom_x_rate > 0.01 )
- {
- img_x = (int)(x / zoom_x_rate);
- }
-
- return img_x;
- }
- private int GetImgY(int y)
- {
- int img_y = y;
- if ( zoom_y_rate > 0.01 )
- {
- img_y = (int)(y / zoom_y_rate);
- }
-
- return img_y;
- }
- private void btnSave_Click(object sender, EventArgs e)
- {
- int nMinLPWidth = int.Parse(txtMinWidth.Text);
- int nMaxLPWidth = int.Parse(txtMaxWidth.Text);
- if (nMinLPWidth < 45 || nMaxLPWidth > 600 || nMinLPWidth >= nMaxLPWidth)
- {
- MessageBox.Show("车牌宽度限制填写不正确,请重新输入!");
- return;
- }
- if( lpr_handle_ > 0 )
- {
- if (loops_.uNumVirtualLoop == 1)
- {
- for (int i = 0; i < LOOP_POINT_COUNT; i++)
- {
- loops_.struLoop[0].struVertex[i].X_1000 = (uint)(loop_point_array_[i].X * 1000 / graph_width_);
- loops_.struLoop[0].struVertex[i].Y_1000 = (uint)(loop_point_array_[i].Y * 1000 / graph_heigh_);
- }
- loops_.struLoop[0].uMinLPWidth = uint.Parse(txtMinWidth.Text);
- loops_.struLoop[0].uMaxLPWidth = uint.Parse(txtMaxWidth.Text);
- loops_.struLoop[0].uTriggerTimeGap = uint.Parse(txtTimes.Text);
- loops_.struLoop[0].eCrossDir = (uint)(cmbDir.SelectedIndex);
- loops_.struLoop[0].byDraw = (chkDraw.Checked ? (byte)1 : (byte)0);
- loops_.struLoop[0].byEnable = (chkEnable.Checked ? (byte)1 : (byte)0);
- }
- else
- {
- // 清空数据
- for (int i = 0; i < LOOP_POINT_COUNT; i++)
- {
- loops_.struLoop[0].struVertex[i].X_1000 = 0;
- loops_.struLoop[0].struVertex[i].Y_1000 = 0;
- }
- loops_.struLoop[0].strName = "";
- loops_.struLoop[0].uMinLPWidth = 0;
- loops_.struLoop[0].uMaxLPWidth = 0;
- loops_.struLoop[0].uTriggerTimeGap = 0;
- loops_.struLoop[0].eCrossDir = 0;
- loops_.struLoop[0].byDraw = 0;
- loops_.struLoop[0].byEnable = 0;
- }
- int ret = VzClientSDK.VzLPRClient_SetVirtualLoop(lpr_handle_, ref loops_);
- if (ret == 0)
- {
- MessageBox.Show("保存线圈参数成功!");
- }
- else
- {
- MessageBox.Show("保存线圈参数失败!");
- }
- }
- }
- private void picBoxVideo_MouseMove(object sender, MouseEventArgs e)
- {
- Point pt_mouse = new Point(e.X, e.Y);
- Point pt_img = PointToImgPoint(pt_mouse);
- int dis_x = 0, dis_y = 0;
- if (mouse_down_)
- {
- if ( active_pt_index_ >= 0 && active_pt_index_ < LOOP_POINT_COUNT )
- {
- Point ptNow = GetInBoundPoint(pt_img);
- if (!GetEditIsCross(active_pt_index_, ptNow))
- {
- // 移动点
- loop_point_array_[active_pt_index_] = ptNow;
- }
- }
- else
- {
- // 移动整个图形
- if( select_loop_ )
- {
- // 获取当前位置与之前位置的坐标差
- dis_x = pt_img.X - pt_prev_.X;
- dis_y = pt_img.Y - pt_prev_.Y;
- // 如果图形上所有的点没有超过图形范围,则移动图形
- MoveBoundLimit(ref dis_x, ref dis_y);
- if (dis_x != 0 || dis_y != 0)
- {
- MoveAllPoints(dis_x, dis_y);
- // 保存之前的坐标
- pt_prev_.X += dis_x;
- pt_prev_.Y += dis_y;
- }
- }
- }
- }
- else
- {
- active_pt_index_ = GetPointIndex(pt_img, 10);
- PointIsInPolygen(pt_img);
- }
- }
- private void MoveAllPoints(int dis_x, int dis_y)
- {
-
- for( int i = 0; i < LOOP_POINT_COUNT; i++ )
- {
- loop_point_array_[i].X += dis_x;
- loop_point_array_[i].Y += dis_y;
- }
- }
- private void picBoxVideo_MouseDown(object sender, MouseEventArgs e)
- {
- pt_mouse_down_.X = e.X;
- pt_mouse_down_.Y = e.Y;
- Point pt_img = PointToImgPoint(pt_mouse_down_);
- select_loop_ = PointIsInPolygen(pt_img);
- if ( select_loop_ )
- {
- pt_prev_ = pt_img;
- }
- mouse_down_ = true;
- }
- private void picBoxVideo_MouseUp(object sender, MouseEventArgs e)
- {
- mouse_down_ = false;
- }
- bool PointIsInPolygen(Point pt)
- {
- Point pt0, pt1;
- int dist = 0;
- int counter = 0;
- bool result = false;
-
- for ( int i = 0; i < LOOP_POINT_COUNT - 1; i++ )
- {
- pt0 = loop_point_array_[i];
- pt1 = loop_point_array_[i + 1];
- if ((pt0.Y <= pt.Y && pt1.Y <= pt.Y) ||
- (pt0.Y > pt.Y && pt1.Y > pt.Y) ||
- (pt0.X < pt.X && pt1.X < pt.X) )
- {
- if( pt.Y == pt1.Y && (pt.X == pt1.X || (pt.Y == pt0.Y &&
- ((pt0.X <= pt.X && pt.X <= pt1.X) || (pt1.X <= pt.X && pt.X <= pt0.X)))) )
- return true;
- continue;
- }
-
- dist = (pt.Y - pt0.Y)*(pt1.X - pt0.X) - (pt.X - pt0.X)*(pt1.Y - pt0.Y);
- if( dist == 0 )
- return true;
- if( pt1.Y < pt0.Y )
- dist = -dist;
-
- if (dist > 0)
- {
- counter ++;
- }
- // counter += dist > 0;
- }
- result = (counter % 2) == 0 ? false : true;
- return result;
- }
- private void MoveBoundLimit(ref int nDisX, ref int nDisY)
- {
- int nCurX = 0;
- int nCurY = 0;
- for( int i = 0; i < LOOP_POINT_COUNT; i++ )
- {
- nCurX = loop_point_array_[i].X + nDisX;
- nCurY = loop_point_array_[i].Y + nDisY;
- if (nCurX > ((int)graph_width_ - CONTROL_BORDER))
- {
- nCurX = ((int)graph_width_ - CONTROL_BORDER);
- }
- else if( nCurX < 0 ){
- nCurX = 0;
- }
- nDisX = nCurX - loop_point_array_[i].X;
- if (nCurY > ((int)graph_heigh_ - CONTROL_BORDER))
- {
- nCurY = ((int)graph_heigh_ - CONTROL_BORDER);
- }
- else if( nCurY < 0 )
- {
- nCurY = 0 ;
- }
- nDisY = nCurY -loop_point_array_[i].Y;
- }
- }
- private bool GetEditIsCross( int nPtIndex, Point ptMouse )
- {
- int nMaxIndex = LOOP_POINT_COUNT - 1;
- bool bCross = false;
- bool bCross1, bCross2;
- Point ptEdge1Start, ptEdge1End;
- Point ptEdge2Start, ptEdge2End;
- Point ptStart, ptEnd;
- // 移动起点
- if( nPtIndex == 0 )
- {
- ptStart = loop_point_array_[1];
- ptEnd = ptStart;
- // 第一条边
- ptEdge1Start = ptMouse;
- ptEdge1End = loop_point_array_[1];
- for (int i = 2; i < LOOP_POINT_COUNT; i++)
- {
- ptEnd = loop_point_array_[i];
- bCross = GetLineIsCross(ptEdge1Start, ptEdge1End, ptStart, ptEnd);
- if( bCross )
- {
- break;
- }
- ptStart = ptEnd;
- }
- } // 移动终点
- else if( nPtIndex == nMaxIndex )
- {
- ptStart = loop_point_array_[0];
- ptEnd = ptStart;
- // 第一条边
- ptEdge1Start = loop_point_array_[nMaxIndex - 1];
- ptEdge1End = ptMouse;
- for( int i = 1; i < nMaxIndex; i++ )
- {
- ptEnd = loop_point_array_[i];
- bCross = GetLineIsCross(ptEdge1Start, ptEdge1End, ptStart, ptEnd);
- if( bCross )
- {
- break;
- }
- ptStart = ptEnd;
- }
- }
- else
- {
- ptStart = loop_point_array_[0];
- ptEnd = ptStart;
- // 第一条边
- ptEdge1Start = loop_point_array_[nPtIndex-1];
- ptEdge1End = ptMouse;
- // 第二条边
- ptEdge2Start = ptMouse;
- ptEdge2End = loop_point_array_[nPtIndex + 1];
- for (int i = 1; i < LOOP_POINT_COUNT; i++)
- {
- ptEnd = loop_point_array_[i];
- if( (i == nPtIndex) || (i == (nPtIndex + 1)) )
- {
- ptStart = ptEnd;
- continue;
- }
-
- bCross1 = GetLineIsCross(ptEdge1Start, ptEdge1End, ptStart, ptEnd);
- bCross2 = GetLineIsCross(ptEdge2Start, ptEdge2End, ptStart, ptEnd);
- if( bCross1 || bCross2 )
- {
- bCross = true;
- break;
- }
- ptStart = ptEnd;
- }
- }
- return bCross;
- }
- private bool GetLineIsCross(Point ptMa, Point ptMb, Point ptNa, Point ptNb)
- {
- double dbV1, dbV2, dbV3, dbV4;
- dbV1 = (ptMb.X - ptMa.X) * (ptNb.Y - ptMa.Y) - (ptMb.Y - ptMa.Y) * (ptNb.X - ptMa.X);
- dbV2 = (ptMb.X - ptMa.X) * (ptNa.Y - ptMa.Y) - (ptMb.Y - ptMa.Y) * (ptNa.X - ptMa.X);
- double dbResult1 = dbV1 * dbV2;
- if( dbResult1 >= 0 )
- {
- return false;
- }
- dbV3 = (ptNb.X - ptNa.X) * (ptMb.Y - ptNa.Y) - (ptNb.Y - ptNa.Y) * (ptMb.X - ptNa.X);
- dbV4 = (ptNb.X - ptNa.X) * (ptMa.Y - ptNa.Y) - (ptNb.Y - ptNa.Y) * (ptMa.X - ptNa.X);
- double dbResult2 = dbV3 * dbV4;
- if( dbResult2 >= 0 )
- {
- return false;
- }
- return true;
- }
- private Point GetInBoundPoint( Point pt )
- {
- Point ptResult = pt;
-
- if( ptResult.X < 0 )
- {
- ptResult.X = 0;
- }
- if( ptResult.X > ((int)graph_width_ - CONTROL_BORDER) )
- {
- ptResult.X = (int)graph_width_ - CONTROL_BORDER;
- }
- if( ptResult.Y < 0 )
- {
- ptResult.Y = 0;
- }
- if (ptResult.Y > ((int)graph_heigh_ - CONTROL_BORDER))
- {
- ptResult.Y = (int)graph_heigh_ - CONTROL_BORDER;
- }
- return ptResult;
- }
- private void EnableLoopParamCtrl(bool enable)
- {
- txtMinWidth.Enabled = enable;
- txtMaxWidth.Enabled = enable;
- txtTimes.Enabled = enable;
- cmbDir.Enabled = enable;
- chkDraw.Enabled = enable;
- chkEnable.Enabled = enable;
- }
- // 删除线圈
- private void btnDeleRule_Click(object sender, EventArgs e)
- {
- loops_.uNumVirtualLoop = 0;
- for ( int i = 0; i < LOOP_POINT_COUNT; i++ )
- {
- loop_point_array_[i].X = 0;
- loop_point_array_[i].Y = 0;
- }
- EnableLoopParamCtrl(false);
- }
- private void LoadLoopParam()
- {
-
- string rule_name = loops_.struLoop[0].strName;
- txtRuleName.Text = rule_name;
- uint time_gap = loops_.struLoop[0].uTriggerTimeGap;
- txtTimes.Text = time_gap.ToString();
- if (loops_.struLoop[0].byDraw == 1)
- {
- chkDraw.Checked = true;
- }
- if (loops_.struLoop[0].byEnable == 1)
- {
- chkEnable.Checked = true;
- }
- uint min_lp_width = loops_.struLoop[0].uMinLPWidth;
- uint max_lp_width = loops_.struLoop[0].uMaxLPWidth;
- txtMinWidth.Text = min_lp_width.ToString();
- txtMaxWidth.Text = max_lp_width.ToString();
- uint cross_dir = loops_.struLoop[0].eCrossDir;
- if (cross_dir >= 0 && cross_dir < 3)
- {
- cmbDir.SelectedIndex = (int)cross_dir;
- }
- else
- {
- cmbDir.SelectedIndex = 0;
- }
- }
- // 添加线圈的功能
- private void btnAddRule_Click(object sender, EventArgs e)
- {
- if (loops_.uNumVirtualLoop >= 1)
- {
- MessageBox.Show("只允许配置一个虚拟线圈!");
- return;
- }
- int RULE_GRAPH_BORDER = 100;
- int nWidth = (int)graph_width_;
- int nHeight = (int)graph_heigh_;
- int nMaxWidth = nWidth - RULE_GRAPH_BORDER;
- int nMaxHeight = nHeight - RULE_GRAPH_BORDER;
- Point pt1 = new Point(RULE_GRAPH_BORDER,RULE_GRAPH_BORDER + nMaxHeight / 2 );
- Point pt2 = new Point(nWidth - RULE_GRAPH_BORDER, RULE_GRAPH_BORDER + nMaxHeight/2);
- Point pt3 = new Point(nWidth - RULE_GRAPH_BORDER, nHeight - RULE_GRAPH_BORDER);
- Point pt4 = new Point(RULE_GRAPH_BORDER, nMaxHeight);
- loop_point_array_[0] = pt1;
- loop_point_array_[1] = pt2;
- loop_point_array_[2] = pt3;
- loop_point_array_[3] = pt4;
- loops_.uNumVirtualLoop = 1;
- loops_.struLoop[0].strName = "电子线圈";
- loops_.struLoop[0].eCrossDir = 0;
- loops_.struLoop[0].uTriggerTimeGap = 10;
- loops_.struLoop[0].byDraw = 1;
- loops_.struLoop[0].byEnable = 1;
- loops_.struLoop[0].uMinLPWidth = 45;
- loops_.struLoop[0].uMaxLPWidth = 600;
- loops_.uNumVirtualLoop = 1;
- LoadLoopParam();
- EnableLoopParamCtrl(true);
- }
- private void btnROI_Click(object sender, EventArgs e)
- {
- VzClientSDK.VZ_LPRC_ROI_EX struROI = new VzClientSDK.VZ_LPRC_ROI_EX();
- int nRet = VzClientSDK.VzLPRClient_GetRegionOfInterestEx(lpr_handle_, ref struROI);
- if (nRet == 0)
- {
- }
- }
-
- }
- }
|