从局域网监控到广域网实时监控的实现




1. 局域网视频监控

  • socket 实现
  • 测试可在同一台电脑运行
  • 条件:处在同一局域网,并知道被监控端的 ip
  • 观看监控视频时同步保存视频到本地


服务端 :等待接受视频信号

import socket
import cv2
import struct
import numpy
import threading
import time


class Camera_Connect_Object(object):
    def __init__(self, TargetIP=('', 6666)): #端口可以自己选
        self.TargetIP = TargetIP
        self.resolution = (640, 480)
        self.img_fps = 25

        now_time = str(time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())))
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        avi_name = now_time
        self.out = cv2.VideoWriter(avi_name+ '.avi' ,fourcc, 25.0, (640,480))

        self.Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.Server.bind(self.TargetIP)
        self.Server.listen(5)

    def RT_Image(self):
        self.client, self.addr = self.Server.accept()
        self.name = self.addr[0] + " Camera"
        print(self.name)
        while True:
            # time.sleep(0.3)  # sleep for 0.3 seconds
            tempdata = self.client.recv(8)
            if len(tempdata) == 0:
                print("+1")
                continue
            info = struct.unpack('lhh', tempdata)
            buf_size = int(info[0])

            if buf_size:
                try:
                    self.buf = b""
                    self.temp_buf = self.buf
                    while buf_size:
                        self.temp_buf = self.client.recv(buf_size)
                        buf_size -= len(self.temp_buf)
                        self.buf += self.temp_buf
                    data = numpy.frombuffer(self.buf, dtype='uint8')

                    self.image = cv2.imdecode(data, 1)
                    print(self.image.shape)
                    self.out.write(self.image)
                    cv2.imshow(self.name, self.image)
                except Exception as e:
                    print(e.args)
                    pass
                finally:
                    if cv2.waitKey(10) == 27:
                        self.client.close()
                        self.out.release()
                        cv2.destroyAllWindows()
                        break

    def Get_data(self):
        showThread = threading.Thread(target=self.RT_Image)
        showThread.start()
        showThread.join()


if __name__ == '__main__':
    camera = Camera_Connect_Object()
    camera.Get_data()


客户端 :向服务端发送视频信号

import socket
import struct
import time
import cv2
import numpy


class Config(object):
    def __init__(self):
        self.TargetIP = ('192.168.xx.xxx', 6666) #填自己电脑的ip
        self.resolution = (640, 480)  # 分辨率
        self.img_fps = 25  # each second send pictures
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.connect(self.TargetIP)
        self.img = ''
        self.img_data = ''

    def RT_Image(self):
        camera = cv2.VideoCapture(0)
        img_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.img_fps]

        while True:
            time.sleep(0.1)  # sleep for 0.1 seconds
            _, self.img = camera.read()

            self.img = cv2.resize(self.img, self.resolution)

            _, img_encode = cv2.imencode('.jpg', self.img, img_param)
            img_code = numpy.array(img_encode)
            self.img_data = img_code.tostring()  # bytes data
            try:

                packet = struct.pack(b'lhh', len(self.img_data), self.resolution[0],
                                     self.resolution[1])
                self.server.send(packet)
                self.server.send(self.img_data)
            
            except Exception as e:
                print(e.args)
                camera.release()
                return


if __name__ == '__main__':
    config = Config()
    config.RT_Image()


2. 与云服务器远程通信

  • socket 实现
  • 服务端在云服务器运行,等待客户端连接
  • 通信过程,客户端发送信息至云端,云端将接收到的信息返回到客户端,并加上系统本地时间


服务端 :接受客户端的消息并回复

import socket
import time

# 创建一个tcp/ip协议的套接字
tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "172.17.xx.xx" #填写云服务器的私网 ip
port = 8888 #记得要先开放端口
buffer_size = 1024
address = (host, port)
# 开始绑定地址
tcpSocket.bind(address)
tcpSocket.listen(5)

