上位机知识篇---无线数据传输
本文将进行使用python将一端获取的图像数据经过网络处理后传输到另一端上的实例代码以及详细解释
以下是一个使用 Python 实现图像数据网络传输的完整实例,包含发送端和接收端代码,并附详细解释:
图像数据网络传输示例
发送端代码 (sender.py
)
import cv2
import numpy as np
import socket
import structdef send_image(socket, image_path):# 1. 读取图像并进行预处理img = cv2.imread(image_path)if img is None:print(f"错误: 无法读取图像 {image_path}")return# 调整图像大小(可选)img = cv2.resize(img, (640, 480))# 2. 对图像进行编码(压缩为JPEG格式)encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90] # 压缩质量为90%result, img_encoded = cv2.imencode('.jpg', img, encode_param)# 3. 将编码后的图像数据转换为字节流data = np.array(img_encoded)byte_data = data.tobytes()# 4. 发送图像数据的长度信息(使用struct确保跨平台兼容性)# 先发送4字节的整数,表示图像数据的长度socket.sendall(struct.pack(">L", len(byte_data)))# 5. 发送实际的图像数据socket.sendall(byte_data)print(f"已发送图像,大小: {len(byte_data)} 字节")if __name__ == "__main__":# 创建TCP套接字并连接到接收端client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = ('localhost', 8888) # 接收端IP和端口client_socket.connect(server_address)try:# 发送图像send_image(client_socket, "test.jpg") # 替换为实际图像路径finally:# 关闭连接client_socket.close()
接收端代码 (receiver.py
)
import cv2
import numpy as np
import socket
import structdef receive_image(socket):# 1. 接收图像数据的长度信息data_length = struct.unpack(">L", socket.recv(4))[0]# 2. 接收完整的图像数据buffer = b""while len(buffer) < data_length:remaining = data_length - len(buffer)buffer += socket.recv(min(4096, remaining)) # 每次最多接收4096字节# 3. 将字节流解码为图像img_data = np.frombuffer(buffer, dtype=np.uint8)img = cv2.imdecode(img_data, cv2.IMREAD_COLOR)return imgif __name__ == "__main__":# 创建TCP套接字并绑定到指定地址和端口server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = ('localhost', 8888)server_socket.bind(server_address)# 开始监听连接server_socket.listen(1)print(f"正在监听 {server_address}...")while True:# 接受客户端连接connection, client_address = server_socket.accept()print(f"连接来自: {client_address}")try:# 接收图像img = receive_image(connection)# 显示接收到的图像cv2.imshow('Received Image', img)cv2.waitKey(0)cv2.imwrite('received.jpg', img) # 保存图像print("图像已接收并保存")finally:# 关闭连接connection.close()
代码详细解释
发送端工作流程
-
图像预处理:
- 使用 OpenCV 读取图像并调整大小(可选),确保数据量适中。
-
图像编码:
- 将图像压缩为 JPEG 格式(通过
cv2.imencode
),减少数据量(相比原始像素数据可压缩 10-50 倍)。
- 将图像压缩为 JPEG 格式(通过
-
数据传输:
- 长度前缀协议:先发送 4 字节的整数(使用
struct.pack
)表示图像数据的长度,确保接收端知道要接收多少数据。 - 分块发送:将编码后的图像数据按块发送,避免大文件一次性传输导致的内存问题。
- 长度前缀协议:先发送 4 字节的整数(使用
接收端工作流程
-
接收数据长度:
- 先接收 4 字节的整数(使用
struct.unpack
),解析出图像数据的总长度。
- 先接收 4 字节的整数(使用
-
接收完整数据:
- 循环接收数据块,直到累计接收的数据长度等于预期长度。
-
图像解码与显示:
- 使用
np.frombuffer
将字节流转换为 NumPy 数组,再通过cv2.imdecode
解码为图像,最后显示或保存。
- 使用
网络传输关键点
- 协议选择:使用 TCP 协议(
SOCK_STREAM
)确保数据可靠传输,避免丢包。 - 字节序处理:使用
>
符号指定大端字节序(网络标准),确保跨平台兼容性。 - 缓冲区管理:通过循环接收数据块,处理可能的粘包问题,确保完整接收图像数据。
运行步骤
-
准备环境:
pip install opencv-python numpy
-
启动接收端:
python receiver.py
-
启动发送端:
python sender.py
-
注意事项:
- 确保两台设备在同一网络中,或修改代码中的 IP 地址为接收端的公网 IP。
- 防火墙可能需要开放指定端口(如 8888)。
扩展与优化建议
-
实时视频流传输:
- 在循环中连续读取摄像头帧并发送,可实现简易视频通话。
- 示例代码(发送端关键部分):
cap = cv2.VideoCapture(0) while True:ret, frame = cap.read()send_image(socket, frame) # 需修改send_image函数支持直接处理帧
-
错误处理:
- 添加超时设置(
socket.settimeout()
)避免长时间等待。 - 增加重传机制(如发送失败时重试)。
- 添加超时设置(
-
安全性:
- 使用 SSL/TLS 加密传输(如通过
ssl.wrap_socket
)。 - 添加身份验证机制(如用户名 / 密码)。
- 使用 SSL/TLS 加密传输(如通过
-
性能优化:
- 使用多线程或异步 I/O 提高并发处理能力。
- 动态调整 JPEG 压缩质量以平衡带宽和图像质量。
通过以上代码和解释,你可以实现基本的图像网络传输功能,并根据需求进行扩展。