[ONVIF系列 - 01] 简介 - 设备发现 - 相关工具

news2024/12/25 9:30:20

1.背景知识

这个事项对我而言是个新知,我从:https://www.cnblogs.com/liwen01/p/17337916.html

跳转到了:ONVIF协议网络摄像机(IPC)客户端程序开发(1):专栏开篇_onvif 许振坪-CSDN博客

1.1 ONVIF协议的分类:

Profile S:「网络摄像机」的技术规格,包括如何发送音视频流,音视频编码器配置,PTZ控制、中继控制等。
Profile C:「门禁控制系统(PACS)设备」的技术规格。
Profile G:「视频储存和录像」的技术规格,包括视频储存,搜索,检索,以及媒体播放功能的技术规格。
Profile A:「常见的例行门禁控制功能」的技术规范,适用于负责授予和撤销员工凭证、创建和更新计划表,以及对系统内门禁控制权限进行更改的安保人员、接待员或人力资源专员等用户。
Profile Q:「传输层安全性(TLS)」的技术规格,该安全通信协议使ONVIF合标设备能够以不受篡改和窃听威胁的方式在网络上与客户通讯。

S是等级最低的,在它之前似乎还有个T。这里是S的协议文档

然后我看到的文档里推荐下载这个:https://download.csdn.net/download/benkaoya/9818513

大概是中文版。

2 可能利用的三方代码

2.1 实现:

作者推荐使用gSoap工具来提供ONVIF协议的解析。

而chatgpt的推荐是使用客户端工具,阅读源码来反向构建其服务程序:

  1. onvif-py

    • 这个库有一个模块化结构,可以用来创建一个支持 ONVIF 协议的服务端。但它主要是作为一个 ONVIF 客户端库,因此你需要阅读源代码来了解如何使用它来创建服务端。这需要一定的编程知识。
  2. onvif_zm(用于 ZoneMinder):

    • 这个库原本是为 ZoneMinder 设计的,用于实现与 ONVIF 设备的通讯。虽然它是作为客户端库,但了解其工作原理后,你可以参考其代码来构建服务端。
  3. onvif.server

    • 这个库是 ONVIF 服务器的一个实现,它支持标准的 ONVIF 服务如 Discovery、Device、Media、PTZ、Event 等。这个库提供了创建和管理 ONVIF 服务器所需的所有基本功能。

2.2 可能的原生代码支持:

2.2.1 gstreamer

https://gstreamer.freedesktop.org/documentation/gst-rtsp-server/rtsp-onvif-server.html?gi-language=c 

我大概知道ONVIF的服务端涉及两个端口:

  1. 摄像头发现端口:udp 239.255.255.250:3702
  2. ONVIF协议侦听端口。 

大概率gstreamer能搞定后一个。前一个是个udp端口

2.2.2 一个可能使用的完整服务端封装:

基于ONVIF协议,实现 网络摄像机 设备发现 功能: 基于ONVIF协议,实现 网络摄像机 设备发现 功能 (gitee.com)

3. 测试

3.1 设备发现代码(In Python)

参阅:https://blog.csdn.net/benkaoya/article/details/72476120

多播地址(Multicast Address)有很多,各个行业都不一样,IPC摄像头用的是239.255.255.250(端口3702)。多播地址的范围和分类可以见官方IANA(互联网地址分配机构)的说明:IPv4 Multicast Address Space Registry。 

import socket
import struct

# 组播地址和端口
MULTICAST_GROUP = '239.255.255.250'
PORT = 3702
UDP_LOCAL_PORT = 1975 #本地接口不可以是组播端口3702

def discover_onvif_devices():
    # 创建一个 UDP 套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    # 设置多播 TTL
    TTL = 2
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, TTL) #TTL 生存时间
    # 允许重用地址
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    # 绑定到本地端口
    sock.bind(('', UDP_LOCAL_PORT )) 
    # 禁用组播环回
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)

    # 加入组播组
    mreq = struct.pack("4sl", socket.inet_aton(MULTICAST_GROUP), socket.INADDR_ANY)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
    is_SendSSDP_request = False
    # 构造 SSDP 请求
    ssdp_request ='<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action><a:MessageID>uuid:2fe59dad-ae6e-47f2-9b3c-5caba35ad4fc</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To></s:Header><s:Body><Probe xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery"><d:Types xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</d:Types></Probe></s:Body></s:Envelope>'
    # 发送请求到多播地址
    sock.sendto(ssdp_request.encode(), (MULTICAST_GROUP , PORT))
    while True:
        try:
            # 设置接收超时时间
            sock.settimeout(3.0)
            # 接收响应
            response, _ = sock.recvfrom(4096)
            print(f'Received response:\n{response.decode()}')
        except socket.timeout:
            if(is_SendSSDP_request):
                break;
            else:
                sock.sendto(ssdp_request.encode(), (MULTICAST_GROUP , PORT))

    # 退出组播组
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_DROP_MEMBERSHIP, mreq)
    
    # 关闭套接字
    sock.close()

