Browse Source

feat: 完善内部调用计算流程

master
fajiao 2 years ago
parent
commit
d25dea0ac1
  1. 12
      Cis.Application/AppConfig.json
  2. 8
      Cis.Application/Core/Algo/HikMarkSeacher.cs
  3. 95
      Cis.Application/Core/Algo/MarkSearcherBase.cs
  4. 9
      Cis.Application/Core/Api/PtzServerApi.cs
  5. 139
      Cis.Application/Core/Center/CameraDataCenter.cs
  6. 13
      Cis.Application/Core/Common/Options.cs
  7. 66
      Cis.Application/Core/Entity/CameraCalcInfo.cs
  8. 1
      Cis.Application/Startup.cs
  9. 11
      Cis.Application/Tb/Common/TbInfo.cs
  10. 2
      Cis.Application/Tb/Service/TbPtzCameraService.cs
  11. 7
      Cis.Core/CoreConfig.json
  12. 10
      Cis.Core/Extension/ObjectExtension.cs

12
Cis.Application/AppConfig.json

@ -1,4 +1,12 @@
{ {
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
"CameraDataOptions": {
"LazyInit": false,
"LoopInterval": "1000"
},
"PTZServer": {
"Type": "",
"Ip": "127.0.0.1",
"Port": "7022"
}
} }

8
Cis.Application/Core/Algo/HikMarkSeacher.cs

@ -40,8 +40,8 @@ public class HikMarkSeacher : MarkSearcherBase
protected override void CalcSensor() protected override void CalcSensor()
{ {
CameraCalcInfo.MinFocusX = 1783.6 / CameraCalcInfo.ImageWidth; _cameraCalcInfo.MinFocusX = 1783.6 / _cameraCalcInfo.ImageWidth;
CameraCalcInfo.MinFocusY = 1781.4 / CameraCalcInfo.ImageHeight; _cameraCalcInfo.MinFocusY = 1781.4 / _cameraCalcInfo.ImageHeight;
} }
#endregion Implement #endregion Implement
@ -50,13 +50,13 @@ public class HikMarkSeacher : MarkSearcherBase
protected virtual double GetFx(double zoomPos) protected virtual double GetFx(double zoomPos)
{ {
CameraCalcInfo calcInfo = CameraCalcInfo; CameraCalcInfo calcInfo = _cameraCalcInfo;
return calcInfo.MinFocusX * GetZoomTag(zoomPos); return calcInfo.MinFocusX * GetZoomTag(zoomPos);
} }
protected virtual double GetFy(double zoomPos) protected virtual double GetFy(double zoomPos)
{ {
CameraCalcInfo calcInfo = CameraCalcInfo; CameraCalcInfo calcInfo = _cameraCalcInfo;
return calcInfo.MinFocusY * GetZoomTag(zoomPos); return calcInfo.MinFocusY * GetZoomTag(zoomPos);
} }

95
Cis.Application/Core/Algo/MarkSearcherBase.cs

