海康球机控制函数VC (PTZ控制+对准具体坐标点)

    控制球机光轴运动到具体坐标的两种方式:设置PTZ参数方法、调用球机3D定位功能。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

【设置PTZ参数方法】

主要利用两个函数:设置参数NET_DVR_SetDVRConfig函数与读取参数NET_DVR_GetDVRConfig函数。

NET_DVR_SetDVRConfig(LONG lUserID, DWORD dwCommand,LONG lChannel, LPVOID lpInBuffer, DWORD dwInBufferSize);

NET_DVR_GetDVRConfig(LONG lUserID, DWORD dwCommand,LONG lChannel, LPVOID lpOutBuffer, DWORD dwOutBufferSize, LPDWORD lpBytesReturned);

 

函数示例:

1.位置坐标转换为角度+进制转换+设置参数

//PTZ参数求取
focus_adjust = 10;//焦距

y_degree = (target_y - std_rows / 2.0) > 0 ? -atan(-(std_rows / 2.0 - target_y) / (std_rows / 2) * tan(21.8 / 180 * PI)) * 180 / PI : atan(-(target_y - std_rows / 2.0) / (std_rows / 2) * tan(21.8 / 180 * PI)) * 180 / PI;

z_degree = ((target_x - std_cols / 2.0) > 0) ? atan((target_x - std_cols / 2.0) / (std_cols / 2) * tan(29.15 / 180 * PI)) * 180 / PI : (360 - atan((std_cols / 2.0 - target_x) / (std_cols / 2) * tan(29.15 / 180 * PI)) * 180 / PI);
		
z_degree = ((z_degree < 100) ? -z_degree : 360 - z_degree);

z_degree += 279;//补上球机初始角度
y_degree += 10;//补上球机初始角度

NET_DVR_PTZPOS m_ptzPos;
		
m_ptzPos.wAction = 1;
int z_idegree = z_degree * 10;
int y_idegree = y_degree * 10;
//进制转换
m_ptzPos.wPanPos = DEC2HEX_doc(z_idegree);
m_ptzPos.wTiltPos = DEC2HEX_doc(y_idegree);
m_ptzPos.wZoomPos = DEC2HEX_doc(focus_adjust);
//设置PTZ参数
if (!NET_DVR_SetDVRConfig(0, NET_DVR_SET_PTZPOS, 0, &m_ptzPos, sizeof(NET_DVR_PTZPOS))){
			auto a = NET_DVR_GetLastError();
			CString s; 
			s.Format("%d", a);
			AfxMessageBox(s);
		}

2.实时读取球机PTZ参数+判断是否完成设置

//判断是否完成移动
	NET_DVR_PTZPOS Pos_judge;
	Pos_judge.wAction = 1;
	DWORD tmp = 0;
	int flags_tmp=1;
	while (flags_tmp)
	{
		if (!NET_DVR_GetDVRConfig(0, NET_DVR_GET_PTZPOS, 0, &Pos_judge, sizeof(NET_DVR_PTZPOS), &tmp))
		{
			auto a = NET_DVR_GetLastError();
			CString s;
			s.Format("%d", a);
			AfxMessageBox(s);
		}
		else if(Pos_judge.wPanPos == m_ptzPos.wPanPos && Pos_judge.wTiltPos == m_ptzPos.wTiltPos && Pos_judge.wZoomPos == m_ptzPos.wZoomPos)
		{
			flags_tmp = 0;
		}
	}

备注:设置PTZ参数是一个并行过程,如果不加入结束判断,读取球机画面时将不是所设定参数状态下的图片,而是PTZ调整过程中的某一张图片。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

【调用球机3D定位功能】

主要包括两个函数:NET_DVR_PTZSelZoomIn与NET_DVR_PTZSelZoomIn_EX,两个参数不同但功能一样。