if __name__ == "__main__":
    discover_onvif_devices()

3.1.1 运行效果:

下面是局域网的一个开通了ONVIF协议的摄像头在收到设备发现组播帧的回执:

Received response:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnshik="http://www.hikvision.com/2011/event/topics" xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl" xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema" xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl" xmlns:axt="http://www.onvif.org/ver20/analytics"><env:Header><wsadis:MessageID>urn:uuid:4e774000-6f8b-11b2-8068-240f9bbadc0c</wsadis:MessageID>
<wsadis:RelatesTo>uuid:2fe59dad-ae6e-47f2-9b3c-5caba35ad4fc</wsadis:RelatesTo>
<wsadis:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsadis:To>
<wsadis:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches</wsadis:Action>
<d:AppSequence InstanceId="1722420540" MessageNumber="1220"/>
</env:Header>
<env:Body><d:ProbeMatches><d:ProbeMatch><wsadis:EndpointReference><wsadis:Address>urn:uuid:4e774000-6f8b-11b2-8068-240f9bbadc0c</wsadis:Address>
</wsadis:EndpointReference>
<d:Types>dn:NetworkVideoTransmitter tds:Device</d:Types>
<d:Scopes>onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/Profile/Streaming onvif://www.onvif.org/Profile/T onvif://www.onvif.org/MAC/24:0f:9b:ba:dc:0c onvif://www.onvif.org/hardware/DS-2CD3T25D-I3 onvif://www.onvif.org/name/HIKVISION%20DS-2CD3T25D-I3 onvif://www.onvif.org/location/city/hangzhou</d:Scopes>
<d:XAddrs>http://192.168.0.6/onvif/device_service http://[240e:33d:17:6a0:260f:9bff:feba:dc0c]/onvif/device_service</d:XAddrs>
<d:MetadataVersion>10</d:MetadataVersion>
</d:ProbeMatch>
</d:ProbeMatches>
</env:Body>
</env:Envelope>

3.2 使用网络调试助手进行设备发现 

3.2.1 步骤清单

  1. 网络调试助手设定UDP协议,地址设定为局域网IP(与摄像头同网段),PORT任意。
  2. 打开
  3. 右下角选择组播,然后加入ONVIF路由发现组播地址:
  4. 给组播地址239.255.255.250:3702端口发送一个查询帧,内容:
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action><a:MessageID>uuid:2fe59dad-ae6e-47f2-9b3c-5caba35ad4fc</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To></s:Header><s:Body><Probe xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery"><d:Types xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</d:Types></Probe></s:Body></s:Envelope> 
  5.  你会收到局域网内的所有设备以自己的私有IP发来的回应帧。暴露自己的基础访问参数。

3.3 找到设备对外视频接口

下面使用3.1、3.2得到的某一个设备的onvif soap接口,比如:http://192.168.0.6/onvif/device_service
,尝试获取它的在线视频地址:

3.3.1 Python代码初次尝试

为了收发soap消息,使用asyncio做 soap请求异步收发:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 获取当前脚本文件所在目录的父目录,并构建相对路径
import os
import sys
current_dir = os.path.dirname(os.path.abspath(__file__))
project_path = os.path.join(current_dir, '..')
sys.path.append(project_path)
sys.path.append(current_dir)

import aiohttp
import asyncio

async def get_stream_uri():
    url = 'http://192.168.0.6/onvif/device_service'
    soap_message = '''<?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
                   xmlns:trt="http://www.onvif.org/ver10/media/wsdl">
        <soap:Header/>
        <soap:Body>
            <trt:GetStreamUri>
                <trt:StreamSetup>
                    <trt:Stream>RTP-Unicast</trt:Stream>
                    <trt:Transport>
                        <trt:Protocol>UDP</trt:Protocol>
                    </trt:Transport>
                </trt:StreamSetup>
                <trt:ProfileToken>PROFILE_TOKEN</trt:ProfileToken>
            </trt:GetStreamUri>
        </soap:Body>
    </soap:Envelope>'''

    async with aiohttp.ClientSession() as session:
        async with session.post(url, data=soap_message, headers={'Content-Type': 'application/soap+xml'}) as response:
            result = await response.text()
            print(result)