@ -10,9 +10,9 @@ public abstract class MarkSearcherBase
/// <summary> /// <summary>
/// 当前相机参数信息 /// 当前相机参数信息
/// </summary> /// </summary>
protected CameraCalcInfo CameraCalcInfo { get; set; } protected CameraCalcInfo _cameraCalcInfo { get; set; }
protected List<MarkLabelCalcInfo> MarkLabelInfoList { get; set; } = new(); protected List<MarkLabelCalcInfo> _markLabelInfoList { get; set; } = new();
protected MatrixBuilder<double> MBuilder { get; set; } = Matrix<double>.Build; protected MatrixBuilder<double> MBuilder { get; set; } = Matrix<double>.Build;
@ -25,14 +25,7 @@ public abstract class MarkSearcherBase
public MarkSearcherBase(CameraCalcInfo cameraCalcInfo) public MarkSearcherBase(CameraCalcInfo cameraCalcInfo)
{ {
InitCameraCalcInfoRelated(cameraCalcInfo); UpdateCameraCalcInfoRelated(cameraCalcInfo);
}
protected void InitCameraCalcInfoRelated(CameraCalcInfo cameraCalcInfo)
{
CameraCalcInfo = cameraCalcInfo;
CalcSensor();
World2CameraMatrix = ConvertWorldToCamera(cameraCalcInfo);
} }
#region Calc #region Calc
@ -41,23 +34,20 @@ public abstract class MarkSearcherBase
/// 计算标签位置过程 /// 计算标签位置过程
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public void Calc(CameraCalcInfo cameraCalcInfo) public List<MarkLabelCalcResult> Calc()
{ {
//判断 List<MarkLabelCalcResult> resultList = new();
if (IsCameraRotate(cameraCalcInfo))
InitCameraCalcInfoRelated(cameraCalcInfo);
if (World2CameraMatrix == null || MarkLabelInfoList.Count == 0) if (World2CameraMatrix == null || _markLabelInfoList.Count == 0)
return; return resultList;
for (int index = 0; index < MarkLabelInfoList.Count; index++) foreach (MarkLabelCalcInfo item in _markLabelInfoList)
{ {
MarkLabelCalcInfo label = MarkLabelInfoList[index]; Matrix<double> labelC2WMatrix = ConvertCameraToWorld(item);
Matrix<double> labelC2WMatrix = ConvertCameraToWorld(label);
Matrix<double> labelPointMatrix = MBuilder.DenseOfArray(new double[,] Matrix<double> labelPointMatrix = MBuilder.DenseOfArray(new double[,]
{ {
{ label.CanvasWidth / CameraCalcInfo.ImageWidth - 0.5 }, { item.CanvasWidth / _cameraCalcInfo.ImageWidth - 0.5 },
{ label.CanvasHeight / CameraCalcInfo.ImageHeight - 0.5 }, { item.CanvasHeight / _cameraCalcInfo.ImageHeight - 0.5 },
{ 1 } { 1 }
}); });
Matrix<double> lResult = labelC2WMatrix.Multiply(labelPointMatrix); Matrix<double> lResult = labelC2WMatrix.Multiply(labelPointMatrix);
@ -65,18 +55,19 @@ public abstract class MarkSearcherBase
double x = pResult[0, 0] / pResult[2, 0] + 0.5; double x = pResult[0, 0] / pResult[2, 0] + 0.5;
double y = pResult[1, 0] / pResult[2, 0] + 0.5; double y = pResult[1, 0] / pResult[2, 0] + 0.5;
MarkLabelCalcResult labelCalcResult = new(); MarkLabelCalcResult labelCalcResult;
if (x > 0.99 || x < 0.01 || y > 0.99 || y < 0.01 || pResult[2, 0] < 0) if (x > 0.99 || x < 0.01 || y > 0.99 || y < 0.01 || pResult[2, 0] < 0)
{ labelCalcResult = MarkLabelCalcResult.New(item.Id, false);
labelCalcResult.InFlag = false;
}
else else
{ labelCalcResult = MarkLabelCalcResult.New(item.Id, true, (x * _cameraCalcInfo.ImageWidth), (y * _cameraCalcInfo.ImageHeight));
labelCalcResult.InFlag = true; resultList.Add(labelCalcResult);
labelCalcResult.CanvasLeft = x * CameraCalcInfo.ImageWidth;
labelCalcResult.CanvasTop = y * CameraCalcInfo.ImageHeight;
}
} }
return resultList;
}
public async Task<List<MarkLabelCalcResult>> CalcAsync()
{
return await Task.Run(Calc);
} }
/// <summary> /// <summary>
@ -84,12 +75,11 @@ public abstract class MarkSearcherBase
/// </summary> /// </summary>
/// <param name="newInfo"></param> /// <param name="newInfo"></param>
/// <returns></returns> /// <returns></returns>
protected bool IsCameraRotate(CameraCalcInfo newInfo) protected bool IsCameraRotate(PtzInfo newInfo)
{ {
return CameraCalcInfo == null || return _cameraCalcInfo.PtzInfo.Pan != newInfo.Pan ||
CameraCalcInfo.PtzInfo.Pan != newInfo.PtzInfo.Pan || _cameraCalcInfo.PtzInfo.Tilt != newInfo.Tilt ||
CameraCalcInfo.PtzInfo.Tilt != newInfo.PtzInfo.Tilt || _cameraCalcInfo.PtzInfo.Zoom != newInfo.Zoom;
CameraCalcInfo.PtzInfo.Zoom != newInfo.PtzInfo.Zoom;
} }
/// <summary> /// <summary>
@ -204,4 +194,39 @@ public abstract class MarkSearcherBase
protected abstract PointF GetFOfMatrixByZoomPos(double zoomPos); protected abstract PointF GetFOfMatrixByZoomPos(double zoomPos);
#endregion Util #endregion Util
#region Operate Attr
protected void UpdateCameraCalcInfoRelated(CameraCalcInfo cameraCalcInfo)
{
_cameraCalcInfo = cameraCalcInfo;
CalcSensor();
World2CameraMatrix = ConvertWorldToCamera(cameraCalcInfo);
}
public void UpdateCameraCalcInfo(PtzInfo ptzInfo)
{
if (IsCameraRotate(ptzInfo))
{
_cameraCalcInfo.PtzInfo = ptzInfo;
World2CameraMatrix = ConvertWorldToCamera(_cameraCalcInfo);
}
}
public void AddMarkLabelCalcInfo(MarkLabelCalcInfo markLabelCalcInfo)
{
_markLabelInfoList.Add(markLabelCalcInfo);
}
public bool ExistsMarkLabelCalcInfo(object id)
{
foreach (MarkLabelCalcInfo info in _markLabelInfoList)
{
if (info.Id.Equals(id))
return true;
}
return false;
}
#endregion Operate Attr
} }