NET_DVR_PTZSelZoomIn(LONG lRealHandle, LPNET_DVR_POINT_FRAME pStruPointFrame);
NET_DVR_PTZSelZoomIn_EX(LONG lUserID, LONG lChannel, LPNET_DVR_POINT_FRAME pStruPointFrame);

参数介绍:

[in]lRealHandle                         NET_DVR_RealPlay或者NET_DVR_RealPlay_V30的返回值
[in]pStruPointFrame                 云台图像区域位置信息

[in]lUserID                                NET_DVR_Login_V40 的返回值
[in]lChannel                              通道号
[in]pStruPointFrame                 云台图像区域位置信息
 

//NET_DVR_POINT_FRAME
//云台图像区域位置信息。

struct{
  int    xTop;
  int    yTop;
  int    xBottom;
  int    yBottom;
  int    bCounter;
}NET_DVR_POINT_FRAME, *LPNET_DVR_POINT_FRAME;
Members
//xTop 方框起始点的x坐标 
//yTop 方框起始点的y坐标 
//xBottom 方框结束点的x坐标 
//yBottom 方框结束点的y坐标 
//bCounter 保留 



返回值: TRUE 表示成功,FALSE 表示失败。接口返回失败请调用NET_DVR_GetLastError 获取错误码,通
过错误码判断出错原因。


功能说明:该结构体中的坐标值与当前预览显示框的大小有关,现假设预览显示框为352*288,我们规定原点为预览显示框左上角的顶点,前四个参数计算方法如下:
xTop = 鼠标当前所选区域的起始点坐标的值*255/352;
xBottom = 鼠标当前所选区域的结束点坐标的值*255/352;
yTop = 鼠标当前所选区域的起始点坐标的值*255/288;
yBottom = 鼠标当前所选区域的结束点坐标的值*255/288;
缩小条件:xTop减去xBottom的值大于2。放大条件:xTop小于xBottom。

函数示例:

NET_DVR_POINT_FRAME  posdata;
	
posdata.xTop = (int)(target_tmp.x * 255 / std_cols );
	
posdata.xBottom = posdata.xTop ;// (int)((target_tmp.x + target_tmp.width) / std_cols * 255);
	
posdata. yTop = (int)(target_tmp.y * 255 / std_rows);

posdata.yBottom = posdata.yTop  ;// (int)((target_tmp.y + target_tmp.height) / std_rows * 255);

posdata.bCounter = 1;

if (!NET_DVR_PTZSelZoomIn_EX(0, 1, &posdata)){
	auto a = NET_DVR_GetLastError();
	CString s;
	s.Format("%d", a);
	AfxMessageBox(s);
}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

【总结】

第一种方法某种意义上是第二种方法的开源版本,但坐标到角度的转换方法因人而异,误差也因人而异;而自带的3D功能坐标对准十分准确,效果很好,但这同样是一个并行过程,同时还不知道函数内部具体参数值,不能有效判断结束标志,所以为后续指令操作带来一个时间上的问题。

倘若大家有更好的球机对准方法,欢迎交流讨论。

如若有以下两个函数的开源代码,望大家能够分享,一起学习。

(NET_DVR_PTZSelZoomIn与NET_DVR_PTZSelZoomIn_EX)

  • 12
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 36
    评论
