• python socket 传输opencv读取的图像


    python socket网络编程

    将ros机器人摄像头捕捉的画面在上位机实时显示,需要用到socket网络编程,提供了TCP和UDP两种方式

    TCP服务器端代码:

    1. 创建TCP套接字:
      • s = socket(AF_INET, SOCK_STREAM) 创建了一个TCP套接字。SOCK_STREAM 表示这是一个TCP套接字,而不是UDP的 SOCK_DGRAM
    2. 绑定地址:
      • s.bind(addr) 将套接字绑定到一个特定的地址和端口上。
    3. 监听连接:
      • s.listen(1) 使套接字开始监听连接请求。参数 1 表示最多可以有一个待处理的连接。
    4. 接受连接:
      • conn, addr = s.accept() 阻塞,直到客户端连接。一旦客户端连接,它将返回一个新的套接字对象和客户端的地址。
    5. 接收和处理数据:
      • 在一个循环中,data = conn.recv(921600) 从新的套接字对象接收数据。
      • 使用 cv2.imdecodecv2.imshow 处理和显示接收到的图像数据。
      • 如果按下 ‘q’ 键,循环将终止。
    6. 清理:
      • 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()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    TCP客户端:

    1. 创建TCP套接字:
      • 同样使用 s = socket(AF_INET, SOCK_STREAM) 创建一个TCP套接字。
    2. 连接到服务器:
      • s.connect(addr) 尝试连接到服务器的地址和端口。
    3. 捕获和处理图像:
      • 在一个循环中,使用 cv2.VideoCapture 捕获图像,并通过 cv2.flip 对图像进行处理。
    4. 发送图像数据:
      • 创建一个新线程 th 来调用 send_img 函数,并使用 th.start() 启动线程。
      • send_img 函数中,使用 cv2.imencode 将图像编码为JPEG格式,然后使用 s.sendall(send_data) 将图像数据发送到服务器。
    5. 显示图像:
      • 在本地显示处理过的图像,并检查是否按下了 ‘q’ 键来决定是否退出循环。
    6. 清理:
      • 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()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    1. 导入必需的库:
      • sysos 是Python的标准库,用于访问与Python解释器和操作系统交互的一些功能。
      • numpy 是一个用于数值计算的库。
      • cv2 是OpenCV库的Python接口,用于图像处理和计算机视觉任务。
      • threadingtime 是Python的标准库,分别用于多线程编程和时间相关的功能。
      • socket 是Python的标准库,用于网络通信。
    2. 创建一个UDP套接字:
      • s = socket(AF_INET, SOCK_DGRAM) 这行代码创建了一个新的UDP套接字。
    3. 绑定套接字到地址:
      • addr = ('127.0.0.1', 8080) 这行代码定义了一个地址,其中 127.0.0.1 是本机的IP地址,8080 是端口号。
      • s.bind(addr) 这行代码将套接字绑定到指定的地址。
    4. 接收和处理数据:
      • 这个脚本进入一个无限循环,等待接收数据。
      • 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’,如果是,则退出循环。
    5. 清理:
      • cv2.destroyAllWindows() 这行代码关闭所有OpenCV窗口。

    UDP服务器端:

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    1. 导入必需的库:
      • 同样导入了numpy, cv2, threading, timesocket库。
    2. 定义 send_img 函数:
      • send_img 函数中,通过 s.sendto(send_data, addr) 语句将图像数据发送到指定的地址。
      • 输出已发送的数据大小,并通过 s.close() 关闭套接字。
    3. 设置地址:
      • addr = ('127.0.0.1', 8080) 设置了目标地址和端口。
    4. 初始化摄像头:
      • 通过 cv2.VideoCapture(0) 初始化摄像头,并进入一个无限循环。
    5. 捕获和处理图像:
      • 在循环中,通过 _, img = cap.read() 语句捕获图像。
      • 通过 cv2.flip(img, 1) 语句将图像进行水平翻转。
    6. 创建并启动发送图像数据的线程:
      • 创建一个新的UDP套接字。
      • 创建一个新线程 th,并将 send_img 函数设置为该线程的目标。
      • 通过 th.setDaemon(True) 将线程设置为守护线程,这意味着主程序退出时,该线程也会退出。
      • 通过 cv2.imencode('.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 50]) 语句将图像编码为JPEG格式,质量设置为50。
      • 通过 th.start() 语句启动线程。
    7. 显示图像:
      • 通过 cv2.putText(...)cv2.imshow('client_frame', img) 语句在本地显示图像,并在图像上添加了文本 “client”。
    8. 退出条件:
      • 如果按下’q’键,通过 cv2.waitKey(1) & 0xFF == ord('q') 语句检测到这一条件,并退出循环。
    9. 清理:
      • 通过 cv2.destroyAllWindows() 语句关闭所有OpenCV窗口。

    该脚本应该与你之前提供的服务器脚本配合使用,服务器脚本用于接收图像数据,而这个客户端脚本用于发送图像数据。

    UDP客户端:

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    MySQL 基础学习总结(一)
    Python的configparser读写配置文件
    mysql总结
    解决Redis启动:未找到命令的问题
    简单的权限验证
    基于ssm的宠物商城网站设计与实现
    用 Java 实现阻塞队列
    Pytest框架实战二
    java面试题(一年工作经验)的心得
    微软Edge浏览器的辅助功能设置:提升用户体验的指南
  • 原文地址:https://blog.csdn.net/Johnor/article/details/133499641