if __name__ == "__main__":
    # 运行异步函数
    asyncio.run(get_stream_uri())
3.3.1.1 结果:

python3 ./gpONVIF.py 
<!DOCTYPE html>
<html><head><title>Document Error: Unauthorized</title></head>
<body><h2>Access Error: 401 -- Unauthorized</h2>
<p>Authentication Error: This onvif request requires authentication information</p>
</body>
</html>

3.3.2 使用身份认证信息再次查询设备对外视频接口

这里使用httpx来处理digest+ws-username auth.
soap封装的xml消息,使用xml.etree来解析。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 获取当前脚本文件所在目录的父目录,并构建相对路径
import os
import sys
current_dir = os.path.dirname(os.path.abspath(__file__))
project_path = os.path.join(current_dir, '..')
sys.path.append(project_path)
sys.path.append(current_dir)

import asyncio
import aiohttp
import xml.etree.ElementTree as ET
from httpx import AsyncClient, DigestAuth
import httpx

# ONVIF 设备服务 URL
device_service_url = 'http://192.168.0.6/onvif/device_service'
username = 'admin'
password = 'xxxxxxxxxx'

async def get_device_information(session, url):
    headers = {'Content-Type': 'application/soap+xml'}
    body = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
                        xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
                <s:Header/>
                <s:Body>
                  <tds:GetServices>
                    <tds:IncludeCapability>false</tds:IncludeCapability>
                  </tds:GetServices>
                </s:Body>
              </s:Envelope>"""
    
    try:
        response = httpx.post(url, headers=headers, data=body, auth=DigestAuth(username, password))
        return response.text
    except Exception as e:
        print(f'An error occurred: {e}')
        return None

def parse_media_service_url(device_response):
    media_service_url = None
    root = ET.fromstring(device_response)
    ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'tds': 'http://www.onvif.org/ver10/device/wsdl'}
    services = root.find('.//tds:GetServicesResponse', namespaces=ns)
    #print(services)
    # 查找 <tds:XAddr> 元素
    for s in services:
        ns1 = s.find('.//tds:Namespace', namespaces=ns)
        #print('........ns................',ns1)
        if(ns1 is not None):
            if('media' in ns1.text):
                 addr = s.find('.//tds:XAddr', namespaces = ns)
                 if(addr is not None):
                      #print('........addr................',addr)
                      media_service_url = addr.text
    return media_service_url

async def get_video_stream_url(session, media_service_url):
    headers = {'Content-Type': 'application/soap+xml'}
    body = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
                        xmlns:trt="http://www.onvif.org/ver10/media/wsdl">
                <s:Header/>
                <s:Body>
                  <trt:GetStreamUri>
                    <trt:StreamSetup>
                      <trt:Stream>RTP-Unicast</trt:Stream>
                      <trt:Transport>
                        <trt:Protocol>RTSP</trt:Protocol>
                      </trt:Transport>
                    </trt:StreamSetup>
                    <trt:ProfileToken>ProfileToken</trt:ProfileToken>
                  </trt:GetStreamUri>
                </s:Body>
              </s:Envelope>"""
    try:
        response = httpx.post(media_service_url, headers=headers, data=body, auth=DigestAuth(username, password))
        return response.text
    except Exception as e:
        print(f'An error occurred: {e}')
        return None

def parse_video_stream_url(media_response):
    root = ET.fromstring(media_response)
    ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'trt': 'http://www.onvif.org/ver10/media/wsdl'}
    uri = root.find('.//trt:GetStreamUriResponse/trt:MediaUri', namespaces=ns)
    if uri is not None:
        return uri.text
    return None

async def main():
     async with httpx.AsyncClient() as session:
        device_response = await get_device_information(session, device_service_url)
        #print(device_response)
        print('>>>>>>>>>>>>>>>>>>>>>>>>>>>')
        media_service_url = parse_media_service_url(device_response)
        print(media_service_url)
        
        if media_service_url:
            media_response = await get_video_stream_url(session, media_service_url)
            print(media_response)
            video_stream_url = parse_video_stream_url(media_response)
            print("Video Stream URL:", video_stream_url)
        else:
            print("Media service URL not found")

# 运行异步主函数
if __name__ == '__main__':
    asyncio.run(main())
3.3.2.1 结果:

似乎找错了服务接口,现在已经很接近了。对吧?

