Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头

1.激活海康摄像头

通过SADP可看到下面这个信息
在这里插入图片描述
输入你想设置的密码即可

若忘记密码可看下面这篇博主的博客
https://blog.csdn.net/gao_summer_cola/article/details/72621766

2.关键信息

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。

用户名默认为admin 密码开始为admin,后可以设置为自己想要的,先通过使用SADP工具可以识别摄像头,然后配置IP与电脑(IPV4地址)在同一个网段。
在这里插入图片描述
然后通过IE浏览器打开对应的IP地址,输入账号和密码进入界面
,知道了用户名和密码和IP地址过后,在找到端口号(默认为554)即可
在这里插入图片描述

3.同步操作

#!/usr/bin/env python
#
# 这个代码注意点 设置好正确的用户名、密码、ip、端口,端口目前是554,
# 启动这个代码之后,会持续查看摄像头工作情况,非常好用,这个可以作为一个测试工具使用
#
import cv2
# UserName = "admin"
# PassW = "a12345678"
# IpAddr = "10.16.97.150"
# Port = "554"
url = 'rtsp://admin:a12345678@10.16.97.150:554/h264/ch1/main/av_stream'
ur2 = 'rtsp://admin:a12345678@10.16.97.149:555/h264/ch1/sub/av_stream'
# cap = cv2.VideoCapture("rtsp://" + UserName + ":" + PassW + "@" + IpAddr + ":" + Port + "/Streaming/Channels/1")
# 摄像头是否处于打开状态可以通过isOpened()方法进行判断
cap = cv2.VideoCapture(url)
cap1 = cv2.VideoCapture(ur2)
ret, frame = cap.read()
ret1, frame = cap1.read()
while ret:
    ret, frame = cap.read()
    ret, frame1 = cap1.read()
    cv2.imshow("frame",frame)
    cv2.imshow("frame1",frame1)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()
cap.release()
cap1.release()
print('done')

2.1效果图

在这里插入图片描述

4.异步操作

python可以使用multiprocessing多进程读取多个摄像头,但是multiprocessing自带的队列在交换数据时内存不会释放

4.1代码1

  • 数字0,代表计算机的默认摄像头(例如上面提及的笔记本前置摄像头)
  • video.avi 视频文件的路径,支持其他格式的视频文件
  • rtsp路径(不同品牌的路径一般是不同的,如下面举出的海康与大华)
user, pwd, ip, channel = "admin", "admin123456", "192.168.35.121", 1

video_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)  # dahua

cap = cv2.VideoCapture(video_stream_path)

# 代码描述:利用多进程方法,利用两个海康威视摄像头,同时录取视频并保存本地
import cv2
import time
import numpy as np
import multiprocessing as mp

# 抓取图片,确认视频流的读入
def image_put(q, name, pwd, ip, channel):
    cap = cv2.VideoCapture("rtsp://%s:%s@%s:%s//Streaming/Channels/1" \
                           % (name, pwd, ip, channel))
    # 获取视频帧率
    fps = cap.get(cv2.CAP_PROP_FPS)
    print('fps: ', fps)
    if cap.isOpened():
        print('HIKVISION1')
        print('camera ' + ip + " connected.")

    while True:
        q.put(cap.read()[1])
        q.get() if q.qsize() > 1 else time.sleep(0.01)

# 获得视频流帧数图片,保存读入的视频
def image_get(q, window_name):
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    # 视频保存路径
    path = "F:/pycharm/practice/vedio/" + window_name + ".avi"
    out = cv2.VideoWriter(path, fourcc, 20.0, (1280, 720), True)
    while True:
        frame = q.get()
        print(frame.shape)
        out.write(frame)