while True:
    print("服务器等待被连接中。。。。。")
    clientSock, client_addr = tcpSocket.accept()
    print("已经连接到客户端,连接地址:{0}".format(client_addr))
    try:
        while True:
            data = clientSock.recv(buffer_size)
            print("接收到客户端的数据为:{0}".format(str(data, encoding="utf8")))
            if data.upper() == "EXIT":
                break
            now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            clientSock.send(bytes("时间:{0},接受的内容为:{1}".format(now_time, str(data, encoding="utf8")), encoding="utf8"))

    except Exception as e:
        print(e)
    finally:
        clientSock.close()

tcpSocket.close()


客户端 :向服务器发送数据,也可接收服务器返回的数据

import socket
import time

# 创建一个tcp/ip协议的套接字
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "39.97.xx.xx" #填写自己的公网 ip
port = 8888 #与服务端的端口一致
buffer_size = 1024
address = (host, port)
# 开始连接服务器地址
clientSocket.connect(address)

if clientSocket is None:
    print("无法连接当前的服务器!\n")
else:
    print("已经连接服务器---> oK\n")
    while True:
        data = input("(q 退出)发送数据到服务器:")
        if data== "q":
            clientSocket.send(bytes("EXIT", encoding="utf8"))
            # 关闭当前的客户端
            clientSocket.close()
            break

        clientSocket.send(bytes(data, encoding="utf8"))
        # 接收服务器发送的数据
        data = clientSocket.recv(buffer_size)
        # 打印接收的数据
        print("服务器返回:{0}\n".format(str(data, encoding="utf8")))


3. 云服务器中转实现远程监控

  • 先在云服务器运行服务端,等待被连接
  • 云服务器可以接收被监控方客户端的视频信号,并保存为 avi 格式存放在云服务器上
  • 云服务器同样可以接收用户客户端的请求,将实时的视频信号转发给用户
  • 用户在远程观看视频的同时,视频也将被保存到本地
  • 顺序是这样的:服务端等待、相机连接到服务器并发送一帧画面、服务器接收一帧画面并保存为 avi 格式、用户连接到服务器查看正在传输的数据并保存视频到本地


客户端 1 :向服务器发送数据,经压缩的图像

import socket
import struct
import time
import cv2
import numpy


class Config(object):
    def __init__(self):
        self.TargetIP = ('39.97.xx.xx', 8888) #使用云服务器公网 ip
        self.resolution = (640, 480)  # 分辨率
        self.img_fps = 70  # each second send pictures
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.connect(self.TargetIP)
        print('采集者已连接服务器!')

    def RT_Image(self):
        camera = cv2.VideoCapture(0)
        img_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.img_fps]
        ret, frame = camera.read()
        while ret:
            time.sleep(0.1)  # sleep for 0.1 seconds
            ret, frame = camera.read()
            
            frame = cv2.resize(frame, self.resolution)
            _, img_encode = cv2.imencode('.jpg', frame, img_param)
            img_code = numpy.array(img_encode)
            self.img_data = img_code.tostring()  # bytes data
            try:
                buf_size = len(self.img_data)
                if buf_size>0 and buf_size<500000:
                    packet = struct.pack(b'i',buf_size)
                    self.server.send(packet)
                    self.server.send(self.img_data)
            
            except Exception as e:
                print(e.args)
                camera.release()
                return

if __name__ == '__main__':
    config = Config()
    config.RT_Image()


客户端 2 :从服务器读取实时数据并解析,保存视频到本地

import socket
import struct
import time
import cv2
import numpy
import threading
import sys


