将ros机器人摄像头捕捉的画面在上位机实时显示,需要用到socket网络编程,提供了TCP和UDP两种方式
s = socket(AF_INET, SOCK_STREAM)
创建了一个TCP套接字。SOCK_STREAM
表示这是一个TCP套接字,而不是UDP的 SOCK_DGRAM
。s.bind(addr)
将套接字绑定到一个特定的地址和端口上。s.listen(1)
使套接字开始监听连接请求。参数 1
表示最多可以有一个待处理的连接。conn, addr = s.accept()
阻塞,直到客户端连接。一旦客户端连接,它将返回一个新的套接字对象和客户端的地址。data = conn.recv(921600)
从新的套接字对象接收数据。cv2.imdecode
和 cv2.imshow
处理和显示接收到的图像数据。conn.close()
关闭客户端连接。s.close()
关闭监听套接字。cv2.destroyAllWindows()
关闭所有OpenCV窗口。import numpy as np
import cv2
from socket import *
# 创建TCP套接字
s = socket(AF_INET, SOCK_STREAM)
addr = ('127.0.0.1', 8080)
s.bind(addr)
s.listen(1) # 监听连接,参数1表示最大连接数
print("Waiting for a connection...")
conn, addr = s.accept() # 接受连接
print(f"Connection from {addr}")
try:
while True:
data = conn.recv(921600) # 接收数据
if not data:
break # 如果没有数据,退出循环
receive_data = np.frombuffer(data, dtype='uint8')
r_img = cv2.imdecode(receive_data, 1)
r_img = r_img.reshape(480, 640, 3)
cv2.putText(r_img, "server", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('server_frame', r_img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
conn.close() # 关闭连接
s.close() # 关闭套接字
cv2.destroyAllWindows()
s = socket(AF_INET, SOCK_STREAM)
创建一个TCP套接字。s.connect(addr)
尝试连接到服务器的地址和端口。cv2.VideoCapture
捕获图像,并通过 cv2.flip
对图像进行处理。th
来调用 send_img
函数,并使用 th.start()
启动线程。send_img
函数中,使用 cv2.imencode
将图像编码为JPEG格式,然后使用 s.sendall(send_data)
将图像数据发送到服务器。s.close()
关闭TCP套接字。cv2.destroyAllWindows()
关闭所有OpenCV窗口。import cv2
import threading
from socket import *
def send_img():
_, send_data = cv2.imencode('.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 50])
s.sendall(send_data) # 发送所有数据
print(f'已发送{len(send_data)}Bytes的数据')
addr = ('127.0.0.1', 8080)
cap = cv2.VideoCapture(0)
s = socket(AF_INET, SOCK_STREAM)
s.connect(addr) # 连接到服务器
try:
while True:
_, img = cap.read()
img = cv2.flip(img, 1)
th = threading.Thread(target=send_img)
th.setDaemon(True)
th.start()
cv2.putText(img, "client", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('client_frame', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
s.close() # 关闭套接字
cv2.destroyAllWindows()
sys
和 os
是Python的标准库,用于访问与Python解释器和操作系统交互的一些功能。numpy
是一个用于数值计算的库。cv2
是OpenCV库的Python接口,用于图像处理和计算机视觉任务。threading
和 time
是Python的标准库,分别用于多线程编程和时间相关的功能。socket
是Python的标准库,用于网络通信。s = socket(AF_INET, SOCK_DGRAM)
这行代码创建了一个新的UDP套接字。addr = ('127.0.0.1', 8080)
这行代码定义了一个地址,其中 127.0.0.1
是本机的IP地址,8080
是端口号。s.bind(addr)
这行代码将套接字绑定到指定的地址。data, _ = s.recvfrom(921600)
这行代码从套接字接收数据,最多接收921600字节的数据。receive_data = np.frombuffer(data, dtype='uint8')
这行代码将接收到的数据转换为一个numpy数组。r_img = cv2.imdecode(receive_data, 1)
这行代码解码接收到的数据,将其转换为一个OpenCV图像对象。r_img = r_img.reshape(480, 640, 3)
这行代码将图像重塑为480x640的大小,并指定该图像有3个颜色通道。cv2.putText(...)
这行代码将文本 “server” 画到图像上。cv2.imshow('server_frame', r_img)
这行代码显示处理后的图像。if cv2.waitKey(1) & 0xFF == ord('q'):
这行代码检查是否按下了键 ‘q’,如果是,则退出循环。cv2.destroyAllWindows()
这行代码关闭所有OpenCV窗口。import sys, os
import numpy as np
import cv2, threading, time
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
# addr = ('192.168.64.1', 8080)
addr = ('127.0.0.1', 8080) # 127.0.0.1表示本机的IP,相当于我和“自己”的关系
s.bind(addr)
while True:
data, _ = s.recvfrom(921600)
receive_data = np.frombuffer(data, dtype='uint8')
r_img = cv2.imdecode(receive_data, 1)
r_img = r_img.reshape(480, 640, 3)
cv2.putText(r_img, "server", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('server_frame', r_img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
numpy
, cv2
, threading
, time
和socket
库。send_img
函数:
send_img
函数中,通过 s.sendto(send_data, addr)
语句将图像数据发送到指定的地址。s.close()
关闭套接字。addr = ('127.0.0.1', 8080)
设置了目标地址和端口。cv2.VideoCapture(0)
初始化摄像头,并进入一个无限循环。_, img = cap.read()
语句捕获图像。cv2.flip(img, 1)
语句将图像进行水平翻转。th
,并将 send_img
函数设置为该线程的目标。th.setDaemon(True)
将线程设置为守护线程,这意味着主程序退出时,该线程也会退出。cv2.imencode('.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 50])
语句将图像编码为JPEG格式,质量设置为50。th.start()
语句启动线程。cv2.putText(...)
和 cv2.imshow('client_frame', img)
语句在本地显示图像,并在图像上添加了文本 “client”。cv2.waitKey(1) & 0xFF == ord('q')
语句检测到这一条件,并退出循环。cv2.destroyAllWindows()
语句关闭所有OpenCV窗口。该脚本应该与你之前提供的服务器脚本配合使用,服务器脚本用于接收图像数据,而这个客户端脚本用于发送图像数据。
import numpy as np
import cv2, threading, time
from socket import *
def send_img():
s.sendto(send_data, addr)
print(f'已发送{img.size}Bytes的数据')
s.close()
# input('>>')
# addr = ('192.168.43.106', 8080)
addr = ('127.0.0.1', 8080) # 127.0.0.1表示本机的IP,相当于我和“自己”的关系
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
img = cv2.flip(img, 1)
s = socket(AF_INET, SOCK_DGRAM)
th = threading.Thread(target=send_img)
th.setDaemon(True)
_, send_data = cv2.imencode('.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 50])
th.start()
cv2.putText(img, "client", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('client_frame', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()