代码链接
参考库链接:
目录
本文将介绍如何调用onvif协议的接口,来实现代码控制海康相机云台转动,查询的大多数代码是使用C++来实现,感觉有点复杂,本文直接采用python接口来实现。C版本的请查看ONVIF系列——c++使用gsoap onvif编写onvif代码并控制海康摄像头
1 安装python-onvif
1.1 pip安装
python官方已经提供了onvif
包的安装,因此可直接通过pip来安装,如下
pip2 install onvif
要注意这里pip必须对应python2,如果对应是python3可能会有问题,因此为了避免这种问题,建议采用如下的源码安装
1.2 源码安装
git clone https://github.com/quatanium/python-onvif
cd python-onvif
python2 setup.py install
1.3 安装测试
安装成功后,运行python2,输入以下语句,不报错即安装成功
from onvif import ONVIFCamera
2 连续运动(python2版本)
在python-onvif
安装包中,有examples
文件夹,其中有个continuous_move.py
文件,代码如下
from time import sleep
from onvif import ONVIFCamera
XMAX = 1
XMIN = -1
YMAX = 1
YMIN = -1
def perform_move(ptz, request, timeout):
# Start continuous move
ptz.ContinuousMove(request)
# Wait a certain time
sleep(timeout)
# Stop continuous move
ptz.Stop({'ProfileToken': request.ProfileToken})
def move_up(ptz, request, timeout=1):
print 'move up...'
request.Velocity.PanTilt._x = 0
request.Velocity.PanTilt._y = YMAX
perform_move(ptz, request, timeout)
def move_down(ptz, request, timeout=1):
print 'move down...'
request.Velocity.PanTilt._x = 0
request.Velocity.PanTilt._y = YMIN
perform_move(ptz, request, timeout)
def move_right(ptz, request, timeout=1):
print 'move right...'
request.Velocity.PanTilt._x = XMAX
request.Velocity.PanTilt._y = 0
perform_move(ptz, request, timeout)
def move_left(ptz, request, timeout=1):
print 'move left...'
request.Velocity.PanTilt._x = XMIN
request.Velocity.PanTilt._y = 0
perform_move(ptz, request, timeout)
def continuous_move():
mycam = ONVIFCamera('192.168.0.112', 80, 'admin', '12345')
# Create media service object
media = mycam.create_media_service()
# Create ptz service object
ptz = mycam.create_ptz_service()
# Get target profile
media_profile = media.GetProfiles()[0]
# Get PTZ configuration options for getting continuous move range
request = ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = media_profile.PTZConfiguration._token
ptz_configuration_options = ptz.GetConfigurationOptions(request)
request = ptz.create_type('ContinuousMove')
request.ProfileToken = media_profile._token
ptz.Stop({'ProfileToken': media_profile._token})
# Get range of pan and tilt
# NOTE: X and Y are velocity vector
global XMAX, XMIN, YMAX, YMIN
XMAX = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].XRange.Max
XMIN = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].XRange.Min
YMAX = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].YRange.Max
YMIN = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].YRange.Min
# move right
move_right(ptz, request)
# move left
move_left(ptz, request)
# Move up
move_up(ptz, request)
# move down
move_down(ptz, request)
if __name__ == '__main__':
continuous_move()
将第43
行函数里的IP、用户名、密码修改为自己相机的参数,比如我的相机参数如下
mycam = ONVIFCamera('192.168.170.*', 80, 'admin', '**')
然后运行python2 continuous_move.py
,相机云台即可分别实现右左上下运动,参考此代码我们便可以编写我们自己的运动控制程序
3 连续运动(python3版本)
Python3版本安装方法如下
pip3 install --upgrade onvif_zeep
连续运动代码
from time import sleep
from onvif import ONVIFCamera
import zeep
XMAX = 1
XMIN = -1
YMAX = 1
YMIN = -1
def zeep_pythonvalue(self, xmlvalue):
return xmlvalue
def perform_move(ptz, request, timeout):
# Start continuous move
ptz.ContinuousMove(request)
# Wait a certain time
sleep(timeout)
# Stop continuous move
ptz.Stop({'ProfileToken': request.ProfileToken})
def move_up(ptz, request, timeout=1):
print('move up...')
request.Velocity.PanTilt.x = 0
request.Velocity.PanTilt.y = YMAX
perform_move(ptz, request, timeout)
def move_down(ptz, request, timeout=1):
print('move down...')
request.Velocity.PanTilt.x = 0
request.Velocity.PanTilt.y = YMIN
perform_move(ptz, request, timeout)
def move_right(ptz, request, timeout=1):
print('move right...')
request.Velocity.PanTilt.x = XMAX
request.Velocity.PanTilt.y = 0
perform_move(ptz, request, timeout)
def move_left(ptz, request, timeout=1):
print('move left...')
request.Velocity.PanTilt.x = XMIN
request.Velocity.PanTilt.y = 0
perform_move(ptz, request, timeout)
def continuous_move():
mycam = ONVIFCamera('192.168.170.**', 80, 'admin', '**')
# Create media service object
media = mycam.create_media_service()
# Create ptz service object
ptz = mycam.create_ptz_service()
# Get target profile
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
media_profile = media.GetProfiles()[0]
# Get PTZ configuration options for getting continuous move range
request = ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = media_profile.PTZConfiguration.token
ptz_configuration_options = ptz.GetConfigurationOptions(request)
request = ptz.create_type('ContinuousMove')
request.ProfileToken = media_profile.token
ptz.Stop({'ProfileToken': media_profile.token})
if request.Velocity is None:
request.Velocity = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
request.Velocity = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
request.Velocity.PanTilt.space = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].URI
request.Velocity.Zoom.space = ptz_configuration_options.Spaces.ContinuousZoomVelocitySpace[0].URI
# Get range of pan and tilt
# NOTE: X and Y are velocity vector
global XMAX, XMIN, YMAX, YMIN
XMAX = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].XRange.Max
XMIN = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].XRange.Min
YMAX = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].YRange.Max
YMIN = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].YRange.Min
# move right
move_right(ptz, request)
# move left
move_left(ptz, request)
# Move up
move_up(ptz, request)
# move down
move_down(ptz, request)
if __name__ == '__main__':
continuous_move()
4 绝对运动(python3版本)
仿照连续运动的实例,结合onvif
协议,可以写绝对运动的控制程序
from time import sleep
from onvif import ONVIFCamera
import zeep
XMAX = 1
XMIN = -1
YMAX = 1
YMIN = -1
def zeep_pythonvalue(self, xmlvalue):
return xmlvalue
def perform_move(ptz, request, timeout):
# Start continuous move
ptz.ContinuousMove(request)
# Wait a certain time
sleep(timeout)
# Stop continuous move
ptz.Stop({'ProfileToken': request.ProfileToken})
def absolute_move():
pan = 0
pan_speed = 1
tilt = 0
tilt_speed = 1
zoom = 1
zoom_speed = 1
mycam = ONVIFCamera('192.168.170.**', 80, 'admin', '**')
# Create media service object
media = mycam.create_media_service()
# Create ptz service object
ptz = mycam.create_ptz_service()
# Get target profile
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
media_profile = media.GetProfiles()[0]
# Get PTZ configuration options for getting absolute move range
request = ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = media_profile.PTZConfiguration.token
# ptz_configuration_options = ptz.GetConfigurationOptions(request)
request = ptz.create_type('AbsoluteMove')
request.ProfileToken = media_profile.token
ptz.Stop({'ProfileToken': media_profile.token})
if request.Position is None:
request.Position = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
if request.Speed is None:
request.Speed = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
request.Position.PanTilt.x = pan
request.Speed.PanTilt.x = pan_speed
request.Position.PanTilt.y = tilt
request.Speed.PanTilt.y = tilt_speed
request.Position.Zoom = zoom
request.Speed.Zoom = zoom_speed
ptz.AbsoluteMove(request)
print('finish')
if __name__ == '__main__':
absolute_move()
5 不同的连续运动(python3版本)
# -*- coding: utf-8 -*-
# @Time : 2021/4/20 10:53
# @Author : RichardoMu
# @File : move.py
# @Software: PyCharm
from time import sleep
from onvif import ONVIFCamera
import zeep
XMAX = 1
XMIN = -1
YMAX = 1
YMIN = -1
def zeep_pythonvalue(self, xmlvalue):
return xmlvalue
def perform_move(ptz, request, timeout):
# Start continuous move
ptz.ContinuousMove(request)
# Wait a certain time
sleep(timeout)
# Stop continuous move
ptz.Stop({'ProfileToken': request.ProfileToken})
def move_up(ptz, request, timeout=1):
print('move up...')
request.Velocity.PanTilt.x = 0
request.Velocity.PanTilt.y = YMAX
perform_move(ptz, request, timeout)
def move_down(ptz, request, timeout=1):
print('move down...')
request.Velocity.PanTilt.x = 0
request.Velocity.PanTilt.y = YMIN
perform_move(ptz, request, timeout)
def move_right(ptz, request, timeout=1):
print('move right...')
request.Velocity.PanTilt.x = XMAX
request.Velocity.PanTilt.y = 0
perform_move(ptz, request, timeout)
def move_left(ptz, request, timeout=1):
print('move left...')
request.Velocity.PanTilt.x = XMIN
request.Velocity.PanTilt.y = 0
perform_move(ptz, request, timeout)
def zoom_up(ptz,request,timeout=1):
print('zoom up')
request.Velocity.Zoom.x = 1
request.Velocity.PanTilt.x = 0
request.Velocity.PanTilt.y = 0
perform_move(ptz,request,timeout)
def zoom_dowm(ptz,request,timeout=1):
print('zoom down')
request.Velocity.Zoom.x = -1
request.Velocity.PanTilt.x = 0
request.Velocity.PanTilt.y = 0
perform_move(ptz, request, timeout)
def continuous_move():
mycam = ONVIFCamera('192.168.66.64', 80, 'admin', 'wst123456')
# Create media service object
media = mycam.create_media_service()
# Create ptz service object
ptz = mycam.create_ptz_service()
# Get target profile
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
media_profile = media.GetProfiles()[0]
# Get PTZ configuration options for getting continuous move range
request = ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = media_profile.PTZConfiguration.token
ptz_configuration_options = ptz.GetConfigurationOptions(request)
request = ptz.create_type('ContinuousMove')
request.ProfileToken = media_profile.token
ptz.Stop({'ProfileToken': media_profile.token})
if request.Velocity is None:
request.Velocity = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
request.Velocity = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
request.Velocity.PanTilt.space = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].URI
request.Velocity.Zoom.space = ptz_configuration_options.Spaces.ContinuousZoomVelocitySpace[0].URI
# Get range of pan and tilt
# NOTE: X and Y are velocity vector
global XMAX, XMIN, YMAX, YMIN
XMAX = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].XRange.Max
XMIN = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].XRange.Min
YMAX = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].YRange.Max
YMIN = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].YRange.Min
for i in range(10):
zoom_up(ptz,request)
for i in range(10):
zoom_dowm(ptz,request)
# move right
for i in range(10):
move_right(ptz, request)
# move left
for i in range(10):
move_left(ptz, request)
# Move up
for i in range(10):
move_up(ptz, request)
# move down
for i in range(10):
move_down(ptz, request)
if __name__ == '__main__':
continuous_move()
6 获取预置位和到设定预置位等操作(python3版本)
# -*- coding: utf-8 -*-
# @Time : 2021/4/20 14:57
# @Author : RichardoMu
# @File : ptz_control.py
# @Software: PyCharm
import sys
from onvif import ONVIFCamera
from time import sleep
IP = "192.168.66.64" # Camera IP address
PORT = 80 # Port
USER = "admin" # Username
PASS = "wst123456" # Password
class ptzControl(object):
def __init__(self):
super(ptzControl, self).__init__()
self.mycam = ONVIFCamera(IP,PORT,USER,PASS)
# create media service object
self.media = self.mycam.create_media_service()
# Get target profile
self.media_profile = self.media.GetProfiles()[0]
# Use the first profile and Profiles have at least one
token = self.media_profile.token
# PTZ controls -------------------------------------------------------------
self.ptz = self.mycam.create_ptz_service()
# Get available PTZ services
request = self.ptz.create_type('GetServiceCapabilities')
Service_Capabilities = self.ptz.GetServiceCapabilities(request)
# Get PTZ status
status = self.ptz.GetStatus({'ProfileToken': token})
# Get PTZ configuration options for getting option ranges
request = self.ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = self.media_profile.PTZConfiguration.token
ptz_configuration_options = self.ptz.GetConfigurationOptions(request)
# get continuousMove request -- requestc
self.requestc = self.ptz.create_type('ContinuousMove')
self.requestc.ProfileToken = self.media_profile.token
if self.requestc.Velocity is None:
self.requestc.Velocity = self.ptz.GetStatus({'ProfileToken': self.media_profile.token}).Position
self.requestc.Velocity.PanTilt.space = ptz_configuration_options.Spaces.ContinuousPanTiltVelocitySpace[0].URI
self.requestc.Velocity.Zoom.space = ptz_configuration_options.Spaces.ContinuousZoomVelocitySpace[0].URI
# get absoluteMove request -- requesta
self.requesta = self.ptz.create_type('AbsoluteMove')
self.requesta.ProfileToken = self.media_profile.token
if self.requesta.Position is None:
self.requesta.Position = self.ptz.GetStatus(
{'ProfileToken': self.media_profile.token}).Position
if self.requesta.Speed is None:
self.requesta.Speed = self.ptz.GetStatus(
{'ProfileToken': self.media_profile.token}).Position
# get relativeMove request -- requestr
self.requestr = self.ptz.create_type('RelativeMove')
self.requestr.ProfileToken = self.media_profile.token
if self.requestr.Translation is None:
self.requestr.Translation = self.ptz.GetStatus(
{'ProfileToken': self.media_profile.token}).Position
self.requestr.Translation.PanTilt.space = ptz_configuration_options.Spaces.RelativePanTiltTranslationSpace[0].URI
self.requestr.Translation.Zoom.space = ptz_configuration_options.Spaces.RelativeZoomTranslationSpace[0].URI
if self.requestr.Speed is None:
self.requestr.Speed = self.ptz.GetStatus(
{'ProfileToken': self.media_profile.token}).Position
self.requests = self.ptz.create_type('Stop')
self.requests.ProfileToken = self.media_profile.token
self.requestp = self.ptz.create_type('SetPreset')
self.requestp.ProfileToken = self.media_profile.token
self.requestg = self.ptz.create_type('GotoPreset')
self.requestg.ProfileToken = self.media_profile.token
self.stop()
# Stop pan, tilt and zoom
def stop(self):
self.requests.PanTilt = True
self.requests.Zoom = True
print(f"self.request:{self.requests}")
self.ptz.Stop(self.requests)
# Continuous move functions
def perform_move(self, requestc):
# Start continuous move
ret = self.ptz.ContinuousMove(requestc)
def move_tilt(self, velocity):
self.requestc.Velocity.PanTilt.x = 0.0
self.requestc.Velocity.PanTilt.y = velocity
self.perform_move(self.requestc)
def move_pan(self, velocity):
self.requestc.Velocity.PanTilt.x = velocity
self.requestc.Velocity.PanTilt.y = 0.0
self.perform_move(self.requestc)
def move_continuous(self, pan, tilt):
self.requestc.Velocity.PanTilt.x = pan
self.requestc.Velocity.PanTilt.y = tilt
self.perform_move(self.requestc)
def zoom(self, velocity):
self.requestc.Velocity.Zoom.x = velocity
self.perform_move(self.requestc)
# Absolute move functions --NO ERRORS BUT CAMERA DOES NOT MOVE
def move_abspantilt(self, pan, tilt, velocity):
self.requesta.Position.PanTilt.x = pan
self.requesta.Position.PanTilt.y = tilt
self.requesta.Speed.PanTilt.x = velocity
self.requesta.Speed.PanTilt.y = velocity
ret = self.ptz.AbsoluteMove(self.requesta)
# Relative move functions --NO ERRORS BUT CAMERA DOES NOT MOVE
def move_relative(self, pan, tilt, velocity):
self.requestr.Translation.PanTilt.x = pan
self.requestr.Translation.PanTilt.y = tilt
self.requestr.Speed.PanTilt = [velocity,velocity]
# self.requestr.Speed.PanTilt.x = velocity
# self.requestr.Speed.PanTilt.y = velocity
self.requestr.Speed.Zoom = 0
ret = self.ptz.RelativeMove(self.requestr)
def zoom_relative(self, zoom, velocity):
self.requestr.Translation.PanTilt.x = 0
self.requestr.Translation.PanTilt.y = 0
self.requestr.Translation.Zoom.x = zoom
self.requestr.Speed.PanTilt.x = 0
self.requestr.Speed.PanTilt.y = 0
self.requestr.Speed.Zoom.x = velocity
ret = self.ptz.RelativeMove(self.requestr)
# Sets preset set, query and and go to
def set_preset(self, name):
self.requestp.PresetName = name
self.requestp.PresetToken = '1'
self.preset = self.ptz.SetPreset(self.requestp) # returns the PresetToken
def get_preset(self):
self.ptzPresetsList = self.ptz.GetPresets(self.requestc)
def goto_preset(self):
self.requestg.PresetToken = '1'
self.ptz.GotoPreset(self.requestg)