python实现onvif协议下控制摄像头变焦,以及融合Mediapipe人形识别与跟踪控制

     这两天才因为项目需要,对网络摄像头的视频采集以及实现人形识别与跟踪技术。对于onvif协议自然起先也没有任何的了解。但是购买的摄像头是SONY网络头是用在其他地方的。因为前期支持探究项目解决方案,就直接拿来做demo测试使用。

 先说说onvif协议:

Onvif,即Open Network Video Interface Forum ,可以译为开放型网络视频接口论坛,是安迅士、博世、索尼在2008年共同成立的一个国际性、开发型网络视频产品标准网络接口的开发论坛,后来由于这个技术开发论坛共同制定的开发型行业标准,就用该论坛的大写字母命名,即ONVIF 网络视频标准规范,习惯简称为:ONVIF协议。

Onvif协议的出现,解决了不同厂商之间开发的各类失败不能融合使用的难题,提供了统一的网络视频开发标准,即最终能够通过Onvif这个标准化的平台实现不同产品之间的集成。

onvif Device test tool工具测试

python实现步骤

  1. 安装必要的库

    • 使用 pip install onvif 安装 ONVIF 库。
    • 根据人形识别所用的库进行安装,比如使用 pip install volo(假设使用 volo 进行人形识别)。
  2. 初始化 ONVIF 摄像头

    • 设置摄像头的 IP 地址、端口、用户名和密码等参数。
    • 创建 ONVIFCamera 对象并更新其地址。
    • 获取 PTZ(Pan/Tilt/Zoom)服务,用于控制摄像头的云台和变焦。
  3. 实现摄像头变焦控制

    • 定义变焦速度等参数。
    • 通过调用 PTZ 服务的相关方法实现拉近(zoom in)、拉远(zoom out)和停止变焦操作。
  4. 人形识别与跟踪

    • 使用选定的人形识别库加载模型并进行图像分析。
    • 在视频流中检测人形,获取人形的位置信息。
    • 根据人形位置调整摄像头的云台和变焦,实现跟踪。

完整代码

import cv2
import numpy as np
import serial
from onvif import ONVIFCamera
import time
import asyncio
from zeep import Client
import tkinter as tk
from threading import Thread
import logging

logging.basicConfig(level=logging.DEBUG)

# 摄像头配置常量
CAMERA_IP = "192.168.0.132"
CAMERA_PORT = 8080
CAMERA_USERNAME = "admin"
CAMERA_PASSWORD = "*****"

# 串口配置常量
SERIAL_PORT = 'COM4'
BAUDRATE = 115200

# 初始化串口
ser = serial.Serial(SERIAL_PORT, BAUDRATE)

# 初始化摄像头
camera = None
try:
    camera = ONVIFCamera(CAMERA_IP, CAMERA_PORT, CAMERA_USERNAME, CAMERA_PASSWORD)
    camera.update_xaddrs()
  
except Exception as e:
    logging.error(f"初始化摄像机错误: {e}")
# 获取 PTZ 服务
def get_ptz_service(camera):
    try:
        if camera:
            return camera.create_ptz_service()
        else:
            print("摄像机未初始化.")
            return None
    except Exception as e:
        print(f"PTZ 服务初始化错误: {e}")
        return None
ptz_service = get_ptz_service(camera)
# ONVIF摄像头设置
def get_stream_url():
    if camera:
        media_service = camera.create_media_service()
        return media_service.GetStreamUri({
            'StreamSetup': {
                'Stream': 'RTP-Unicast',
                'Transport': {'Protocol': 'RTSP'}
            },
            'ProfileToken': camera.media.GetProfiles()[0].token
        }).Uri
    else:
        return None
