精华内容
下载资源
问答
  • 海康威视网络摄像头Python SDK

    海康威视网络摄像头Python SDK+移动物体位置检测

     

    文末附 海康威视网络摄像头Python SDK 下载链接

     

    本文参考博客

    https://blog.csdn.net/c20081052/article/details/95082377

    https://blog.csdn.net/pengpengloveqiaoqiao/article/details/89487049

     

    注意:摄像头要在镜头上贴红外滤光片 过滤掉可见光

     

    效果展示,已经过滤到大部分波长可见光,手在镜头前来回移动,红框即检测到移动物体的位置,并框出来(海康威视的摄像头可见光好像不能完全被滤光片过滤掉,但是可以过滤到投影机的画面或者屏幕的画面,不影响使用)

     

    目录

    1.将海康威视的C++  sdk 转化为 Python sdk

    2.调用海康威视Python SDK

    3.调用多个海康威视摄像头

    4. 将多个摄像头画面拼接成一个

    5.挨个摄像头透视变换

    6. 透视变换完后再在拼接后的画面上做动态物体检测,参考博客


    1.将海康威视的C++  sdk 转化为 Python sdk  (本文已经处理完了)

    如何将海康威视的C++  sdk 转化为 Python 可用的sdk ,请参考博主 ciky奇 的文章,链接如下

    https://blog.csdn.net/c20081052/article/details/95082377  如果最后一步Python调用时遇到报错,尝试将所有相关的文件全部复制到Python工程的路径下

    环境:

    1. windows10  64位

    2. opecv

    3. python3

    4.海康威视网络摄像头64位 C++ sdk

        https://www.hikvision.com/cn/download_61.html

        下载SDK_Win64

    5.其他库文件:

       5.1 opencv-python

       5.2 numpy

       5.3 multiprocessing (多进程使用)

    本文已将海康威视C++ sdk转为Python sdk处理好,可以直接下载使用,文末网址分享

     

    如果HKIPCamera 一直报错,找不到模块    ,首先 python 和 opencv要安装好,并且设置好环境变量,如果还是报错:

     

    一般是缺少VC++库的运行时组件,两个方案:

     

    1. 从微软官网下载VC++库的运行时组件:  

    此组件也可以解决其他项目上的很多疑难杂症

    官网链接: https://visualstudio.microsoft.com/zh-hans/downloads/

     

    2、下载一个DirectX修复工具

    链接:https://pan.baidu.com/s/1thfI2SyCpQoToBxuwFnxuA 
    提取码:8aza 

     

    打开后点击   工具----> 选项---->扩展---->开始扩展

     

     

     

    扩展完了以后,此时会默认选中同时更新C++,点击检测并修复,

    如果缺少组件就会自动安装,如果已经安装了但是不是最新的,会自动更新,

    等修复完了,再尝试运行Python程序

     

     

    如果还是一直存在问题,请回头参考博文https://blog.csdn.net/c20081052/article/details/95082377一步一步重新操作

     

    2.调用海康威视Python SDK

     

    import cv2
    import numpy as np
    import HKIPcamera
    
    def get_cam_frame(ip, account, password):
    
        ip = str(ip)  # 摄像头IP地址,要和本机IP在同一局域网
        name = str(account)       # 管理员用户名
        pw = str(password)        # 管理员密码
    
        HKIPcamera.init(ip, name, pw)
    
        while(True): 
            fram = HKIPcamera.getframe()     
            frame = np.array(fram)
            cv2.imshow('frame',frame)
            c = cv2.waitKey(10)
            if c == 27:
                break;
        HKIPcamera.release()
       
    
    if __name__ == '__main__':
    
        get_cam_frame('192.168.1.64', 'admin', '123456')
    
    
    

     

     

    3.调用多个海康威视摄像头

        调用多个摄像头需要用到多进程,多线程不起作用

        在第一步的代码基础上修改一下

     

    import cv2
    import numpy as np
    import HKIPcamera
    from multiprocessing import Process, Queue
    
    def get_cam_frame(frameName, ip, account, password):
        ip = str(ip)  # 摄像头IP地址,要和本机IP在同一局域网
        name = str(account)  # 管理员用户名
        pw = str(password)  # 管理员密码
    
        HKIPcamera.init(ip, name, pw)
    
        while True:
            fram = HKIPcamera.getframe()
            frame = np.array(fram)
            cv2.imshow(frameName, frame)
            c = cv2.waitKey(10)
            if c == 27:
                 break;
        HKIPcamera.release()
    
    
    if __name__ == '__main__':
    
        
         p0 = Process(target=get_cam_frame, args=('frame0', '192.168.1.64', 'admin', '123456',))
         p0.start()
    
        
         p1 = Process(target=get_cam_frame, args=('frame1', '192.168.1.65', 'admin', '123456',))
         p1.start()
         
         # 以此类推   p2 p3 ... pn
    
    
    
    
    
    
    
    

     

        

    4. 将多个摄像头画面拼接成一个

     

           再在上述的代码基础上修改

     

    import cv2
    import numpy as np
    import HKIPcamera
    from multiprocessing import Process, Queue
    import os
    import signal
    
    def get_cam_frame(frameName, ip, account, password, n):
        ip = str(ip)  # 摄像头IP地址,要和本机IP在同一局域网
        name = str(account)  # 管理员用户名
        pw = str(password)  # 管理员密码
    
        HKIPcamera.init(ip, name, pw)
    
        while True:
            fram = HKIPcamera.getframe()
            frame = np.array(fram)
            # 由于摄像头画面是1920*1080,多个拼接的话,画面会非常大,所有重置一下每个摄像头的画面
            frame = cv2.resize(frame, (768, 540), interpolation=cv2.INTER_CUBIC)
            n.put(frame)
            cv2.imshow(frameName, frame)
            c = cv2.waitKey(10)
            if c == 27:
                 break;
        HKIPcamera.release()
    
    
    if __name__ == '__main__':
    
         q0 = Queue(3)
         p0 = Process(target=get_cam_frame, args=('frame0', '192.168.1.64', 'admin', '123456', q0,))
         p0.start()
    
         q1 = Queue(3)
         p1 = Process(target=get_cam_frame, args=('frame1', '192.168.1.65', 'admin', '12345', q1,))
         p1.start()
    
         while True:
             if p0.is_alive() and p1.is_alive():
                 frame0 = q0.get()
                 frame1 = q1.get()
                 # 横着拼
                 full_frame = np.hstack([frame0, frame1])
                 # 竖着拼
                 # full_frame = np.vstack([frame0, frame1])
                 cv2.imshow('full_frame', full_frame)
                 c = cv2.waitKey(10)
                 if c==27:
                     os.kill(p0.pid, signal.SIGTERM)
                     os.kill(p1.pid, signal.SIGTERM)
                     break;
    
    
    
    
    
    
    
    
    
    
    

     

    5.挨个摄像头透视变换

       如果不了解opencv-python透视变换函数的参数,请先看下此博客的透视变换函数介绍,链接如下:

       https://blog.csdn.net/wsp_1138886114/article/details/83374333

       

    import cv2
    import numpy as np
    import HKIPcamera
    from multiprocessing import Process, Queue
    import os
    import signal
    
    def get_cam_frame(frameName, ip, account, password, n):
        ip = str(ip)  # 摄像头IP地址,要和本机IP在同一局域网
        name = str(account)  # 管理员用户名
        pw = str(password)  # 管理员密码
    
        HKIPcamera.init(ip, name, pw)
    
        while True:
            fram = HKIPcamera.getframe()
            frame = np.array(fram)
            # 由于摄像头画面是1920*1080,多个拼接的话,画面会非常大,所有重置一下每个摄像头的画面
            frame = cv2.resize(frame, (768, 540), interpolation=cv2.INTER_CUBIC)
            n.put(frame)
            cv2.imshow(frameName, frame)
            c = cv2.waitKey(10)
            if c == 27:
                 break;
        HKIPcamera.release()
    
    
    
    #第一个摄像头透视变化的四个点
    frame0_x0, frame0_y0, frame0_x1, frame0_y1, frame0_x2, frame0_y2, frame0_x3, frame0_y3 = 0, 0, 0, 0, 0, 0, 0, 0
    #第二个摄像头透视变化的四个点
    frame1_x0, frame1_y0, frame1_x1, frame1_y1, frame1_x2, frame1_y2, frame1_x3, frame1_y3 = 0, 0, 0, 0, 0, 0, 0, 0
    
    
    #简单来写,按照从第一个摄像头开始,鼠标每点击一次,获取一个点
    #例如鼠标第一次点击,就等于给坐标frame0_x0, frame0_y0 赋值, 第二次点击就是给坐标frame0_x1, frame0_y1赋值,以此类推
    
    clickNum = 0
    
    def draw_point(event, x, y, flags, param):
        global frame0_x0, frame0_y0, frame0_x1, frame0_y1, frame0_x2, frame0_y2, frame0_x3, frame0_y3
        global frame1_x0, frame1_y0, frame1_x1, frame1_y1, frame1_x2, frame1_y2, frame1_x3, frame1_y3, clickNum
        if event == cv2.EVENT_LBUTTONDOWN:
            if clickNum == 0:
                frame0_x0 = x
                frame0_y0 = y
            elif clickNum == 1:
                frame0_x1 = x
                frame0_y1 = y
            elif clickNum == 2:
                frame0_x2 = x
                frame0_y2 = y
            elif clickNum == 3:
                frame0_x3 = x
                frame0_y3 = y
            elif clickNum == 4:
                frame1_x0 = x
                frame1_y0 = y
            elif clickNum == 5:
                frame1_x1 = x
                frame1_y1 = y
            elif clickNum == 6:
                frame1_x2 = x
                frame1_y2 = y
            elif clickNum == 7:
                frame1_x3 = x
                frame1_y3 = y
    
            clickNum += 1
    
    
    # 透视变换
    def perspective_transform():
        global frame0, frame1, clickNum
        global frame0_x0, frame0_y0, frame0_x1, frame0_y1, frame0_x2, frame0_y2, frame0_x3, frame0_y3
        global frame1_x0, frame1_y0, frame1_x1, frame1_y1, frame1_x2, frame1_y2, frame1_x3, frame1_y3
        
        if clickNum==8:
            W_cols, H_rows = frame0.shape[:2]
    
            pts0_1 = np.float32(
                [[frame0_x0, frame0_y0], [frame0_x1, frame0_y1],
                 [frame0_x2, frame0_y2], [frame0_x3, frame0_y3]])
            pts0_2 = np.float32([[0, 0], [W_cols, 0], [0, H_rows], [W_cols, H_rows]])
            M0 = cv2.getPerspectiveTransform(pts0_1, pts0_2)
            frame0 = cv2.warpPerspective(frame0, M0, (W_cols, H_rows))
    
            # 这里的变换需要减去第一个摄像头的画面的宽度,768
            pts1_1 = np.float32(
                [[frame1_x0-768, frame1_y0], [frame1_x1-768, frame1_y1],
                 [frame1_x2-768, frame1_y2], [frame1_x3-768, frame1_y3]])
            pts1_2 = np.float32([[0, 0], [W_cols, 0], [0, H_rows], [W_cols, H_rows]])
            M1 = cv2.getPerspectiveTransform(pts1_1, pts1_2)
            frame1 = cv2.warpPerspective(frame1, M1, (W_cols, H_rows))
     
    
    if __name__ == '__main__':
    
         q0 = Queue(3)
         p0 = Process(target=get_cam_frame, args=('frame0', '192.168.1.64', 'admin', '123456', q0,))
         p0.start()
    
         q1 = Queue(3)
         p1 = Process(target=get_cam_frame, args=('frame1', '192.168.1.65', 'admin', '123456', q1,))
         p1.start()
    
         cv2.namedWindow('full_frame')
         # 鼠标点击事件
         cv2.setMouseCallback('full_frame', draw_point)
    
         while True:
             if p0.is_alive() and p1.is_alive():
                 frame0 = q0.get()
                 frame1 = q1.get()
    
                 # 透视变换
                 perspective_transform()
                 # 透视变换完再拼接
                 # 横着拼
                 full_frame = np.hstack([frame0, frame1])
                 # 竖着拼
                 #full_frame = np.vstack([frame0, frame1])
                 cv2.imshow('full_frame', full_frame)
                 c = cv2.waitKey(10)
                 if c==27:
                     os.kill(p0.pid, signal.SIGTERM)
                     os.kill(p1.pid, signal.SIGTERM)
                     break;
    
    
    
    
    
    
    
    
    
    
    

     

     

    6. 透视变换完后再在拼接后的画面上做动态物体检测,参考博客

     https://blog.csdn.net/pengpengloveqiaoqiao/article/details/89487049

       

    import cv2
    import numpy as np
    import HKIPcamera
    from multiprocessing import Process, Queue
    import os
    import signal
    
    def get_cam_frame(frameName, ip, account, password, n):
        ip = str(ip)  # 摄像头IP地址,要和本机IP在同一局域网
        name = str(account)  # 管理员用户名
        pw = str(password)  # 管理员密码
    
        HKIPcamera.init(ip, name, pw)
    
        while True:
            fram = HKIPcamera.getframe()
            frame = np.array(fram)
            # 由于摄像头画面是1920*1080,多个拼接的话,画面会非常大,所有重置一下每个摄像头的画面
            frame = cv2.resize(frame, (768, 540), interpolation=cv2.INTER_CUBIC)
            n.put(frame)
            cv2.imshow(frameName, frame)
            c = cv2.waitKey(10)
            if c == 27:
                 break;
        HKIPcamera.release()
    
    
    
    #第一个摄像头透视变化的四个点
    frame0_x0, frame0_y0, frame0_x1, frame0_y1, frame0_x2, frame0_y2, frame0_x3, frame0_y3 = 0, 0, 0, 0, 0, 0, 0, 0
    #第二个摄像头透视变化的四个点
    frame1_x0, frame1_y0, frame1_x1, frame1_y1, frame1_x2, frame1_y2, frame1_x3, frame1_y3 = 0, 0, 0, 0, 0, 0, 0, 0
    
    
    #简单来写,按照从第一个摄像头开始,鼠标每点击一次,获取一个点
    #例如鼠标第一次点击,就等于给坐标frame0_x0, frame0_y0 赋值, 第二次点击就是给坐标frame0_x1, frame0_y1赋值,以此类推
    
    clickNum = 0
    
    def draw_point(event, x, y, flags, param):
        global frame0_x0, frame0_y0, frame0_x1, frame0_y1, frame0_x2, frame0_y2, frame0_x3, frame0_y3
        global frame1_x0, frame1_y0, frame1_x1, frame1_y1, frame1_x2, frame1_y2, frame1_x3, frame1_y3, clickNum
        if event == cv2.EVENT_LBUTTONDOWN:
            if clickNum == 0:
                frame0_x0 = x
                frame0_y0 = y
            elif clickNum == 1:
                frame0_x1 = x
                frame0_y1 = y
            elif clickNum == 2:
                frame0_x2 = x
                frame0_y2 = y
            elif clickNum == 3:
                frame0_x3 = x
                frame0_y3 = y
            elif clickNum == 4:
                frame1_x0 = x
                frame1_y0 = y
            elif clickNum == 5:
                frame1_x1 = x
                frame1_y1 = y
            elif clickNum == 6:
                frame1_x2 = x
                frame1_y2 = y
            elif clickNum == 7:
                frame1_x3 = x
                frame1_y3 = y
    
            clickNum += 1
    
    
    # 透视变换
    def perspective_transform():
        global frame0, frame1, clickNum
        global frame0_x0, frame0_y0, frame0_x1, frame0_y1, frame0_x2, frame0_y2, frame0_x3, frame0_y3
        global frame1_x0, frame1_y0, frame1_x1, frame1_y1, frame1_x2, frame1_y2, frame1_x3, frame1_y3
    
        if clickNum==8:
            W_cols, H_rows = frame0.shape[:2]
    
            pts0_1 = np.float32(
                [[frame0_x0, frame0_y0], [frame0_x1, frame0_y1],
                 [frame0_x2, frame0_y2], [frame0_x3, frame0_y3]])
            pts0_2 = np.float32([[0, 0], [W_cols, 0], [0, H_rows], [W_cols, H_rows]])
            M0 = cv2.getPerspectiveTransform(pts0_1, pts0_2)
            frame0 = cv2.warpPerspective(frame0, M0, (W_cols, H_rows))
    
            # 这里的变换需要减去第一个摄像头的画面的宽度,768
            pts1_1 = np.float32(
                [[frame1_x0-768, frame1_y0], [frame1_x1-768, frame1_y1],
                 [frame1_x2-768, frame1_y2], [frame1_x3-768, frame1_y3]])
            pts1_2 = np.float32([[0, 0], [W_cols, 0], [0, H_rows], [W_cols, H_rows]])
            M1 = cv2.getPerspectiveTransform(pts1_1, pts1_2)
            frame1 = cv2.warpPerspective(frame1, M1, (W_cols, H_rows))
    
    
    
    
    
    if __name__ == '__main__':
    
         q0 = Queue(3)
         p0 = Process(target=get_cam_frame, args=('frame0', '192.168.1.64', 'admin', '123456', q0,))
         p0.start()
    
         q1 = Queue(3)
         p1 = Process(target=get_cam_frame, args=('frame1', '192.168.1.65', 'admin', '123456', q1,))
         p1.start()
    
         cv2.namedWindow('full_frame')
         # 鼠标点击事件
         cv2.setMouseCallback('full_frame', draw_point)
    
         kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
         fgbg = cv2.createBackgroundSubtractorMOG2()
         while True:
             if p0.is_alive() and p1.is_alive():
                 frame0 = q0.get()
                 frame1 = q1.get()
    
                 # 透视变换
                 perspective_transform()
                 # 透视变换完再拼接
                 # 横着拼
                 full_frame = np.hstack([frame0, frame1])
                 # 竖着拼
                 #full_frame = np.vstack([frame0, frame1])
    
                 fgmask = fgbg.apply(full_frame)
                 mask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
                 contours, _ = cv2.findContours(fgmask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
                 for c in contours:
                     if 100 < cv2.contourArea(c) < 40000:
                         x, y, w, h = cv2.boundingRect(c)
                         cv2.rectangle(full_frame, (x, y), (x + w, y + h), (0, 0, 255))
    
    
                 cv2.imshow('full_frame', full_frame)
                 c = cv2.waitKey(10)
                 if c==27:
                     os.kill(p0.pid, signal.SIGTERM)
                     os.kill(p1.pid, signal.SIGTERM)
                     break;
    
    
    
    
    
    
    
    
    
    
    

     

     

    最后再写个Json或者XML(我没写)保存一下透视变换的点位信息完整工程分享

    链接:https://pan.baidu.com/s/1zHwWCW5dW-XR6a98RfEuew 
    提取码:6gfc

     

     

     

     

    展开全文
  • Python调用海康威视网络摄像头进行远程人脸识别 Python调用网络摄像头 RTSP (Real Time Streaming Protocol),是一种语法和操作类似 HTTP 协议,专门用于音频和视频的应用层协议。 和 HTTP 类似,RTSP 也使用 URL ...

    Python调用网络摄像头

    RTSP (Real Time Streaming Protocol),是一种语法和操作类似 HTTP 协议,专门用于音频和视频的应用层协议。 和 HTTP 类似,RTSP 也使用 URL 地址。摄像机传输数据用的是码流,高清网络摄像机产品编码器都会产生两个编码格式,称为主码流和子码流,即双码流技术。双码流能实现本地和远程传输的两种不同的带宽码流需求,本地传输可以用主码流,能获得更清晰的存储录像,远程传输就因为带宽限制的原因,而使用子码流来获得流畅的图像和录像。不同摄像头厂家的RTSP协议地址有所不同,查找到各大厂家的协议格式如下:

    海康:

    rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream
    #1) username  用户名,常用 admin
    #2) password  密码,常用 12345
    #3) ip        摄像头IP,如 192.0.0.64
    #4) port      端口号,默认为 554,可以不写
    #5) codec     视频编码模式,有 h264、MPEG-4、mpeg4 等,可以不写
    #6) channel   通道号,起始为1,例如通道1,则为 ch1
    #7) subtype   码流类型,主码流为 main,辅码流为 sub
    

    大华:

    rtsp://[username]:[password]@[ip]:[port]/cam/realmonitor?[channel=1]&[subtype=1] 
    #1) username、password、ip、port 同上
    #2) channel  通道号,起始为1,例如通道2,则为 channel=2
    #3) subtype  码流类型,主码流为0(即 subtype=0),辅码流为1(即 subtype=1)
    

    宇视:

    rtsp://{用户名}:{密码}@{ip}:{port}/video1/2/3#1)video1/2/3表示主码流,子码流,三码流(可以不用)
    #2)其他一样
    

    Python调用海康威视网络摄像头并实时显示的例程如下:

    import cv2
    
    cap = cv2.VideoCapture("rtsp://admin:a123456789@121.248.50.30/h264/ch1/main/av_stream")
    while True:
        ret, frame = cap.read()
        cv2.imshow("Video", frame)
        cv2.waitKey(1)
    

    画面显示效果良好,传输25fps 1920×1080的复合流相比海康威视官方监视平台约有1s的时延。

    调用网络摄像头进行人脸检测与人脸识别

    调用Python模块face_recognition进行基于网络摄像头的人脸识别功能开发,face_recognition基于dlib中的深度学习模型,用Labeled Faces in the Wild人脸数据集进行测试,有高达99.38%的准确率,但对亚洲人脸的识别准确率尚待提升。

    face_recognition模块能够基于本地摄像头实现人脸识别并流畅地显示画面,但网络摄像头添加了人脸检测和人脸识别功能后,画面延迟和卡顿现象十分严重,解决措施:1. 降低人脸检测和人脸识别的频率,每0.2秒进行一次人脸检测,每2秒进行一次人脸识别;2. 采用多线程,将远程视频画面的获取与人脸检测识别分开处理,效果有所改善。

    最终代码:

    import os
    import cv2
    import queue
    import threading
    import face_recognition
    import numpy as np
    
    q = queue.Queue()
    
    
    # 线程1获取网络摄像头图像
    def Receive():
        print("Start Reveive")
        cap = cv2.VideoCapture("rtsp://admin:a123456789@121.248.50.30/h264/ch1/main/av_stream")
        ret, frame = cap.read()
        q.put(frame)
        while ret:
            ret, frame = cap.read()
            q.put(frame)
    
    
    # 线程2进行人脸检测识别并显示
    def Display():
        print("Start Displaying")
    
        # 加载人脸数据库并学习
        database_path = "./Face_Database/"
        filenames = os.listdir(database_path)
    
        image_set = []
        known_face_names = []
        known_face_encodings = []
    
        for filename in filenames:
            image_set.append(face_recognition.load_image_file(database_path + filename))
            known_face_names.append(filename.split(".")[0])
    
        for image in image_set:
            known_face_encodings.append(face_recognition.face_encodings(image)[0])
    
        # 检测识别人脸及显示
        face_locations = []
        face_names = []
        count = 0
        while True:
            if not q.empty():
                count += 1
    
                frame = q.get()
                small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
                rgb_small_frame = small_frame[:, :, ::-1]
    
                # 每0.2秒进行一次人脸检测
                if count % 5 == 0:
                    face_locations = face_recognition.face_locations(rgb_small_frame)
    
                # 每2秒进行一次人脸识别
                if count % 50 == 0:
                    face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
                    face_names = []
    
                    for face_encoding in face_encodings:
    
                        matches = face_recognition.compare_faces(known_face_encodings, face_encoding, tolerance=0.48)
                        name = "Unknown"
    
                        face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
                        best_match_index = np.argmin(face_distances)
    
                        if matches[best_match_index]:
                            name = known_face_names[int(best_match_index)]
    
                        face_names.append(name)
    
                # 显示人脸定位框及姓名
                for (top, right, bottom, left), name in zip(face_locations, face_names):
                    top *= 4
                    right *= 4
                    bottom *= 4
                    left *= 4
    
                    cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
                    cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
                    cv2.putText(frame, name, (left + 6, bottom - 6), cv2.FONT_HERSHEY_DUPLEX, 1.0, (255, 255, 255), 1)
    
                cv2.imshow('Video', frame)
    
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break
    
    
    if __name__ == '__main__':
        p1 = threading.Thread(target=Receive)
        p2 = threading.Thread(target=Display)
        p1.start()
        p2.start()
    
    展开全文
  • windows下python3.7调用海康威视网络摄像头sdk CH-HCNetSDKV6.1.4.42_build20200527_win64
  • 切换选项卡为Release和x64,修改配置类型为动态库(.dll) 项目下添加3rdparty文件夹,在里面添加海康威视sdk的头文件和库文件: VC++目录->包含目录中添加如下头文件路径(修改python目录到你自己的): 注意使用了...

    本文参考以下博文加自己的实践,发现有些步骤是不必要的,例如不需要为opencv等第三方库指定路径

    https://blog.csdn.net/c20081052/article/details/95082377
    https://www.ryannn.com/archives/hikvision/comment-page-2#comments
    https://blog.csdn.net/GottaYiWanLiu/article/details/106187962

    运行环境:

    Win10系统,64位,Anaconda3

    python 3.7.9(基于anaconda环境)

    vcpkg(boost,opencv3)

    Visual Studio 2019

    硬件:DS-2CD3T56DWD-I5

    相机SDK: 设备网络SDK_V6.1.4.42(for Windows x64)

    准备工作

    1、海康SDK下载

    下载地址:https://www.hikvision.com/cn/download_61.html

    选择自己对应的系统平台版本,我这边选的是设备网络SDK_Win64 :CH-HCNetSDKV6.1.4.42_build20200527_win64

    该文件夹下主要是头文件和库文件。

    2、下载安装vcpkg

    vcpkg如何安装请参考别的博客。安装完以后,命令行cd至vcpkg根目录,然后命令行输入

    ./vcpkg install boost:x64-windows
    ./vcpkg install opencv3:x64-windows
    

    即可安装boost和opencv3。

    3、安装Swig

    Swig是用来封装库的,下载链接:http://www.swig.org/download.html

    我安装的版本是swigwin-4.0.2:http://prdownloads.sourceforge.net/swig/swigwin-4.0.2.zip

    然后将安装目录添加至环境变量path

    4、下载OpenCV-swig接口文件

    下载地址:https://github.com/renatoGarcia/opencv-swig

    我们主要会用到其目录下lib文件夹中的文件opencv文件夹和opencv.i接口文件
    在这里插入图片描述

    实现方案

    1. 使用swig编译生成python和c++数据交换需要的.py和.cxx文件

    新建一个文件夹,例如HicVision_python_SDK文件夹。将下载的opencv-swig\lib下的opencv.i和opencv文件夹放入新建的HicVision_python_SDK文件夹中。

    复制以下三个文件,到新建的HicVision_python_SDK文件夹中。注意代码中的字符串不要出现中文即可避免编码问题。

    HKIPcamera.i

    /*  Example of wrapping a C function that takes a C double array as input using
     *  numpy typemaps for SWIG. */
    %module HKIPcamera
    %include <opencv/mat.i>
    %cv_mat__instantiate_defaults
    %header %{
        /*  Includes the header in the wrapper code */
        #include "HKIPcamera.h"
    %}
     
    %include "HKIPcamera.h"
    

    HKIPcamera.h

    #include <opencv2/opencv.hpp>
    using namespace cv;
     
    void init(char* ip, char* usr, char* password);
    Mat getframe();
    void release();
    

    HKIPcamera.cpp

    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <opencv2\opencv.hpp>
    #include <iostream>
    #include <time.h>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <windows.h>
    #include "HCNetSDK.h"
    #include "plaympeg4.h"
     
    #define USECOLOR 1
     
    using namespace cv;
    using namespace std;
     
    //--------------------------------------------
    int iPicNum = 0;//Set channel NO.
    LONG nPort = -1;
    HWND hWnd = NULL;
    CRITICAL_SECTION g_cs_frameList;
    list<Mat> g_frameList;
    LONG lUserID;
    NET_DVR_DEVICEINFO_V30 struDeviceInfo;
    HANDLE hThread;
    LONG lRealPlayHandle = -1;
     
    void yv12toYUV(char *outYuv, char *inYv12, int width, int height, int widthStep)
    {
    	int col, row;
    	unsigned int Y, U, V;
    	int tmp;
    	int idx;
    	for (row = 0; row < height; row++)
    	{
    		idx = row * widthStep;
    		int rowptr = row * width;
     
    		for (col = 0; col < width; col++)
    		{
    			tmp = (row / 2)*(width / 2) + (col / 2);
    	
    			Y = (unsigned int)inYv12[row*width + col];
    			U = (unsigned int)inYv12[width*height + width * height / 4 + tmp];
    			V = (unsigned int)inYv12[width*height + tmp];
     
    			outYuv[idx + col * 3] = Y;
    			outYuv[idx + col * 3 + 1] = U;
    			outYuv[idx + col * 3 + 2] = V;
    		}
    	}
    }
     
    //解码回调 视频为YUV数据(YV12),音频为PCM数据
    void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)
    {
    	long lFrameType = pFrameInfo->nType;
     
    	if (lFrameType == T_YV12)
    	{
    #if USECOLOR
    		//int start = clock();
    		static IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3);//得到图像的Y分量  
    		yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth, pFrameInfo->nHeight, pImgYCrCb->widthStep);//得到全部RGB图像
    		static IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3);
    		cvCvtColor(pImgYCrCb, pImg, CV_YCrCb2RGB);
    		//int end = clock();
    #else
    		static IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 1);
    		memcpy(pImg->imageData, pBuf, pFrameInfo->nWidth*pFrameInfo->nHeight);
    #endif
     
    		EnterCriticalSection(&g_cs_frameList);
    		//g_frameList.push_back(pImg);
    		g_frameList.push_back(cv::cvarrToMat(pImg));
    		LeaveCriticalSection(&g_cs_frameList);
    }
     
     
    ///实时流回调
    void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
    {
    	DWORD dRet;
    	switch (dwDataType)
    	{
    	case NET_DVR_SYSHEAD:    //系统头
    		if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号
    		{
    			break;
    		}
    		if (dwBufSize > 0)
    		{
    			if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024))
    			{
    				dRet = PlayM4_GetLastError(nPort);
    				break;
    			}
    			//设置解码回调函数 只解码不显示
    			if (!PlayM4_SetDecCallBack(nPort, DecCBFun))
    			{
    				dRet = PlayM4_GetLastError(nPort);
    				break;
    			}
    			//打开视频解码
    			if (!PlayM4_Play(nPort, hWnd))
    			{
    				dRet = PlayM4_GetLastError(nPort);
    				break;
    			}
    		}
    		break;
     
    	case NET_DVR_STREAMDATA:   //码流数据
    		if (dwBufSize > 0 && nPort != -1)
    		{
    			BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
    			while (!inData)
    			{
    				Sleep(10);
    				inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
    				OutputDebugString(L"PlayM4_InputData failed \n");
    			}
    		}
    		break;
    	}
    }
     
    void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
    {
    	char tempbuf[256] = { 0 };
    	switch (dwType)
    	{
    	case EXCEPTION_RECONNECT:    //预览时重连
    		printf("----------reconnect--------%d\n", time(NULL));
    		break;
    	default:
    		break;
    	}
    }
     
    bool OpenCamera(char* ip, char* usr, char* password)
    {
    	lUserID = NET_DVR_Login_V30(ip, 8000, usr, password, &struDeviceInfo);
    	if (lUserID == 0)
    	{
    		cout << "Log in success!" << endl;
    		return TRUE;
    	}
    	else
    	{
    		printf("Login error, %d\n", NET_DVR_GetLastError());
    		NET_DVR_Cleanup();
    		return FALSE;
    	}
    }
    DWORD WINAPI ReadCamera(LPVOID IpParameter)
    {
    	//---------------------------------------
    	//设置异常消息回调函数
    	NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);
     
    	//cvNamedWindow("Mywindow", 0);
    	//cvNamedWindow("IPCamera", 0);
     
    	//HWND  h = (HWND)cvGetWindowHandle("Mywindow");
    	//h = cvNamedWindow("IPCamera");
    	//---------------------------------------
    	//启动预览并设置回调数据流 
    	NET_DVR_CLIENTINFO ClientInfo;
    	ClientInfo.lChannel = 1;        //Channel number 设备通道号
    	ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流
    	ClientInfo.lLinkMode = 1;       //Main Stream
    	ClientInfo.sMultiCastIP = NULL;
     
    	LONG lRealPlayHandle;
    	lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE);
    	if (lRealPlayHandle < 0)
    	{
    		printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n", NET_DVR_GetLastError());
    		return -1;
    	}
    	else
    		cout << "Call NET_DVR_RealPlay_V30 successful!" << endl;
    	Sleep(-1);
    	if (!NET_DVR_StopRealPlay(lRealPlayHandle))
    	{
    		printf("NET_DVR_StopRealPlay error! Error number: %d\n", NET_DVR_GetLastError());
    		return 0;
    	}
    	NET_DVR_Logout(lUserID);
    	NET_DVR_Cleanup();
    	return 0;
    }
     
     
    void init(char* ip, char* usr, char* password) {
    	//HANDLE hThread;
    	//LPDWORD threadID;
    	//---------------------------------------
    	// 初始化
    	NET_DVR_Init();
    	//设置连接时间与重连时间
    	NET_DVR_SetConnectTime(2000, 1);
    	NET_DVR_SetReconnect(10000, true);
    	OpenCamera(ip, usr, password);
    	InitializeCriticalSection(&g_cs_frameList);
    	hThread = ::CreateThread(NULL, 0, ReadCamera, NULL, 0, 0);
    }
     
    Mat getframe() {
    	Mat frame1;
    	EnterCriticalSection(&g_cs_frameList);
    	while (!g_frameList.size()) {
    		LeaveCriticalSection(&g_cs_frameList);
    		EnterCriticalSection(&g_cs_frameList);
    	}
    	list<Mat>::iterator it;
    	it = g_frameList.end();
    	it--;
    	Mat dbgframe = (*(it));
    	(*g_frameList.begin()).copyTo(frame1);
    	frame1 = dbgframe;
    	g_frameList.pop_front();
    	//imshow("camera", frame1);
    	//waitKey(1);
     
    	g_frameList.clear();   // 丢掉旧的帧
    	LeaveCriticalSection(&g_cs_frameList);
    	return(frame1);
    }
     
    void release() {
    	::CloseHandle(hThread);
    	NET_DVR_StopRealPlay(lRealPlayHandle);
    	//关闭预览
    	NET_DVR_Logout(lUserID);
    	//注销用户
    	NET_DVR_Cleanup();
    }
    

    在这里插入图片描述

    这样HicVision_python_SDK文件夹下就拥有上图红框的所有文件了。然后使用cmd或者powershell,cd到这个路径,执行

    swig -ID:\vcpkg\installed\x64-windows\include -python -c++ HKIPcamera.i
    

    注意将其中的D:\vcpkg修改为自己的vcpkg安装目录。

    执行之后将在该目录生成HKIPcamera.py和HKIPcamera_wrap.cxx。
    在这里插入图片描述

    2. 修改海康SDK下的plaympeg4.h文件

    这里直接参考https://blog.csdn.net/c20081052/article/details/95082377所描述即可:
    在这里插入图片描述

    3、用VS2019编译生成动态链接库文件

    首先创建空C++项目,并且项目命名为HKIPcamera
    在这里插入图片描述
    在这里插入图片描述
    然后将之前文件夹下的三个文件放入项目中:
    在这里插入图片描述

    在这里插入图片描述
    修改上面的编译选项为Release和x64
    在这里插入图片描述
    右键项目属性,切换选项卡为Release和x64,修改配置类型为动态库(.dll)
    在这里插入图片描述

    在这里插入图片描述
    项目下添加3rdparty文件夹,在里面添加海康威视sdk的头文件和库文件:
    在这里插入图片描述
    在这里插入图片描述
    取消安全周期检查:
    在这里插入图片描述

    VC++目录->包含目录中添加如下头文件路径(修改python目录到你自己的):
    注意使用了vcpkg之后,就不需要添加使用vcpkg安装的opencv等库的头文件和.lib了。

    3rdparty\include
    D:\ProgramData\Anaconda3\envs\dust37\Lib\site-packages\numpy\core\include
    D:\ProgramData\Anaconda3\envs\dust37\include
    

    在这里插入图片描述

    VC++目录->库目录中添加如下库的路径:(修改python目录到你自己的)

    D:\ProgramData\Anaconda3\envs\dust37\libs
    3rdparty\lib
    3rdparty\lib\HCNetSDKCom
    

    在这里插入图片描述

    预处理器->预处理器定义中内容如下:

    WIN32
    NDEBUG
    _CONSULE
    _CRT_SECURE_NO_WARNINGS
    

    在这里插入图片描述

    链接器->输入->附加依赖项中添加:
    HCNetSDK.lib
    GdiPlus.lib
    HCAlarm.lib
    HCCore.lib
    HCGeneralCfgMgr.lib
    HCPreview.lib
    PlayCtrl.lib

    注意使用了vcpkg之后,就不需要添加使用vcpkg安装的opencv等库的头文件和.lib了。
    完成以上步骤后,右键工程项目名选择生成,之后会在工程x64文件夹下的Release文件夹下生成.dll和.lib文件如下(红色)
    在这里插入图片描述

    复制一份 HKIPcamera.dll 文件并重命名为 _HKIPcamera.pyd到该目录下,并将海康SDK中的3rdparty\lib下的库文件都复制到该目录),以及将上文中用swig生成的HKIPcamera.py 也复制过来(如上图蓝色)
    最后编写了个test.py也放在上图目录下,其内容如下(主要用来检测是否编译成功了):

    import HKIPcamera
    import time
    import numpy as np
    import matplotlib.pyplot as plt
    import cv2
     
     
    ip = str('10.167.93.111')  # 摄像头IP地址,要和本机IP在同一局域网
    name = str('admin')       # 管理员用户名
    pw = str('abcd1234')        # 管理员密码
    HKIPcamera.init(ip, name, pw)
    # HKIPcamera.getfram()
    #for i in range(100):
    while(True):
        t = time.time()
        fram = HKIPcamera.getframe()
        t2 = time.time()
        cv2.imshow('123', np.array(fram))
        cv2.waitKey(1)
        print(t2-t)
        time.sleep(0.1)
    HKIPcamera.release()
    time.sleep(5)
    HKIPcamera.init(ip, name, pw)
    

    在anaconda的prompt控制台下运行该test.py,会看到python调用SDK的实时画面,其延迟性同网页预览版差不多。但比rtsp流读取的效果好很多~

    至此成功!

    将该库给别人使用

    经过测试,该库给别人使用的唯一条件是目标计算机使用的python版本需要与编译时的python版本完全一致,而不需要在指定目录下安装opencv等库。

    因此放上我个人编译的版本。注意需要使用Python 3.7.9运行。运行时修改test.py中的8-10行为你自己的ip,name和pd

    ip = str('10.167.93.111')  # 摄像头IP地址,要和本机IP在同一局域网
    name = str('admin')       # 管理员用户名
    pw = str('abcd1234')        # 管理员密码
    

    然后使用

    python test.py
    

    即可运行。

    展开全文
  • 接上一篇博客: https://blog.csdn.net/GottaYiWanLiu/article/details/106187962  错误如下: 一、首先要确认已经装好了python和opencv,并且已经在Win10下设置好环境变量,根据你实际安装的路径来,设置好后一...

     

    接上一篇博客:

    https://blog.csdn.net/GottaYiWanLiu/article/details/106187962

     

    错误如下:

     

    一、首先要确认已经装好了python和opencv,并且已经在Win10下设置好环境变量,根据你实际安装的路径来,设置好后一步步确认。

     

     

     

    二、 如果第一步设置完以后还是报错,一般是缺少VC++库的运行时组件,有两个解决方案:

     

    1. 从微软官网下载VC++库的运行时组件:  

    此组件也可以解决其他项目上的很多疑难杂症

    官网链接: https://visualstudio.microsoft.com/zh-hans/downloads/

     

     

    2、下载一个DirectX修复工具

    链接:https://pan.baidu.com/s/1thfI2SyCpQoToBxuwFnxuA 
    提取码:8aza 
     

    打开后点击   工具----> 选项---->扩展---->开始扩展

     

     

     

    扩展完了以后,此时会默认选中同时更新C++,点击检测并修复,

    如果缺少组件就会自动安装,如果已经安装了但是不是最新的,会自动更新,

    等修复完了,再尝试运行Python程序

     

    展开全文
  • 部署环境 由于实验室只有无线网没有有线网,在这里依靠wifi路由器做出一个有线网。 wifi路由器根据wifi配置有线网 ip 192.168.113.17 ...在这里是网络已经可以联通。 此时摄像头默认的ip地址是192.168.1.64 ...
  • 防止一些意外,故转载自:Python调用海康威视网络相机之——python调用海康威视C++的SDK 运行环境 Win10系统,64位,Anaconda3 python 3.5.5(基于anaconda环境) opencv 3.4.2 (早前就已经安装了,本文不会讲如何...
  • /usr/bin/python import cv2 # 参数 # -------------------------------------- 这是一条分割线 -------------------------------------- # -------------------------------------- 摄像机的:用户...
  • 上一篇文章讲到了如何在NVIDIA Jetson TX2上手动编译opencv源码使用opencv-python并且调用板载摄像头(只能手动编译安装)。 这篇文章记录一下我用TX2连接海康威视网口相机的过程 相机型号:DS-2CD5028FWD/E2-IB IP...

空空如也

空空如也

1 2
收藏数 25
精华内容 10
关键字:

python海康威视网络摄像头

python 订阅