日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

使用opencv-python读取多个(海康\大华)网络摄像头的视频流,解决实时读取延迟问题

發布時間:2023/12/20 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用opencv-python读取多个(海康\大华)网络摄像头的视频流,解决实时读取延迟问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上一篇博客中,主要介紹了python之opencv按幀提取視頻中的圖片,但是,由于最近在做人臉識別的項目,用的是大華的監控攝像頭,我發現大華的攝像頭實時讀取延遲問題特別嚴重,尤其是主碼流,這個問題困擾了我好久,最終想到的方式就是自己實時推流,經過實踐,終于解決了實時讀取延遲問題。

前言

同樣需要準備對應的python開發環境,具體參考上一篇python之opencv按幀提取視頻中的圖片,里面介紹了詳細的需要的庫文件。

好了,既然是自己實現實時預覽推流,那就要確定使用推流方式,我這里使用的是RTSP地址和格式實現推流的,下面是我歸納的各大監控攝像頭廠商的RTSP具體推流格式。

各大攝像頭廠商RTSP推流格式

  • 海康實時流
    rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream
    說明
    username: 用戶名。例如admin。
    password: 密碼。例如123456。
    ip: 為設備IP。例如 192.168.0.224。
    port: 端口號默認為554,若為默認可不填寫。
    codec:有h264、MPEG-4、mpeg4這幾種。
    channel: 通道號,起始為1。例如通道1,則為ch1。
    subtype: 碼流類型,主碼流為main,子碼流為sub。
  • 舉個栗子:

    例如,請求海康攝像機通道1的主碼流,Url如下 rtsp://admin:123456@192.168.0.224:554/h264/ch1/main/av_stream rtsp://admin:123456@192.168.0.224:554/MPEG-4/ch1/main/av_stream rtsp://admin:123456@192.168.0.224:554/h264/ch33/main/av_stream //ipc例如,請求海康攝像機通道1的子碼流,Url如下: rtsp://admin:123456@192.168.0.224/mpeg4/ch1/sub/av_stream rtsp://admin:123456@192.168.0.224/h264/ch1/sub/av_stream【新版本】URL:rtsp://username:password@<address>:<port>/Streaming/Channels/<id>(?parm1=value1&parm2-=value2…)注:VLC可以支持解析URL里的用戶名密碼,實際發給設備的RTSP請求不支持帶用戶名密碼。 舉例:DS-9632N-ST的模擬通道01主碼流:rtsp://admin:123456@192.168.0.224:554/Streaming/Channels/101?transportmode=unicastDS-9016HF-ST的IP通道01主碼流:rtsp://admin:123456@192.168.0.224:554/Streaming/Channels/1701?transportmode=unicastDS-9016HF-ST的模擬通道01子碼流:rtsp://admin:123456@192.168.0.224:554/Streaming/Channels/102?transportmode=unicast (單播)rtsp://admin:123456@192.168.0.224:554/Streaming/Channels/102?transportmode=multicast (多播)rtsp://admin:123456@192.168.0.224:554/Streaming/Channels/102 (?后面可省略,默認單播)注:前面老URL,NVR(>=64路的除外)的IP通道從33開始;新URL,通道號全部按順序從1開始。
  • 大華
    rtsp://username:password@ip:port/cam/realmonitor?channel=1&subtype=0
  • 說明:
    username: 用戶名,例如admin。
    password: 密碼,例如admin。
    ip: 為設備IP,例如192.168.0.224。
    port: 端口號默認為554,若為默認可不填寫。
    channel: 通道號,起始為1;例如通道2,則為channel=2。
    subtype: 碼流類型,主碼流為0(即subtype=0);子碼流為1(即subtype=1)。

    舉個栗子:

    例如,請求某設備的通道2的子碼流,Url如下 rtsp://admin:admin@192.168.0.224:554/cam/realmonitor?channel=2&subtype=1
  • 雄邁/巨峰
  • 默認IP地址:192.168.0.224
    用戶名: admin
    密碼空:123456
    端口:TCP端口:34567 和 HTTP端口:80,onvif端口是8899

    舉個栗子:
    RTSP地址:rtsp://192.168.0.224 :554/user=admin&password=123456&channel=1&stream=0.sdp?real_stream

    192.168.0.224 這個是被連接的設備的IP
    554這個是RTSP服務的端口號,可以在設備的網絡服務里面更改
    user=admin這個是設備的登錄用戶名
    password= 123456
    channel=1 第一通道
    stream=0.sdp?主碼流
    stream=1.sdp?副碼流

  • 天視通
  • 默認IP地址:192.168.0.224
    用戶名admin
    密碼123456
    端口:http端口80 數據端口8091 RTSP端口554 ONVIF端口 80

    舉個栗子:
    RTSP地址(不需要密碼):

    • 主碼流地址:rtsp://192.168.0.224 :554/mpeg4

    • 子碼流地址:rtsp://192.168.0.224 :554/mpeg4cif
      RTSP地址(需要密碼):

    • 主碼流 rtsp://admin:123456@192.168.0.224 :554/mpeg4

    • 子碼流 rtsp://admin:123456@192.168.0.224 :554/mpeg4cif

  • 中維/尚維
    默認IP地址:DHCP 默認(0.0.0.0)
    用戶名admin 默認
    密碼 空
  • 舉個栗子:

    RTSP地址:rtsp://0.0.0.0:8554/live1.264(次碼流) rtsp://0.0.0.0:8554/live0.264 (主碼流)
  • 九安
    RTSP地址:rtsp://IP:port(website port)/ch0_0.264(主碼流)
    rtsp://IP:port(website port)/ch0_1.264(子碼流)

  • 技威/YOOSEE
    默認IP地址:DHCP 用戶名admin 密碼123456
    RTSP地址:主碼流:rtsp://IPadr:554/onvif1
    次碼流:rtsp://IPadr:554/onvif2
    onvif端口是5000
    設備發現的端口是3702

  • V380
    默認IP地址:DHCP 用戶名admin 密碼空/admin
    onvif端口8899
    RTSP地址:主碼流rtsp://ip//live/ch00_1
    子碼流rtsp://ip//live/ch00_0

  • 宇視
    默認IP地址: 192.168.0.13/DHCP 默認用戶名 admin 和默認密碼 123456
    端口:HTTP 80/RTSP 554/HTTPS 110(443)/onvif端口 80
    RTSP地址:rtsp://用戶名:密碼@ip:端口號/video1/2/3,分別對應主/輔/三碼流;
    舉個栗子:

  • rtsp://admin:admin@192.168.8.8:554/video1,就表示主碼流; rtsp://admin:admin@192.168.8.8:554/video2,表示子碼流; rtsp://admin:admin@192.168.8.8:554/video3,表示3碼流;
  • 天地偉業
    默認IP地址:192.168.1.2 用戶名“Admin”、密碼“1111”
    onvif端口號“8080”
    RTSP地址:rtsp://192.168.1.2

  • 巨龍/JVT
    默認IP地址:192.168.1.88 默認用戶名 admin 默認密碼admin
    RTSP地址:
    主碼流地址:rtsp://IP地址/av0_0
    次碼流地址:rtsp://IP地址/av0_1
    onvif端口 2000

  • 海清
    RTSP地址:rtsp://用戶名:密碼@ip:端口號/av0_0

  • D-Link
    rtsp://[username]:[password]@[ip]:[port]/[channel].sdp
    說明:
    username:用戶名。例如admin
    password:密碼。例如12345,如果沒有網絡驗證可直接寫成rtsp:// [ip]:[port]/[channel].sdp
    ip:為設備IP。例如192.168.0.108。
    port:端口號默認為554,若為默認可不填寫。
    channel:通道號,起始為1。例如通道2,則為live2。

  • 舉個栗子:

    例如,請求某設備的通道2的碼流,URL如下 rtsp://admin:12345@192.168.200.201:554/live2.sdp
  • Axis(安訊士)
    rtsp://[username]:[password]@[ip]/axis-media/media.amp?[videocodec]&[resolution]
    說明:
    username:用戶名。例如admin
    password:密碼。例如12345,如果沒有網絡驗證可省略用戶名密碼部分以及@字符。
    ip:為設備IP。例如192.168.0.108。
    videocodec:支持MPEG、h.264等,可缺省。
    resolution:分辨率,如resolution=1920x1080,若采用默認分辨率,可缺省此參數。
  • 舉個栗子:

    例如,請求某設備h264編碼的1280x720的碼流,URL如下: rtsp:// 192.168.200.202/axis-media/media.amp?videocodec=h264&resolution=1280x720

    好了。支持,市場上主流的監控攝像頭RTSP推流就介紹完畢了,接下來就實戰RTSP實時推流吧。這里一大華攝像頭為栗子。

    實戰

    在上一篇,我們知道了,開啟實時預覽的方式,需要開啟opencv VideoCapture,細心一點你會發現,在上一篇中有這樣的代碼如下:

    # 導入所需要的庫 import cv2 import numpy as np # 讀取視頻文件 videoCapture = cv2.VideoCapture("test.mp4") # 通過攝像頭的方式 # videoCapture=cv2.VideoCapture(1)

    經過分析,你會發現,我們只需要把cv2.VideoCapture(“test.mp4”)這里做成實時推流的即可。

    一:開啟RTSP:

    在前面,我們知道了大華攝像頭的RTSP推流方式,那好,第一步就先實現RTSP推流吧。代碼如下:

    import cv2import time import multiprocessing as mpdef image_put(q, name, pwd, ip, channel=1)://使用占位符,動態的代替ip地址,用戶名,密碼,預覽通道等參數cap = cv2.VideoCapture("rtsp://%s:%s@%s//Streaming/Channels/%d" % (name, pwd, ip, channel))if cap.isOpened():print('HIKVISION')else:cap = cv2.VideoCapture("rtsp://%s:%s@%s/cam/realmonitor?channel=%d&subtype=0" % (name, pwd, ip, channel))print('DaHua')while True:q.put(cap.read()[1])q.get() if q.qsize() > 1 else time.sleep(0.01)def image_get(q, window_name):cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)while True:frame = q.get()cv2.imshow(window_name, frame)cv2.waitKey(1)def run_multi_camera():# user_name, user_pwd = "admin", "password"user_name, user_pwd = "admin", "admin123456"camera_ip_l = ["192.168.35.121", # ipv4"[fe80::3aaf:29ff:fed3:d260]", # ipv6# 把你的攝像頭的地址放到這里,如果是ipv6,那么需要加一個中括號。]

    二:多線程隊列解決實時閱覽延遲問題:

    上面,我們知道了,如何實現實時預覽,下面就解決一下核心問題,實時讀取延遲問題,代碼如下:

    import multiprocessing as mp ... img_queues = [mp.Queue(maxsize=2) for _ in camera_ip_l] # queue ... q.put(frame) if is_opened else None # 線程A不僅將圖片放入隊列 q.get() if q.qsize() > 1 else time.sleep(0.01) # 線程A還負責移除隊列中的舊圖 ...

    好了,完成了,這倆步,就可以解決實時讀取延遲問題了,最后附上完整代碼。

    完整代碼:

    import cv2import time import multiprocessing as mpdef image_put(q, name, pwd, ip, channel=1):cap = cv2.VideoCapture("rtsp://%s:%s@%s//Streaming/Channels/%d" % (name, pwd, ip, channel))if cap.isOpened():print('HIKVISION')else:cap = cv2.VideoCapture("rtsp://%s:%s@%s/cam/realmonitor?channel=%d&subtype=0" % (name, pwd, ip, channel))print('DaHua')while True:q.put(cap.read()[1])q.get() if q.qsize() > 1 else time.sleep(0.01)def image_get(q, window_name):cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)while True:frame = q.get()cv2.imshow(window_name, frame)cv2.waitKey(1)def run_multi_camera():# user_name, user_pwd = "admin", "password"user_name, user_pwd = "admin", "admin123456"camera_ip_l = ["192.168.35.121", # ipv4"[fe80::3aaf:29ff:fed3:d260]", # ipv6# 把你的攝像頭的地址放到這里,如果是ipv6,那么需要加一個中括號。]mp.set_start_method(method='spawn') # initqueues = [mp.Queue(maxsize=4) for _ in camera_ip_l]processes = []for queue, camera_ip in zip(queues, camera_ip_l):processes.append(mp.Process(target=image_put, args=(queue, user_name, user_pwd, camera_ip)))processes.append(mp.Process(target=image_get, args=(queue, camera_ip)))for process in processes:process.daemon = Trueprocess.start()for process in processes:process.join()if __name__ == '__main__':run_multi_camera()

    當然還有更簡單的實現方式,下面看看如何利用OpenCV官網給出的視頻流讀取吧

    簡單版-OpenCV官網給出的視頻流讀取示例

    經過簡單修改,如下:

    def run_opencv_camera():video_stream_path = 0 # local camera (e.g. the front camera of laptop)cap = cv2.VideoCapture(video_stream_path)while cap.isOpened():is_opened, frame = cap.read()cv2.imshow('frame', frame)cv2.waitKey(1)cap.release()

    當 video_stream_path = 0 的時候,電腦會開啟默認攝像頭,比如筆記本電腦的前置攝像頭 。
    當我們需要讀取網絡攝像頭的時候,我們可以對 cap = cv2.VideoCapture(括號里面的東西進行修改),填寫上我們想要讀取的視頻流,它可以是:

  • List item數字0,代表計算機的默認攝像頭(例如上面提及的筆記本前置攝像頭)
  • video.avi 視頻文件的路徑,支持其他格式的視頻文件
  • rtsp路徑(不同品牌的路徑一般是不同的,如下面舉出的海康與大華)
  • user, pwd, ip, channel = "admin", "admin123456", "192.168.35.121", 1video_stream_path = 0 # local camera (e.g. the front camera of laptop) video_stream_path = 'video.avi' # the path of video file video_stream_path = "rtsp://%s:%s@%s/h265/ch%s/main/av_stream" % (user, pwd, ip, channel) # HIKIVISION old version 2015 video_stream_path = "rtsp://%s:%s@%s//Streaming/Channels/%d" % (user, pwd, ip, channel) # HIKIVISION new version 2017 video_stream_path = "rtsp://%s:%s@%s/cam/realmonitor?channel=%d&subtype=0" % (user, pwd, ip, channel) # dahuacap = cv2.VideoCapture(video_stream_path)

    具體參考:OpenCV官網給出的視頻流讀取示例代碼

    好了,到此,我們就解決實時讀取延遲問題,但是,目前我們只是監控一路,如何監控多路,解決實時讀取延遲問題了,其實很簡單,因為每一路是獨立,互不干涉,下面就實戰多個攝像頭。

    實時預覽多路攝像頭

    有了單路的思路,你會發現,多路只要使用多線程隊列,就能解決延遲卡頓問題,讀取多個攝像頭。

    def image_put(q, user, pwd, ip, channel=1):cap = cv2.VideoCapture("rtsp://%s:%s@%s//Streaming/Channels/%d" % (user, pwd, ip, channel))if cap.isOpened():print('HIKVISION')else:cap = cv2.VideoCapture("rtsp://%s:%s@%s/cam/realmonitor?channel=%d&subtype=0" % (user, pwd, ip, channel))print('DaHua')while True:q.put(cap.read()[1])q.get() if q.qsize() > 1 else time.sleep(0.01)def image_get(q, window_name):cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)while True:frame = q.get()cv2.imshow(window_name, frame)cv2.waitKey(1)def run_single_camera():user_name, user_pwd, camera_ip = "admin", "admin123456", "192.168.35.121"mp.set_start_method(method='spawn') # initqueue = mp.Queue(maxsize=2)processes = [mp.Process(target=image_put, args=(queue, user_name, user_pwd, camera_ip)),mp.Process(target=image_get, args=(queue, camera_ip))][process.start() for process in processes][process.join() for process in processes]def run_multi_camera():# user_name, user_pwd = "admin", "password"user_name, user_pwd = "admin", "admin123456"camera_ip_l = ["172.20.114.26", # ipv4"[fe80::3aaf:29ff:fed3:d260]", # ipv6]mp.set_start_method(method='spawn') # initqueues = [mp.Queue(maxsize=4) for _ in camera_ip_l]processes = []for queue, camera_ip in zip(queues, camera_ip_l):processes.append(mp.Process(target=image_put, args=(queue, user_name, user_pwd, camera_ip)))processes.append(mp.Process(target=image_get, args=(queue, camera_ip)))for process in processes:process.daemon = Trueprocess.start()for process in processes:process.join()if __name__ == '__main__':# run_single_camera()run_multi_camera()pass

    關鍵部分解釋:

    我使用Python3自帶的多線程模塊,創建一個隊列,線程A從通過rtsp協議從視頻流中讀取出每一幀,并放入隊列中,線程B從隊列中將圖片取出,處理后進行顯示。線程A如果發現隊列里有兩張圖片(證明線程B的讀取速度跟不上線程A),那么線程A主動將隊列里面的舊圖片刪掉,換上新圖片。通過多線程的方法:

  • 線程A的讀取速度始終不收線程B的影響,防止網絡攝像頭的緩存區爆滿
  • 線程A更新了隊列中的圖片,使線程B始終讀取到最新的畫面,降低了延遲
  • import multiprocessing as mp ... img_queues = [mp.Queue(maxsize=2) for _ in camera_ip_l] # queue ... q.put(frame) if is_opened else None # 線程A不僅將圖片放入隊列 q.get() if q.qsize() > 1 else time.sleep(0.01) # 線程A還負責移除隊列中的舊圖 ...

    好了,支持,多路和單路實時預覽效果,便實現了,下面看一下具體的實現效果吧:

    總結

    以上是生活随笔為你收集整理的使用opencv-python读取多个(海康\大华)网络摄像头的视频流,解决实时读取延迟问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。