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