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()
{
CameraCalcInfo.MinFocusX = 1783.6 / CameraCalcInfo.ImageWidth;
CameraCalcInfo.MinFocusY = 1781.4 / CameraCalcInfo.ImageHeight;
_cameraCalcInfo.MinFocusX = 1783.6 / _cameraCalcInfo.ImageWidth;
_cameraCalcInfo.MinFocusY = 1781.4 / _cameraCalcInfo.ImageHeight;
}
#endregion Implement
@ -50,13 +50,13 @@ public class HikMarkSeacher : MarkSearcherBase
protected virtual double GetFx(double zoomPos)
{
CameraCalcInfo calcInfo = CameraCalcInfo;
CameraCalcInfo calcInfo = _cameraCalcInfo;
return calcInfo.MinFocusX * GetZoomTag(zoomPos);
}
protected virtual double GetFy(double zoomPos)
{
CameraCalcInfo calcInfo = CameraCalcInfo;
CameraCalcInfo calcInfo = _cameraCalcInfo;
return calcInfo.MinFocusY * GetZoomTag(zoomPos);
}

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

@ -10,9 +10,9 @@ public abstract class MarkSearcherBase
/// <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;
@ -25,14 +25,7 @@ public abstract class MarkSearcherBase
public MarkSearcherBase(CameraCalcInfo cameraCalcInfo)
{
InitCameraCalcInfoRelated(cameraCalcInfo);
}
protected void InitCameraCalcInfoRelated(CameraCalcInfo cameraCalcInfo)
{
CameraCalcInfo = cameraCalcInfo;
CalcSensor();
World2CameraMatrix = ConvertWorldToCamera(cameraCalcInfo);
UpdateCameraCalcInfoRelated(cameraCalcInfo);
}
#region Calc
@ -41,23 +34,20 @@ public abstract class MarkSearcherBase
/// 计算标签位置过程
/// </summary>
/// <returns></returns>
public void Calc(CameraCalcInfo cameraCalcInfo)
public List<MarkLabelCalcResult> Calc()
{
//判断
if (IsCameraRotate(cameraCalcInfo))
InitCameraCalcInfoRelated(cameraCalcInfo);
List<MarkLabelCalcResult> resultList = new();
if (World2CameraMatrix == null || MarkLabelInfoList.Count == 0)
return;
if (World2CameraMatrix == null || _markLabelInfoList.Count == 0)
return resultList;
for (int index = 0; index < MarkLabelInfoList.Count; index++)
foreach (MarkLabelCalcInfo item in _markLabelInfoList)
{
MarkLabelCalcInfo label = MarkLabelInfoList[index];
Matrix<double> labelC2WMatrix = ConvertCameraToWorld(label);
Matrix<double> labelC2WMatrix = ConvertCameraToWorld(item);
Matrix<double> labelPointMatrix = MBuilder.DenseOfArray(new double[,]
{
{ label.CanvasWidth / CameraCalcInfo.ImageWidth - 0.5 },
{ label.CanvasHeight / CameraCalcInfo.ImageHeight - 0.5 },
{ item.CanvasWidth / _cameraCalcInfo.ImageWidth - 0.5 },
{ item.CanvasHeight / _cameraCalcInfo.ImageHeight - 0.5 },
{ 1 }
});
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 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)
{
labelCalcResult.InFlag = false;
}
labelCalcResult = MarkLabelCalcResult.New(item.Id, false);
else
{
labelCalcResult.InFlag = true;
labelCalcResult.CanvasLeft = x * CameraCalcInfo.ImageWidth;
labelCalcResult.CanvasTop = y * CameraCalcInfo.ImageHeight;
}
labelCalcResult = MarkLabelCalcResult.New(item.Id, true, (x * _cameraCalcInfo.ImageWidth), (y * _cameraCalcInfo.ImageHeight));
resultList.Add(labelCalcResult);
}
return resultList;
}
public async Task<List<MarkLabelCalcResult>> CalcAsync()
{
return await Task.Run(Calc);
}
/// <summary>
@ -84,12 +75,11 @@ public abstract class MarkSearcherBase
/// </summary>
/// <param name="newInfo"></param>
/// <returns></returns>
protected bool IsCameraRotate(CameraCalcInfo newInfo)
protected bool IsCameraRotate(PtzInfo newInfo)
{
return CameraCalcInfo == null ||
CameraCalcInfo.PtzInfo.Pan != newInfo.PtzInfo.Pan ||
CameraCalcInfo.PtzInfo.Tilt != newInfo.PtzInfo.Tilt ||
CameraCalcInfo.PtzInfo.Zoom != newInfo.PtzInfo.Zoom;
return _cameraCalcInfo.PtzInfo.Pan != newInfo.Pan ||
_cameraCalcInfo.PtzInfo.Tilt != newInfo.Tilt ||
_cameraCalcInfo.PtzInfo.Zoom != newInfo.Zoom;
}
/// <summary>
@ -204,4 +194,39 @@ public abstract class MarkSearcherBase
protected abstract PointF GetFOfMatrixByZoomPos(double zoomPos);
#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();
}
public RequestRealControl GetPtzInfo(int cameraId)
public RequestRealControl GetPtzRrc(int cameraId)
{
RequestRealControl realControl = new();
try
@ -54,6 +54,13 @@ public class PtzServerApi : IPtzApi, ISingleton
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)
{
//获取结构体大小

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

@ -13,10 +13,29 @@ public class CameraDataCenter
private readonly SqlSugarRepository<CmMarkLabel> _cmMarkLableRep;
private readonly SqlSugarRepository<TbPtzCamera> _tbPtzCameraRep;
private readonly PtzServerApi _ptzServerApi;
private readonly CameraDataOptions options = App.GetOptions<CameraDataOptions>();
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
@ -31,29 +50,16 @@ public class CameraDataCenter
private void Init()
{
// 初始化 tbPtzCameraList
_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)
if (!options.LazyInit)
{
IsBackground = true// 设置后台线程
};
_thread.Start();
}
private void LazyInit()
{
// 初始化 tbPtzCameraList
_tbPtzCameraList = new();
// 初始化 ptzInfoDict
_cameraPtzInfoDict = new ConcurrentDictionary<string, CameraCalcInfo>();
List<TbPtzCamera> list = _tbPtzCameraRep.GetList();
// 根据 Ip 去重
foreach (TbPtzCamera item in list)
{
if (!_tbPtzCameraDict.ContainsKey(item.Ip))
_tbPtzCameraDict[item.Ip] = item;
}
}
// 初始化 thread
_thread = new Thread(WorkLoop)
@ -65,47 +71,100 @@ public class CameraDataCenter
#region Loop
/// <summary>
/// 循环运行
/// </summary>
private void WorkLoop()
{
while (true)
{
GetPtzInfoByApi();
Thread.Sleep(10000);
RefreshPtzInfoByApi();
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);
CameraCalcInfo ptzInfo = new()
{
Pan = rrc.PTZPositionInfo.FP,
Tilt = rrc.PTZPositionInfo.FT,
Zoom = rrc.PTZPositionInfo.FZ
};
PtzInfo ptzInfo = _ptzServerApi.GetPtzInfo(item.CameraId);
_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
#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;
}

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

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

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