def image_collect(queue_list, camera_ip_l):

    """show in single opencv-imshow window"""
    #window_name = "%s_and_so_no" % camera_ip_l[0]
    # cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
    # while True:
    #     imgs = [q.get() for q in queue_list]
    #     imgs = np.concatenate(imgs, axis=1)
    #     cv2.imshow(window_name, imgs)
    #     cv2.waitKey(1)
    """show in multiple opencv-imshow windows"""
    [cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
     for window_name in camera_ip_l]
    while True:
        for window_name, q in zip(camera_ip_l, queue_list):
            cv2.imshow(window_name, q.get())
            cv2.waitKey(1)
# 解决进程问题
def run_multi_camera():
    # user_name, user_pwd = "admin", "password"
    user_name, user_pwd = "admin", "a12345678"
    # 摄像头的账户密码改成自己摄像头注册的信息
    camera_ip_l = [
        "10.16.55.149",  # ipv4
        "10.16.55.150",
        # 把你的摄像头的地址放到这里,如果是ipv6,那么需要加一个中括号
    ]
    ports=['554','555']

    mp.set_start_method(method='spawn')  # init
    queues = [mp.Queue(maxsize=2) for _ in camera_ip_l]
    processes = [mp.Process(target=image_collect, args=(queues, camera_ip_l))]
    #processes = []
    for queue, camera_ip,port in zip(queues, camera_ip_l,ports):
        processes.append(mp.Process(target=image_put, args=(queue, user_name, user_pwd, camera_ip,port)))
        processes.append(mp.Process(target=image_get, args=(queue, camera_ip)))
    for process in processes:
        process.daemon = True  # setattr(process, 'deamon', True)
        process.start()
    for process in processes:
        process.join()

if __name__ == '__main__':
    run_multi_camera()           # 调用主函数

效果图:
在这里插入图片描述

4.2代码2

把两个摄像头收集到的实时画面传给同一个进程:

# 代码描述:利用多进程方法,利用两个海康威视摄像头,同时录取视频并保存本地
import cv2
import time
import multiprocessing as mp

# 抓取图片,确认视频流的读入
def image_put(q, name, pwd, ip, channel):
    cap = cv2.VideoCapture("rtsp://%s:%s@%s:%s//Streaming/Channels/1" \
                           % (name, pwd, ip, channel))
    # 获取视频帧率
    fps = cap.get(cv2.CAP_PROP_FPS)
    print('fps: ', fps)
    if cap.isOpened():
        print('HIKVISION1')
        print('camera ' + ip + " connected.")

    while True:
        q.put(cap.read()[1])
        q.get() if q.qsize() > 1 else time.sleep(0.01)

def image_collect(queue_list, camera_ip_l):
    import numpy as np

    """show in single opencv-imshow window"""
    window_name = "%s_and_so_no" % camera_ip_l[0]
    cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
    while True:
        imgs = [q.get() for q in queue_list]
        imgs = np.concatenate(imgs, axis=1)
        cv2.imshow(window_name, imgs)
        cv2.waitKey(1)
# 解决进程问题
def run_multi_camera():
    # user_name, user_pwd = "admin", "password"
    user_name, user_pwd = "admin", "a12345678"
    # 摄像头的账户密码改成自己摄像头注册的信息
    camera_ip_l = [
        "10.16.55.149",  # ipv4
        "10.16.55.150",
        # 把你的摄像头的地址放到这里,如果是ipv6,那么需要加一个中括号
    ]
    ports=['554','555']

    mp.set_start_method(method='spawn')  # init
    queues = [mp.Queue(maxsize=2) for _ in camera_ip_l]
    processes = [mp.Process(target=image_collect, args=(queues, camera_ip_l))]
    #processes = []
    for queue, camera_ip,port in zip(queues, camera_ip_l,ports):
        processes.append(mp.Process(target=image_put, args=(queue, user_name, user_pwd, camera_ip,port)))

    for process in processes:
        process.daemon = True  # setattr(process, 'deamon', True)
        process.start()
    for process in processes:
        process.join()

if __name__ == '__main__':
    run_multi_camera()           # 调用主函数

