《球机隐私遮蔽定位解析及ONVIF实现》


隐私遮蔽

  • 高速球摄像机实现隐私区域遮蔽
  • 隐私区域自由选取
  • 无论相机处于什么状态,遮蔽块能随着球机移动而移动
  • 球机在不同位姿下的图像点坐标的实时匹配

原理推导

  • 目前两种思路:一种是按照3D定位原理匹配;一种是利用共同世界坐标的单应变换;

  • 球机坐标转换关系推导一下,理论验证通过,实用的话暂时没想好方法;

  • 3D定位原理类似,参照《球机3D定位解析及ONVIF实现》

单应变换思路

  • 可以转化为球机在旋转或变倍过程中的,不同位姿下的图像坐标匹配关系推导如下

  • 可以参考《单应性变换-Homography》

  • 相机1时刻,图像坐标和相对世界坐标转换关系
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RehaWO19-1629730750376)(file:///C:/Users/VOILEN~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png)]

  • 相机2时刻,图像坐标和相对世界坐标转换关系
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IJxv8pNK-1629730750378)(file:///C:/Users/VOILEN~1/AppData/Local/Temp/msohtmlclip1/01/clip_image004.png)]

  • 将(1)式代入(2)式,可得

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dHT5ODtZ-1629730750379)(file:///C:/Users/VOILEN~1/AppData/Local/Temp/msohtmlclip1/01/clip_image006.png)]

  • 化简,得

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1uGWB9qM-1629730750380)(file:///C:/Users/VOILEN~1/AppData/Local/Temp/msohtmlclip1/01/clip_image008.png)]

式中,在这里插入图片描述

  • 求解,可得

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GAg0aYZA-1629730750383)(file:///C:/Users/VOILEN~1/AppData/Local/Temp/msohtmlclip1/01/clip_image014.png)]

  • 球机在不同位姿下的转换,需要内参矩阵(标定可得)、旋转和平移矩阵(球机的PTZ轴不在透镜中心,所以根据PTZ的变化,无法获知旋转和平移矩阵)

3D定位思路

  • 示意图如下,目标点在球机两个不同位姿下的图像坐标P1P2

  • 先计算 P 1 P_1 P1到视野中心点,球机旋转的水平和垂直角度

{ α V : 1 − > o = a r c t a n ( Y 1 − H / 2 H / 2 ∗ t a n ( F O V v / 2 ) ) α H : 1 − > o = a r c t a n ( X 1 − W / 2 W / 2 ∗ t a n ( F O V h / 2 ) ) \begin{cases} \alpha_{V:1->o}=arctan(\frac{Y_1-H/2}{H/2}*tan(FOV_v/2)) \\ \alpha_{H:1->o}=arctan(\frac{X_1-W/2}{W/2}*tan(FOV_h/2)) \end{cases} {αV:1>o=arctan(H/2Y1H/2tan(FOVv/2))αH:1>o=arctan(W/2X1W/2tan(FOVh/2))

  • 利用球机在1和2时刻的PTZ坐标,计算 P 1 P_1 P1 P 2 P_2 P2的水平和垂直角度

{ α V : 1 − > 2 = T i l t 2 − T i l t 1 α H : 1 − > 2 = P a n 2 − P a n 1 \begin{cases} \alpha_{V:1->2} = Tilt_2-Tilt_1\\ \alpha_{H:1->2} = Pan_2-Pan_1\\ \end{cases} {αV:1>2=Tilt2Tilt1αH:1>2=Pan2Pan1

  • 计算 P 2 P_2 P2到视野中心点,球机旋转的水平和垂直角度

{ α V : 2 − > o = α V : 1 − > o − α V : 1 − > 2 α H : 2 − > o = α H : 1 − > o − α H : 1 − > 2 \begin{cases} \alpha_{V:2->o}= \alpha_{V:1->o}-\alpha_{V:1->2}\\ \alpha_{H:2->o}= \alpha_{H:1->o}-\alpha_{H:1->2} \end{cases} {αV:2>o=αV:1>oαV:1>2αH:2>o=αH:1>oαH:1>2

  • 计算 P 2 P_2 P2点的图像坐标

{ Y 2 = t a n ( α V : 2 − > o ) t a n ( F O V v / 2 ) ∗ H 2 + H 2 X 2 = t a n ( α H : 2 − > o ) t a n ( F O V h / 2 ) ∗ W 2 + W 2 \begin{cases} Y_2 = \frac{tan(\alpha_{V:2->o})}{tan(FOV_v/2)}*\frac{H}{2} + \frac{H}{2} \\ X_2 = \frac{tan(\alpha_{H:2->o})}{tan(FOV_h/2)}*\frac{W}{2} + \frac{W}{2} \end{cases} {Y2=tan(FOVv/2)tan(αV:2>o)2H+2HX2=tan(FOVh/2)tan(αH:2>o)2W+2W

实现

请添加图片描述

  • 隐私遮蔽实现主函数:privacy_shelter.py
class shelter:
    def __init__(self, width, height, fov_h, fov_v, pos_onvif1, rect):
        self.width = width
        self.height = height
        self.fov_h = fov_h
        self.fov_v = fov_v
        self.pos_sdk1 = self.ptz_to_sdk(pos_onvif1)
        self.rect = rect # l,t,r,b

    def ptz_to_sdk(self, pos_onvif):
        p_ = min(180 * pos_onvif['pan'] + 180, 360)
        t_ = 45 * pos_onvif['tilt'] + 45
        z_ = 3 * pos_onvif['zoom'] + 1
        return {'pan' :p_, 'tilt' :t_, 'zoom' :z_}

    def ptz_to_onvif(self, pos_sdk):
        p_ = (pos_sdk['pan'] - 180) / 180
        t_ = (pos_sdk['tilt'] - 45) / 45
        z_ = (pos_sdk['zoom'] - 1) / 3
        return {'pan' :p_, 'tilt' :t_, 'zoom' :z_}

    def locate(self, target):
        x, y = target
        # 水平方向
        delt_x = np.rad2deg( np.arctan((x - self.width / 2) / (self.width / 2) * np.tan( np.deg2rad(self.fov_h /2))) )
        # 垂直方向
        delt_y = np.rad2deg( np.arctan((y - self.height / 2) / (self.height / 2) * np.tan( np.deg2rad(self.fov_v / 2))) )
        return [delt_x, delt_y]

    def match_point(self, point, pos_onvif2):
        delt_x0, delt_y0 = self.locate(point)
        pos_sdk2 = self.ptz_to_sdk(pos_onvif2)
        delt_pos_sdk = [pos_sdk2['pan'] - self.pos_sdk1['pan'], pos_sdk2['tilt'] - self.pos_sdk1['tilt']]
        delt_x2 = delt_x0 - delt_pos_sdk[0]
        delt_y2 = delt_y0 + delt_pos_sdk[1]
        x2 = np.tan(np.deg2rad(delt_x2)) / np.tan(np.deg2rad(self.fov_h / 2)) * self.width / 2 + self.width / 2
        y2 = np.tan(np.deg2rad(delt_y2)) / np.tan(np.deg2rad(self.fov_v / 2)) * self.height / 2 + self.height / 2
        return [x2, y2]

    def match(self, pos_onvif2):
        l2, t2 = self.match_point([self.rect[0], self.rect[1]], pos_onvif2)
        r2, b2 = self.match_point([self.rect[2], self.rect[3]], pos_onvif2)
        return [int(l2), int(t2), int(r2), int(b2)]

参考链接

  1. 单应性变换-Homography
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值