@ -5,6 +5,11 @@
/// </summary>
public class CameraCalcInfo
{
/// <summary>
/// Camera Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// Ptz 信息
/// </summary>
@ -26,6 +31,15 @@ public class CameraCalcInfo
public double MinFocusX { get; set; } = 0f;
public double MinFocusY { get; set; } = 0f;
public static CameraCalcInfo New(long id, PtzInfo ptzInfo)
{
return new()
{
Id = id,
PtzInfo = ptzInfo
};
}
}
/// <summary>
@ -47,6 +61,16 @@ public class PtzInfo
/// Zoom 坐标
/// </summary>
public double Zoom { get; set; }
public static PtzInfo New(double pan, double tilt, double zoom)
{
return new()
{
Pan = pan,
Tilt = tilt,
Zoom = zoom
};
}
}
/// <summary>
@ -54,6 +78,11 @@ public class PtzInfo
/// </summary>
public class MarkLabelCalcInfo
{
/// <summary>
/// MarkLabel Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// Ptz 信息
/// </summary>
@ -78,6 +107,19 @@ public class MarkLabelCalcInfo
/// 画布 top 距离
/// </summary>
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>
@ -85,6 +127,11 @@ public class MarkLabelCalcInfo
/// </summary>
public class MarkLabelCalcResult
{
/// <summary>
/// MarkLabel Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// true 显示(在当前视频画面里面)
/// false 不显示(不在当前视频画面里面)
@ -101,4 +148,23 @@ public class MarkLabelCalcResult
/// </summary>
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>
public void ConfigureServices(IServiceCollection services)
{
services.AddConfigurableOptions<CameraDataOptions>();
services.AddConfigurableOptions<PtzServerOptions>();
services.AddSingleton<CameraDataCenter>(new CameraDataCenter());

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

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cis.Application.Tb;
namespace Cis.Application.Tb;
public class TbInfo
{
@ -25,5 +19,4 @@ public class TbInfo
public const string TbPtzCameraTbName = "tb_ptzcamera";
#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 = "")
{
JObject queryObj = !string.IsNullOrEmpty(queryJson) ? queryJson.ToJObject():default;
JObject queryObj = !string.IsNullOrEmpty(queryJson) ? queryJson.ToJObject() : default;
List<TbPtzCamera> list = await _tbPtzCameraRep.AsQueryable()
.ToListAsync();
return list;

7
Cis.Core/CoreConfig.json

@ -21,14 +21,9 @@
]
},
"Cache": {
"CacheType": "Redis", // MemoryRedis
"CacheType": "Memory", // MemoryRedis
"RedisConnectionString": "127.0.0.1:6379;password=123456;db=2"
},
"PTZServer": {
"Type": "",
"Ip": "127.0.0.1",
"Port": "7022"
},
"AppSettings": {
"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);
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