9
Cis.Application/Core/Api/PtzServerApi.cs

@ -24,7 +24,7 @@ public class PtzServerApi : IPtzApi, ISingleton
_stream = _tcpClient.GetStream(); _stream = _tcpClient.GetStream();
} }
public RequestRealControl GetPtzInfo(int cameraId) public RequestRealControl GetPtzRrc(int cameraId)
{ {
RequestRealControl realControl = new(); RequestRealControl realControl = new();
try try
@ -54,6 +54,13 @@ public class PtzServerApi : IPtzApi, ISingleton
return realControl; return realControl;
} }
public PtzInfo GetPtzInfo(int cameraId)
{
RequestRealControl rrc = GetPtzRrc(cameraId);
PtzInfo ptzInfo = PtzInfo.New(rrc.PTZPositionInfo.FP, rrc.PTZPositionInfo.FT, rrc.PTZPositionInfo.FZ);
return ptzInfo;
}
public static byte[] StructToByte(object structObj) public static byte[] StructToByte(object structObj)
{ {
//获取结构体大小 //获取结构体大小

139
Cis.Application/Core/Center/CameraDataCenter.cs

@ -13,10 +13,29 @@ public class CameraDataCenter
private readonly SqlSugarRepository<CmMarkLabel> _cmMarkLableRep; private readonly SqlSugarRepository<CmMarkLabel> _cmMarkLableRep;
private readonly SqlSugarRepository<TbPtzCamera> _tbPtzCameraRep; private readonly SqlSugarRepository<TbPtzCamera> _tbPtzCameraRep;
private readonly PtzServerApi _ptzServerApi; private readonly PtzServerApi _ptzServerApi;
private readonly CameraDataOptions options = App.GetOptions<CameraDataOptions>();
private Thread _thread { get; set; } private Thread _thread { get; set; }
private List<TbPtzCamera> _tbPtzCameraList { get; set; }
private ConcurrentDictionary<string, CameraCalcInfo> _cameraPtzInfoDict { get; set; } /// <summary>
/// (cbCameraId, MarkSearcherBase)
/// </summary>
private ConcurrentDictionary<long, MarkSearcherBase> _markSearcherDict { get; set; } = new();
/// <summary>
/// (cbCameraId, cbCameraIp)
/// </summary>
private Dictionary<long, string> _cbCameraId2IpDict { get; set; } = new();
/// <summary>
/// (cameraIp, TbPtzCamera)
/// </summary>
private ConcurrentDictionary<string, TbPtzCamera> _tbPtzCameraDict { get; set; } = new();
/// <summary>
/// (cameraIp, PtzInfo)
/// </summary>
private ConcurrentDictionary<string, PtzInfo> _cameraPtzInfoDict { get; set; } = new();
#endregion Attr #endregion Attr
@ -31,29 +50,16 @@ public class CameraDataCenter
private void Init() private void Init()
{ {
// 初始化 tbPtzCameraList if (!options.LazyInit)
_tbPtzCameraList = _tbPtzCameraRep.GetList();
// 根据 Ip 去重
_tbPtzCameraList = _tbPtzCameraList.Where((a, i) => _tbPtzCameraList.FindIndex(b => b.Ip == a.Ip) == i).ToList();
// 初始化 ptzInfoDict
_cameraPtzInfoDict = new ConcurrentDictionary<string, CameraCalcInfo>();
// 初始化 thread
_thread = new Thread(WorkLoop)
{ {
IsBackground = true// 设置后台线程 List<TbPtzCamera> list = _tbPtzCameraRep.GetList();
}; // 根据 Ip 去重
_thread.Start(); foreach (TbPtzCamera item in list)
} {
if (!_tbPtzCameraDict.ContainsKey(item.Ip))
private void LazyInit() _tbPtzCameraDict[item.Ip] = item;
{ }
// 初始化 tbPtzCameraList }
_tbPtzCameraList = new();
// 初始化 ptzInfoDict
_cameraPtzInfoDict = new ConcurrentDictionary<string, CameraCalcInfo>();
// 初始化 thread // 初始化 thread
_thread = new Thread(WorkLoop) _thread = new Thread(WorkLoop)
@ -65,47 +71,100 @@ public class CameraDataCenter
#region Loop #region Loop
/// <summary>
/// 循环运行
/// </summary>
private void WorkLoop() private void WorkLoop()
{ {
while (true) while (true)
{ {
GetPtzInfoByApi(); RefreshPtzInfoByApi();
Thread.Sleep(10000); RefreshMarkSearcher();
Thread.Sleep(options.LoopInterval);
} }
} }
private void GetPtzInfoByApi() private void RefreshPtzInfoByApi()
{ {
foreach (TbPtzCamera item in _tbPtzCameraList) foreach (TbPtzCamera item in _tbPtzCameraDict.Values)
{ {
RequestRealControl rrc = _ptzServerApi.GetPtzInfo(item.CameraId); PtzInfo ptzInfo = _ptzServerApi.GetPtzInfo(item.CameraId);
CameraCalcInfo ptzInfo = new()
{
Pan = rrc.PTZPositionInfo.FP,
Tilt = rrc.PTZPositionInfo.FT,
Zoom = rrc.PTZPositionInfo.FZ
};
_cameraPtzInfoDict[item.Ip] = ptzInfo; _cameraPtzInfoDict[item.Ip] = ptzInfo;
} }
} }
private void Calc() private void RefreshMarkSearcher()
{ {
foreach (KeyValuePair<long, MarkSearcherBase> pair in _markSearcherDict)
{
long cameraId = pair.Key;
MarkSearcherBase markSearcher = pair.Value;
string cameraIp = _cbCameraId2IpDict[cameraId];
if (cameraIp == null) continue;
PtzInfo ptzInfo = _cameraPtzInfoDict[cameraIp];
if (ptzInfo == null) continue;
markSearcher.UpdateCameraCalcInfo(ptzInfo);
List<MarkLabelCalcResult> resultList = markSearcher.Calc();
}
} }
#endregion Loop #endregion Loop
#region external call #region external call
public bool GetCamera(string ip) /// <summary>
/// 激活 cbCamera 进入运算
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool ActiveCamera(long cameraId)
{ {
return false; CbCamera cbCamera = _cbCameraRep.GetById(cameraId);
if (cbCamera == null) return false;
TbPtzCamera tbPtzCamera;
string cameraIp = cbCamera.Ip;
if (!_tbPtzCameraDict.IsExistKey(cameraIp))
{
tbPtzCamera = _tbPtzCameraRep.GetFirst(u => u.Ip == cameraIp);
if (tbPtzCamera == null) return false;
_tbPtzCameraDict[cameraIp] = tbPtzCamera;
}
else
{
tbPtzCamera = _tbPtzCameraDict[cameraIp];
}
_cbCameraId2IpDict[cbCamera.Id] = cameraIp;
CameraCalcInfo cameraCalcInfo = CameraCalcInfo.New(cameraId, _ptzServerApi.GetPtzInfo(tbPtzCamera.Id));
HikMarkSeacher markSeacher = new(cameraCalcInfo);
List<CmMarkLabel> cmMarkLabelList = _cmMarkLableRep.GetList(u => u.CbCameraId == cameraId);
foreach (CmMarkLabel item in cmMarkLabelList)
{
MarkLabelCalcInfo markLabelCalcInfo = MarkLabelCalcInfo.New(
item.Id,
PtzInfo.New(item.PanPosition, item.TiltPosition, item.ZoomPosition),
item.CanvasWidth,
item.CanvasHeight,
item.CanvasLeft,
item.CanvasTop
);
markSeacher.AddMarkLabelCalcInfo(markLabelCalcInfo);
}
_markSearcherDict[cameraId] = markSeacher;
return true;
} }
public bool ActiveCamera(string ip) /// <summary>
/// 解除 cbCamera 进入运算
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool DeActiveCamera(long cameraId)
{ {
return false;
}
public bool UpdateCamera(long cameraId, long markLabelId)
{
return false; return false;
} }

13
Cis.Application/Core/Common/Options.cs

@ -1,5 +1,18 @@
namespace Cis.Application.Core; namespace Cis.Application.Core;
public class CameraDataOptions : IConfigurableOptions
{
/// <summary>
/// 是否懒加载
/// </summary>
public bool LazyInit { get; set; }
/// <summary>
/// 循环间隔,单位毫秒
/// </summary>
public int LoopInterval { get; set; }
}
/// <summary> /// <summary>
/// PtzServer选项 /// PtzServer选项
/// </summary> /// </summary>

66
Cis.Application/Core/Entity/CameraCalcInfo.cs

@ -5,6 +5,11 @@
/// </summary> /// </summary>
public class CameraCalcInfo public class CameraCalcInfo
{ {
/// <summary>
/// Camera Id
/// </summary>
public long Id { get; set; }
/// <summary> /// <summary>
/// Ptz 信息 /// Ptz 信息
/// </summary> /// </summary>
@ -26,6 +31,15 @@ public class CameraCalcInfo
public double MinFocusX { get; set; } = 0f; public double MinFocusX { get; set; } = 0f;
public double MinFocusY { get; set; } = 0f; public double MinFocusY { get; set; } = 0f;
public static CameraCalcInfo New(long id, PtzInfo ptzInfo)
{
return new()
{
Id = id,
PtzInfo = ptzInfo
};
}
} }
/// <summary> /// <summary>
@ -47,6 +61,16 @@ public class PtzInfo
/// Zoom 坐标 /// Zoom 坐标
/// </summary> /// </summary>
public double Zoom { get; set; } public double Zoom { get; set; }
public static PtzInfo New(double pan, double tilt, double zoom)
{
return new()
{
Pan = pan,
Tilt = tilt,
Zoom = zoom
};
}
} }
/// <summary> /// <summary>
@ -54,6 +78,11 @@ public class PtzInfo
/// </summary> /// </summary>
public class MarkLabelCalcInfo public class MarkLabelCalcInfo
{ {
/// <summary>
/// MarkLabel Id
/// </summary>
public long Id { get; set; }
/// <summary> /// <summary>
/// Ptz 信息 /// Ptz 信息
/// </summary> /// </summary>
@ -78,6 +107,19 @@ public class MarkLabelCalcInfo
/// 画布 top 距离 /// 画布 top 距离
/// </summary> /// </summary>
public double CanvasTop { get; set; } public double CanvasTop { get; set; }
public static MarkLabelCalcInfo New(long id, PtzInfo ptzInfo, double canvasWidth, double canvasHeight, double canvasLeft, double canvasTop)
{
return new()
{
Id = id,
PtzInfo = ptzInfo,
CanvasWidth = canvasWidth,
CanvasHeight = canvasHeight,
CanvasLeft = canvasLeft,
CanvasTop = canvasTop
};
}
} }
/// <summary> /// <summary>
@ -85,6 +127,11 @@ public class MarkLabelCalcInfo
/// </summary> /// </summary>
public class MarkLabelCalcResult public class MarkLabelCalcResult
{ {
/// <summary>
/// MarkLabel Id
/// </summary>
public long Id { get; set; }
/// <summary> /// <summary>
/// true 显示(在当前视频画面里面) /// true 显示(在当前视频画面里面)
/// false 不显示(不在当前视频画面里面) /// false 不显示(不在当前视频画面里面)
@ -101,4 +148,23 @@ public class MarkLabelCalcResult
/// </summary> /// </summary>
public double CanvasTop { get; set; } public double CanvasTop { get; set; }
public static MarkLabelCalcResult New(long id, bool inFlag)
{
return new()
{
Id = id,
InFlag = inFlag
};
}
public static MarkLabelCalcResult New(long id, bool inFlag, double canvasLeft, double canvasTop)
{
return new()
{
Id = id,
InFlag = inFlag,
CanvasLeft = canvasLeft,
CanvasTop = canvasTop
};
}
} }

1
Cis.Application/Startup.cs

@ -14,6 +14,7 @@ public class Startup : AppStartup
/// <param name="services"></param> /// <param name="services"></param>
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddConfigurableOptions<CameraDataOptions>();
services.AddConfigurableOptions<PtzServerOptions>(); services.AddConfigurableOptions<PtzServerOptions>();
services.AddSingleton<CameraDataCenter>(new CameraDataCenter()); services.AddSingleton<CameraDataCenter>(new CameraDataCenter());

11
Cis.Application/Tb/Common/TbInfo.cs

@ -1,10 +1,4 @@
using System; namespace Cis.Application.Tb;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cis.Application.Tb;
public class TbInfo public class TbInfo
{ {
@ -25,5 +19,4 @@ public class TbInfo
public const string TbPtzCameraTbName = "tb_ptzcamera"; public const string TbPtzCameraTbName = "tb_ptzcamera";
#endregion Table Info #endregion Table Info
} }

2
Cis.Application/Tb/Service/TbPtzCameraService.cs

@ -19,7 +19,7 @@ public class TbPtzCameraService : ITransient
public async Task<List<TbPtzCamera>> GetList(string queryJson = "") public async Task<List<TbPtzCamera>> GetList(string queryJson = "")
{ {
JObject queryObj = !string.IsNullOrEmpty(queryJson) ? queryJson.ToJObject():default; JObject queryObj = !string.IsNullOrEmpty(queryJson) ? queryJson.ToJObject() : default;
List<TbPtzCamera> list = await _tbPtzCameraRep.AsQueryable() List<TbPtzCamera> list = await _tbPtzCameraRep.AsQueryable()
.ToListAsync(); .ToListAsync();
return list; return list;

7
Cis.Core/CoreConfig.json

@ -21,14 +21,9 @@
] ]
}, },
"Cache": { "Cache": {
"CacheType": "Redis", // MemoryRedis "CacheType": "Memory", // MemoryRedis
"RedisConnectionString": "127.0.0.1:6379;password=123456;db=2" "RedisConnectionString": "127.0.0.1:6379;password=123456;db=2"
}, },
"PTZServer": {
"Type": "",
"Ip": "127.0.0.1",
"Port": "7022"
},
"AppSettings": { "AppSettings": {
"InjectSpecificationDocument": true // Swagger "InjectSpecificationDocument": true // Swagger
}, },

10
Cis.Core/Extension/ObjectExtension.cs

@ -138,4 +138,14 @@ public static class ObjectExtension
var sc = pi.GetCustomAttributes<SugarColumn>(false).FirstOrDefault(u => u.IsIgnore == true); var sc = pi.GetCustomAttributes<SugarColumn>(false).FirstOrDefault(u => u.IsIgnore == true);
return sc != null; return sc != null;
} }
public static bool IsExistKey(this IDictionary dict, object key)
{
foreach (object item in dict.Keys)
{
if (Equals(key, item))
return true;
}
return false;
}
} }
Loading…
Cancel
Save