http://192.168.0.6/onvif/Media2
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnshik="http://www.hikvision.com/2011/event/topics" xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl" xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema" xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl" xmlns:axt="http://www.onvif.org/ver20/analytics"><env:Body><env:Fault><env:Code><env:Value>env:Sender</env:Value>
<env:Subcode><env:Value>ter:InvalidArgVal</env:Value>
<env:Subcode><env:Value>ter:NoProfile</env:Value>
</env:Subcode>
</env:Subcode>
</env:Code>
<env:Reason><env:Text xml:lang="en">The requested profile token ProfileToken does not exist.</env:Text>
</env:Reason>
<env:Node>http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver</env:Node>
<env:Role>http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver</env:Role>
<env:Detail><env:Text>No Such ProfileToken</env:Text>
</env:Detail>
</env:Fault>
</env:Body>
</env:Envelope>

Video Stream URL: None  

4.FAQ 

4.1 什么是gSoap?

gSOAP 是一个开源的 C 语言库,用于开发 Web 服务和客户端。它简化了 SOAP(Simple Object Access Protocol)和 XML 相关的通信,使得在 C 语言应用程序中实现 Web 服务变得更容易。gSOAP 提供了自动化的工具来生成 C 语言的客户端和服务器端代码,从而支持 Web 服务的创建和消费。

以下是 gSOAP 的一些关键特点:

  1. SOAP 支持:gSOAP 实现了 SOAP 1.1 和 SOAP 1.2 协议,使得开发人员可以通过简单的接口来创建和解析 SOAP 消息。

  2. WSDL 支持:gSOAP 可以从 WSDL(Web Services Description Language)文件自动生成 C 语言代码,简化了 Web 服务的客户端和服务器端的开发。

  3. 轻量级:gSOAP 设计为一个轻量级库,适合嵌入式和资源有限的环境。

  4. 高效:gSOAP 具有高效的解析和序列化功能,可以处理大量的数据交换。

  5. 灵活性:它支持多种数据格式,包括 XML 和 JSON。

  6. 跨平台:gSOAP 是跨平台的,可以在多种操作系统上使用,包括 Windows、Linux 和 macOS。

  7. XML 和 JSON 处理:除了 SOAP,gSOAP 还提供对 XML 和 JSON 数据格式的处理支持。

使用 gSOAP,可以快速地将现有的 C 语言应用程序与 Web 服务集成,实现分布式计算和数据交换。

附录A 测试工具 ODM

原始链接:ODM download | SourceForge.net

A.1 摄像头ONVIF协议使能

测试时可能需要参考一些既有的摄像头的功能实现。注意支持ONVIF的摄像头默认一般不自动打开这个功能,需要先在摄像头的控制界面配置。ONVIF的中文名称是:开放型网络视频接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1963095.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字人直播系统搭建能力评测!3招教你快速摸清源码厂商的真实实力?

随着数字人直播的应用场景不断拓展和应用频率的持续升高&#xff0c;其所蕴含着的市场前景和收益潜力逐渐显现&#xff0c;连带着数字人直播系统搭建的热度也迎来了新的高潮。在此背景下&#xff0c;作为非科班和研发资源有限的创业者们主要的入局途径&#xff0c;各大数字人源…

Vatee万腾平台:智能管理领域的稳健前行者

在数字经济飞速发展的今天&#xff0c;企业管理模式正经历着前所未有的变革。智能化管理&#xff0c;作为这场变革的核心驱动力&#xff0c;正逐步渗透到企业的每一个角落。而在这场智能化浪潮中&#xff0c;Vatee万腾平台以其稳健的步伐和前瞻的视野&#xff0c;成为了智能管理…

【LLM大模型】一个小时内快速部署大模型

这个教程有以下几部分构成&#xff1a; 硬件配置概念介绍实操测试结果 1.硬件配置 本文使用的方法配置要求低&#xff0c;没有gpu也可以正常使用(就是有点慢)&#xff0c;不管是windows 还是linux&#xff0c;都可以无障碍使用大模型&#xff0c;有脚就行&#xff0c;废话少…

开放式耳机哪个牌子好?五款热门机型对比pk大揭秘!

作为一名耳机测评师&#xff0c;很多人想要知道如何才能选择一款合适自己的开放式耳机&#xff0c;其实我也非常的犯难&#xff0c;因为问的人实在是太多了&#xff0c;而且每个人的情况都不一样&#xff0c;所以不能说我指定的机型就一定适合你&#xff0c;所以这篇文章就是来…

【python】高数计算题难度大?python带你轻松拿下

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

ansys fluent流道分析得到的质量流率为负数

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

从技术角度看视频美颜SDK:实现美颜功能的关键算法