class FromServer(object):
    def __init__(self):
        self.TargetIP = ('39.97.xx.xx', 9999) #公网 ip 端口不要与客户端 1 的重复了
        self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.clientSocket.connect(self.TargetIP)

        self.resolution = (640, 480)
        self.img_fps = 70
    

    def RT_Image(self):
        video_name = bytes.decode(struct.unpack('14s', (self.clientSocket.recv(14)))[0])
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        out = cv2.VideoWriter(video_name+ '.avi' ,fourcc, 35.0, (640,480))
        try:
            while True:
                tempdata = self.clientSocket.recv(4)
                if cv2.waitKey(10) == 27:
                    self.clientSocket.close()
                    out.release()
                    sys.exit()
                    break
                if len(tempdata) == 4:
                    info = struct.unpack('i', tempdata)
                    buf_size = int(info[0])
                    if buf_size>0 and buf_size<500000:
                        try:
                            buf = b""
                            temp_buf = buf
                            while buf_size:
                                temp_buf = self.clientSocket.recv(buf_size)
                                buf_size -= len(temp_buf)
                                buf += temp_buf
                            data = numpy.frombuffer(buf, dtype='uint8')
                            self.image = cv2.imdecode(data, 1)
                            out.write(self.image)
                            cv2.imshow(video_name, self.image)
                        except Exception as e:
                            print(e)
                            pass
                    else:
                        buf_size = 0
        except Exception as e:
            self.clientSocket.close()
            out.release()

    def Get_data(self):
        showThread = threading.Thread(target=self.RT_Image)
        showThread.start()
        showThread.join()


if __name__ == '__main__':
    data = FromServer()
    data.Get_data()


服务端 :中转视频信号并保存数据在云端

import socket
import cv2
import struct
import numpy
import threading
import time


class Transstation(object):
    def __init__(self, cam_ip, user_ip):
        self.cam_ip = cam_ip
        self.cam_Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.cam_Server.bind(self.cam_ip)
        self.cam_Server.listen(5)
        print('服务器接收工作准备初始化完成!')

        self.user_ip = user_ip
        self.tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcpSocket.bind(self.user_ip)
        self.tcpSocket.listen(5)
        print('服务器发送工作准备初始化完成!')

        self.now_time = ''
        self.resolution = (640, 480)
        self.img_fps = 70

    def receiveVideoThread(self):     
        print("等待相机中。。。。。")
        clientSock, client_addr = self.cam_Server.accept()
        print("已经连接到相机,连接地址:{0}".format(client_addr))
        self.now_time = str(time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())))
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        out = cv2.VideoWriter(self.now_time+ '.avi' ,fourcc, 35.0, (640,480))
        print('正在保存视频 %s.avi'%self.now_time)
        flag = 1
        while True:
            tempdata = clientSock.recv(4)
            if cv2.waitKey(10) == 27:
                clientSock.close()
                out.release()
                break
            if len(tempdata) == 4:
                info = struct.unpack('i', tempdata)
                buf_size = int(info[0])
                if buf_size>0 and buf_size<500000:
                    try:
                        buf = b""
                        temp_buf = buf
                        while buf_size:
                            temp_buf = clientSock.recv(buf_size)
                            buf_size -= len(temp_buf)
                            buf += temp_buf
                        data = numpy.frombuffer(buf, dtype='uint8')
                        img = cv2.imdecode(data, 1)
                        self.image = img
                        out.write(img)
                        
                    except Exception as e:
                        print(e.args)
                        pass
    
    def sendVideoThread(self):
        print("等待用户中。。。。。")
        clientSock, client_addr = self.tcpSocket.accept()
        print("已经连接到用户,地址:{0}".format(client_addr))
        img_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.img_fps]
        s_name = struct.pack(b'14s',str.encode(self.now_time))
        clientSock.send(s_name)
        while True:
            if cv2.waitKey(10) == 27:
                clientSock.close()
                break
            _, img_encode = cv2.imencode('.jpg', self.image, img_param)
            img_code = numpy.array(img_encode)
            img_data = img_code.tostring()
            try:
                packet = struct.pack(b'i',len(img_data))
                clientSock.send(packet)
                clientSock.send(img_data)
            except Exception as e:
                pass

    
    def start_work(self):
        camThread = threading.Thread(target=self.receiveVideoThread)
        usrThread = threading.Thread(target=self.sendVideoThread)
        camThread.start()
        usrThread.start()
        camThread.join()
        usrThread.join()

if __name__ == '__main__':
    cam_ip = ('172.17.xx', 8888) #私网 ip
    usr_ip = ('172.17.xx', 9999)#私网 ip
    server = Transstation(cam_ip,usr_ip)
    server.start_work()




猜你喜欢

转载自blog.csdn.net/fengge2018/article/details/105525972