async def process_video_async(cap):
    while True:
        ret, frame = cap.read()
        if not ret:
            print("视频读取失败")
            break

        resized_frame = cv2.resize(frame, (899, 600))
        cv2.imshow('Video', resized_frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
        await asyncio.sleep(0)

def start_video_processing():
    stream_url = get_stream_url()
    if stream_url:
        cap = cv2.VideoCapture(stream_url)
        cap.set(cv2.CAP_PROP_FPS, 30)
        asyncio.run(process_video_async(cap))
        cap.release()
    else:
        print("无法获取视频流 URL。")
# 摄像头控制
class CameraControl:
    def __init__(self, ptz_service, camera):
        self.ptz_service = ptz_service
        self.zoom_speed = 0.1
        self.camera_profile_token = 'P2'

    def zoom_in(self):
        try:
            if self.camera_profile_token and 'P2':
                self.ptz_service.ContinuousMove({
                    'ProfileToken': 'P2',
                    'Velocity': {
                     'PanTilt': {'x': 0.0, 'y': 0.0},
                     'Zoom': {'x': self.zoom_speed}
                    }
                })
                print("拉近操作进行中")
            else:
                print("摄像头或 PTZ 服务未正确初始化。")
        except 
### 使用Python实现USB摄像头的缩放功能 为了使用Python控制USB摄像头执行缩放操作,可以利用`opencv-python`库来访问和处理来自摄像头的数据。然而,需要注意的是OpenCV本身并不直接提供用于调整摄像镜头光学变焦参数的方法。对于大多数消费级USB摄像头来说,通常也不支持硬件级别的变焦控制。 但是,在软件层面模拟放大效果是可行的做法之一。这可以通过裁剪图像中心区域再将其拉伸至原始尺寸的方式达成近似于数码变焦的效果[^1]。 下面是一个简单的例子展示如何通过截取画面中央部分并重新调整大小以达到类似变焦的目的: ```python import cv2 def zoom_at(img, zoom=1, angle=0): """ Zooms and rotates an image. :param img: Input frame from camera feed. :param zoom: Factor by which to enlarge the center of the image (default is no change). Values greater than 1 will cause enlargement while less than one causes reduction. :param angle: Rotation angle in degrees (optional). Not used here but kept for completeness. Positive values mean counter-clockwise rotation. :return: Processed output frame with applied transformations. """ cy, cx = [i / 2 for i in img.shape[:-1]] # Center coordinates rot_mat = cv2.getRotationMatrix2D((cx,cy),angle,abs(zoom)) result = cv2.warpAffine( src=img, M=rot_mat, dsize=(img.shape[1], img.shape[0]), borderMode=cv2.BORDER_CONSTANT, borderValue=(0,0,0)) if zoom >= 1: h,w = int(result.shape[0]/zoom),int(result.shape[1]/zoom) y,x = (result.shape[0]-h)//2,(result.shape[1]-w)//2 crop_img = result[y:y+h, x:x+w] return cv2.resize(crop_img, None, fx=zoom,fy=zoom) else: out_dim = ( max(int(img.shape[0]*zoom)+1,1), max(int(img.shape[1]*zoom)+1,1) ) pad_x = max(out_dim[1] - w, 0) // 2 pad_y = max(out_dim[0] - h, 0) // 2 padded_image = cv2.copyMakeBorder( result, top=int(pad_y), bottom=int(pad_y), left=int(pad_x), right=int(pad_x), borderType=cv2.BORDER_CONSTANT,value=[0,0,0]) start_h = abs(min(0,h-out_dim[0]))//2 end_h = start_h + min(h,out_dim[0]) start_w = abs(min(0,w-out_dim[1]))//2 end_w = start_w + min(w,out_dim[1]) cropped_padded = padded_image[start_h:end_h,start_w:end_w] return cv2.resize(cropped_padded,None,fx=1/zoom,fy=1/zoom) cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break z_factor = 1.5 # Change this value to adjust 'zoom' level processed_frame = zoom_at(frame,zoom=z_factor) cv2.imshow('Zoomed Video Feed',processed_frame) key = cv2.waitKey(1) & 0xFF if key == ord("q"): break cap.release() cv2.destroyAllWindows() ``` 上述代码定义了一个名为`zoom_at()`函数用来创建具有指定缩放和平移特性的变换矩阵,并应用到输入帧上;接着在一个循环里不断获取新的视频帧并对它们施加此变换,最后显示经过处理后的结果给用户查看直到按下键盘上的 "Q" 键退出程序[^3]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道1993

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值