本篇文章&#xff0c;笔者将从技术角度&#xff0c;深入探讨视频美颜SDK实现美颜功能的关键算法。 1.人脸检测与特征点定位 人脸检测主要采用的是卷积神经网络等深度学习算法&#xff0c;这些算法能够在不同光照、姿态和表情下准确识别出人脸。 常见的算法包括Dlib库中的68点…

开发环境搭建——Redis的安装配置

1、msi安装 双击msi安装程序&#xff0c;打开安装向导&#xff0c;点击next 接收终端用户协议&#xff0c;点击next 选择安装路径&#xff0c;并勾选将安装路径添加到系统的PATH环境变量 设置Redis服务端口&#xff0c;默认6379&#xff0c;点击next 设置最大内存限制&#xf…

Golang基础常识性知识面试中常见的六大陷阱及应对技巧

一、nil slice & empty slice 1、nil切片与空切片底层 nil切片&#xff1a;var nilSlice [] string nil slice的长度len和容量cap都是0 nil slicenil nil slice的pointer是nil 空切片&#xff1a;emptySlice0 : make([]int,0) empty slice的长度是0&#xff0c;容量是由…

算法初学者学二分查找

力扣704&#xff0c;二分查找 题目是这样的 二分查找的思路就是&#xff1a; 先确定左右两个边界&#xff0c;左边界是从左往右&#xff0c;右边界是从右往左&#xff0c;所以&#xff0c;左边界是找的比target大的第一个值&#xff0c;右边界最后停的点是比target小的第一个…

谢希仁计算机网络第八版期末复习简答(1)

绪论 计算机网络的概念以及常见的网络类型? 计算机网络&#xff0c;是指地理位置分散的、具有独立功能的多台计算机及其外部设备&#xff0c;通过各种通信线路互联起来&#xff0c;在网络操作系统、网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息…

2024年的AI人工智能风口是Python?一篇文章告诉你为什么!

Python是一种面向对象的、解释型的、通用的、开源的脚本编程语言&#xff0c;它之所以非常流行&#xff0c;我认为主要有三点原因&#xff1a; 1.Python 简单易用&#xff0c;学习成本低&#xff0c;看起来非常干净&#xff1b; 2.Python 标准库和第三库众多&#xff0c;功能…

短剧系统源码分享,快速搭建部署上线教程

一、短剧系统是什么&#xff1f; 短剧制作平台&#xff0c;作为一站式综合解决方案&#xff0c;集剧本创作、角色设计、场景搭建、视频编辑、便捷发布及深度数据分析能力于一身。该平台精准定位于助力企业利用短剧形式强化品牌传播力并驱动商业价值增长&#xff0c;无论企业是…

物理学中三个令人兴奋的想法:稳态作用原理、洛伦兹变换和度量张量

​ 图片来源&#xff1a; https 文章目录 ​一、说明二、最小行动原则三、洛伦兹变换四、Minkowski 公制五、度量张量&#xff1a;曲面的几何形状六、三维欧几里得距离。 ​一、说明 虽然物理学引起了公众的好奇心&#xff0c;但许多人发现数学令人生畏。然而&#xff0c;物理…

C#知识|文件与目录操作:目录的操作

哈喽,你好啊,我是雷工! 前边学习了文件的删除、复制、移动,接下来学习目录的操作。 以下为学习笔记。 01 效果演示 1.1、显示指定目录下的所有文件 在左侧的文本框中显示出F:\F004-C#目录下的所有文件, 演示效果: 1.2、显示指定目录下的所有子文件 在左侧的文本框中显…

Serverless Knative冷启动与自动扩缩容研究:从原理到实践

最近一个研究生网页的提问&#xff0c;然后就有了这篇博客&#xff01; 大佬你好&#xff0c;我看到您的关于Serverless的文章于是十分冒昧的向您提问。我现在是一名在研究通过Serverless容器调度解决冷启动问题的本科生&#xff0c;导师放养&#xff0c;就让看论文但是后面的代…

多态、接口、类练习题

代码&#xff1a; public static void main(String[] args) {Person2 personnew Person2("唐僧",new Horse());person.passRiver();person.onRoad();} 接口&#xff1a; interface Vehicles{public void work(); } lass Horse implements Vehicles{Overridepubli…

HIS系统开发,医院HIS系统开发注意事项

在当今信息化迅速发展的时代&#xff0c;医院信息系统&#xff08;HIS&#xff09;的开发已成为提升医疗服务效率和质量的关键。HIS系统的开发并非易事&#xff0c;它涉及到众多复杂的技术和管理问题。以下是开发HIS系统时需要特别注意的几个关键问题。 数据安全与隐私保护是HI…