Python套接字通信完成同一网段下的图像(视频)传输

  1. 将USB摄像头连结到客户端电脑上,如果在虚拟机中,注意设置外接设备USB为3.0,且确保连接到虚拟机中而非主机当中;
  2. 如果客户端和服务器都在同一台主机上运行的话,无需修改 self.TargetIP = ('127.0.0.1', 6666),直接使用本地环回地址即可;
  3. 如果客户端和服务器不处于同一主机的话,注意修改self.TargetIP,需要客户端和服务器处于同一网段,且能相互ping通;
  4. Python套接字传递的数据类型需要注意和统一,所以需要先打包数据,通过套接字发送到服务器之后,然后在解包数据,通过numpy再还原成图像数据格式;
  5. 调试过程中如果出现address already in use等报错信息的话,说明套接字进程资源没有成功释放,通过以下命令查看进程号: netstat -nap | grep 6666 再通过:kill -9 进程号 杀死进程释放资源;
  6. 在opencv中引发ssize.area()>0错误的话可能是因为摄像头设备号写错了,操作了空的设备;

关闭eth0或者某个网络接口

因为所用的客户端笔记本电脑上有两个网口,一个eth0和wlan0,其中eth0和服务器不处于同一网段,wlan0和服务器处于同一网段,但是客户端ping服务器的时候,数据都是从eth0发送的,而不是从wlan0,从而导致无法ping通,所以采用如下方法关闭eth0网口。

  • ifdown eth0 关闭eth0网络接口 
  • ifup eth0 打开eth0网络接口 
  • 如果上面的命令无效,请使用下面的 (注意使用root用户)
  • ifconfig eth0 down 关闭eth0接口 
  • ifconfig eth0 up 打开eth0接口

TCP客户端代码:

import socket
import struct
import time
import cv2
import numpy

class Config(object):

    def __init__(self):
        self.TargetIP = ('127.0.0.1', 6666)
        self.resolution = (640, 480)  # 分辨率
        self.img_fps = 15  # 帧数
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.client.connect(self.TargetIP)
        self.img = ''
        self.img_data = ''

    def RT_Image(self):
        print("请准备好摄像头")
        camera = cv2.VideoCapture(0)
        print("即将发送数据")
        # 设置图片格式为.jpg的图片质量,其值为0---100(数值越大质量越高),默认95
        img_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.img_fps]

        while True:
            # time.sleep(0.1)
            _, self.img = camera.read()
            self.img = cv2.resize(self.img, self.resolution)

            # cv2.imshow("client", self.img)
            _, 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])
                # 头部文件的长度
                print(len(packet))
                self.client.send(packet)
                # 具体图像的数据长度
                print(len(self.img_data))
                self.client.send(self.img_data)

            except Exception as e:
                print(e.args)
                if cv2.waitKey(10) == 27:
                    cv2.destroyAllWindows()
                    camera.release()
                    break


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

TCP服务器代码:

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

class Camera_Connect_Object(object):
    def __init__(self, TargetIP=('', 6666)):
        # 不传参的话默认使用本机环回地址
        self.TargetIP = TargetIP
        # 分辨率
        self.resolution = (640, 480)
        # 双方确定传输帧数,(888)为校验值
        self.src = 888 + 15
        # 图片播放时间间隔
        self.interval = 0
        # 每秒传输多少帧数
        self.img_fps = 15

        # 套接字部分
        self.Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.Server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.Server.bind(self.TargetIP)
        self.Server.listen(5)
        self.client = ""
        self.addr = ""
        self.name = ""

        # 接受客户端信息所用变量
        self.buf = b""

    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)
            # 第一次接受头部信息
            temp_data = self.client.recv(12)
            if len(temp_data) == 0:
                print("连接可能突然被中断了")
                continue
            # 按格式解码,确定帧数和分辨率
            info = struct.unpack('lhh', temp_data)
            # 获取读的图片总长度
            buf_size = int(info[0])
            print(buf_size)

            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.fromstring(self.buf, dtype='uint8')    # 按uint8转换为图像矩阵
                    self.image = cv2.imdecode(data, 1)                  # 图像解码
                    cv2.imshow(self.name, self.image)                   # 展示图片

                except Exception as e:
                    print(e.args)
                    pass

                finally:
                    if cv2.waitKey(10) == 27:  # 每10ms刷新一次图片,按‘ESC’(27)退出
                        self.client.close()
                        cv2.destroyAllWindows()
                        break


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

 参考链接:https://blog.csdn.net/a19990412/article/details/80930725?utm_source=blogkpcl0

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值