效果图:
在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在使用OpenCV调用海康威视摄像头前,需要先安装海康威视SDK并设置好环境变量。具体步骤如下: 1. 下载海康威视SDK并安装。 2. 打开SDK安装目录下的“HCNetSDKCom”文件夹,在其中找到“HCNetSDK.dll”和“PlayCtrl.dll”两个文件。将这两个文件复制到系统目录下(一般为C:\Windows\System32)。 3. 在系统环境变量中添加“HCNETSDKPATH”变量,并将其值设置为SDK安装目录。 4. 在Visual Studio中,打开项目的属性页,选择“VC++目录”,将“包含目录”和“库目录”分别设置为SDK安装目录下的“Include”和“Lib”文件夹。 5. 在项目中添加以下代码: ```cpp #include <opencv2/opencv.hpp> #include <HCNetSDK.h> #include <PlayM4.h> #include <Windows.h> using namespace cv; int main() { // 初始化SDK NET_DVR_Init(); // 登录设备 LONG lUserID; NET_DVR_DEVICEINFO_V30 struDeviceInfo; lUserID = NET_DVR_Login_V30("192.168.1.64", 8000, "admin", "12345", &struDeviceInfo); if (lUserID < 0) { printf("Login failed, error code: %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return -1; } // 开启预览 LONG lRealPlayHandle; NET_DVR_PREVIEWINFO struPlayInfo = { 0 }; struPlayInfo.hPlayWnd = NULL; struPlayInfo.lChannel = 1; struPlayInfo.dwStreamType = 0; struPlayInfo.dwLinkMode = 0; lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, NULL, NULL); if (lRealPlayHandle < 0) { printf("NET_DVR_RealPlay_V40 failed, error code: %d\n", NET_DVR_GetLastError()); NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return -1; } // 显示图像 Mat frame; namedWindow("Camera", WINDOW_NORMAL); while (true) { // 获取图像数据 LONG lRealPlayRet = NET_DVR_GetRealPlayerIndex(lRealPlayHandle); if (lRealPlayRet < 0) { printf("NET_DVR_GetRealPlayerIndex failed, error code: %d\n", NET_DVR_GetLastError()); break; } LPNET_DVR_PREVIEWINFO lpPreviewInfo = &struPlayInfo; LONG lFrame = NET_DVR_GetNextVideoFrame(lRealPlayHandle); if (lFrame < 0) { printf("NET_DVR_GetNextVideoFrame failed, error code: %d\n", NET_DVR_GetLastError()); break; } BYTE* pBuf = NULL; DWORD dwBufSize = 0; BOOL bRet = PlayM4_GetData(lRealPlayRet, &pBuf, &dwBufSize); if (!bRet) { printf("PlayM4_GetData failed, error code: %d\n", PlayM4_GetLastError(lRealPlayRet)); break; } Mat yuvImg(Size(lpPreviewInfo->dwWidth, lpPreviewInfo->dwHeight * 3 / 2), CV_8UC1, pBuf); cvtColor(yuvImg, frame, COLOR_YUV2BGR_I420); // 显示图像 imshow("Camera", frame); if (waitKey(30) == 27) // 按下ESC退出 break; } // 关闭预览 NET_DVR_StopRealPlay(lRealPlayHandle); // 注销设备 NET_DVR_Logout(lUserID); // 释放SDK资 NET_DVR_Cleanup(); return 0; } ``` 以上代码中,我们通过NET_DVR_Login_V30函数登录设备,通过NET_DVR_RealPlay_V40函数开启预览,通过PlayM4_GetData函数获取图像数据,然后转换为OpenCV格式的图像并显示出来。在使用完毕后,通过NET_DVR_StopRealPlay函数关闭预览,通过NET_DVR_Logout函数注销设备,通过NET_DVR_Cleanup函数释放SDK资。 需要注意的是,海康威视SDK的函数返回值有可能是负数,表示操作失败,此时可以通过NET_DVR_GetLastError函数获取错误码进行排查。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZZY_dl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值