type TShowStr = record X: Word; Y: Word; S: array [0 .. 43] of AnsiChar; end; type TCamera = record pHWND: HWND; strict private aCam: LongInt; g_nPort: LongInt; struDeviceInfo: NET_DVR_DEVICEINFO_V30; lRealHandle: LongInt; struPlayInfo: NET_DVR_CLIENTINFO; pUser: Pointer; dwRet: Integer; public property ErrCode: Integer read dwRet; procedure HCLogin(IP, User, Psd: String; Port: Word); procedure HCPlay(aHWND: HWND); procedure HCAddChar(str: TArray); procedure HCAddChar_V30(str: TArray); function HCGetJpeg(JpgName: String; JpgSize: Word = 0; JpgQua: Word = 19): Boolean; procedure HCStop; procedure HCLogout; end; {$ENDIF //} implementation procedure TCamera.HCLogin(IP, User, Psd: String; Port: Word); begin NET_DVR_Init(); lRealHandle := -1; dwRet := 0; aCam := NET_DVR_Login_V30(PAnsiChar(ansistring(IP)), Port, PAnsiChar(ansistring(User)), PAnsiChar(ansistring(Psd)), @struDeviceInfo); dwRet := NET_DVR_GetLastError; end; procedure TCamera.HCPlay(aHWND: HWND); begin struPlayInfo.lChannel := 1; struPlayInfo.lLinkMode := 0; struPlayInfo.sMultiCastIP := NIL; struPlayInfo.hPlayWnd := aHWND; lRealHandle := NET_DVR_RealPlay_V30(aCam, @struPlayInfo, nil, pUser, true); dwRet := NET_DVR_GetLastError; end; procedure TCamera.HCAddChar(str: TArray); var i: Integer; aStr: NET_DVR_SHOWSTRING; begin if length(str) > MAX_STRINGNUM then begin setlength(str, MAX_STRINGNUM); end; for i := 0 to length(str) - 1 do begin aStr.struStringInfo[i].wShowString := 1; aStr.struStringInfo[i].wStringSize := length(str[i].S); aStr.struStringInfo[i].wShowStringTopLeftX := str[i].X; aStr.struStringInfo[i].wShowStringTopLeftY := str[i].Y; move(str[i].S[0], aStr.struStringInfo[i].sString[0], length(str[i].S)); end; aStr.dwSize := sizeof(aStr); NET_DVR_SetDVRConfig(aCam, NET_DVR_SET_SHOWSTRING, 1, @aStr, sizeof(NET_DVR_SHOWSTRING)); dwRet := NET_DVR_GetLastError; end; procedure TCamera.HCAddChar_V30(str: TArray); var i: Integer; aStr: NET_DVR_SHOWSTRING_V30; begin if length(str) > MAX_STRINGNUM_V30 then begin setlength(str, MAX_STRINGNUM_V30); end; for i := 0 to length(str) - 1 do begin aStr.struStringInfo[i].wShowString := 1; aStr.struStringInfo[i].wStringSize := length(str[i].S); aStr.struStringInfo[i].wShowStringTopLeftX := str[i].X; aStr.struStringInfo[i].wShowStringTopLeftY := str[i].Y; move(str[i].S[0], aStr.struStringInfo[i].sString[0], length(str[i].S)); end; aStr.dwSize := sizeof(aStr); NET_DVR_SetDVRConfig(aCam, NET_DVR_SET_SHOWSTRING_V30, 1, @aStr, sizeof(NET_DVR_SET_SHOWSTRING_V30)); dwRet := NET_DVR_GetLastError; end; function TCamera.HCGetJpeg(JpgName: String; JpgSize: Word = 0; JpgQua: Word = 19): Boolean; var aJpg: NET_DVR_JPEGPARA; begin aJpg.wPicSize := JpgSize; aJpg.wPicQuality := JpgQua; if aCam >= 0 then begin result := NET_DVR_CaptureJPEGPicture(aCam, 1, aJpg, PAnsiChar(ansistring(JpgName))); dwRet := NET_DVR_GetLastError(); end else result := false; dwRet := NET_DVR_GetLastError; end; procedure TCamera.HCStop; begin if lRealHandle >= 0 then begin NET_DVR_StopRealPlay(lRealHandle); lRealHandle := -1; end; PlayM4_CloseStream(g_nPort); PlayM4_FreePort(g_nPort); end; procedure TCamera.HCLogout; begin if lRealHandle > -1 then begin HCStop; end; if aCam >= 0 then begin NET_DVR_Logout_V30(aCam); aCam := -1; end; NET_DVR_Cleanup(); end;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值