python - 使用 python 3.4 opencv 3.2 使用 usbcam 进行套接字编程

标签 python opencv image-processing webcam raspbian

我正在做一个项目,需要在服务器端使用 USB 网络摄像头在客户端实时流式传输视频。

我正在使用(Opencv 3.2.0 + python 3.4.3)。

下面给出的代码工作正常,我想知道这段代码实际如何工作以及它如何将帧传输到客户端。

此代码中存在延迟,以及如何克服该延迟。我尝试设置分辨率,但在客户端出现错误,例如([错误]:新数组的总大小必须保持不变)。当我将其设置为默认分辨率时(即 640*480)它工作正常。

Help me 
    1. to set the resolution. -answered
    2. why dtype uint8 is used? -answered
    3. what is role fileDescriptor? -answered

更新的问题:

  1. 在服务器端 - 我遇到类似的问题(需要按两次 ctrl+c 才能停止服务器 - 为什么会这样) - new
  2. 服务器或者成功运行(即,第一次未连接,并且第二次 connecting第三次 停止第四次 运行 - 为什么会这样? -
  3. 如何减少延迟? -

让我们看看谁会回答所有这些问题!!!

服务器:

import cv2
import time
import json
import socket
import base64
import numpy as np
from threading import Thread

SERVER_IP = "x.x.x.x"
SERVER_PORT = xxxx
MAX_NUM_CONNECTIONS = 20
DEVICE_NUMBER = 0

class ConnectionPool(Thread):

    def __init__(self, ip_, port_, conn_, device_):
        Thread.__init__(self)
        self.ip = ip_
        self.port = port_
        self.conn = conn_
        self.device = device_
        print("[+] New server socket thread started for " + self.ip + ":" +str(self.port))

    def run(self):
        try:
            while True:
                ret, frame = self.device.read()
                a = b'\r\n'
                data = frame.tostring()
                da = base64.b64encode(data)
                self.conn.sendall(da + a)

        except Exception as e:
            print("Connection lost with " + self.ip + ":" + str(self.port) +"\r\n[Error] " + str(e.message))
        self.conn.close()

if __name__ == '__main__':
    cap = cv2.VideoCapture(DEVICE_NUMBER)
    print("Waiting connections...")
    connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    connection.bind((SERVER_IP, SERVER_PORT))
    connection.listen(MAX_NUM_CONNECTIONS)
    while True:
        (conn, (ip, port)) = connection.accept()
        thread = ConnectionPool(ip, port, conn, cap)
        thread.start()
    connection.close()
    cap.release()

客户:

import cv2
import socket
import base64
import numpy as np

IP_SERVER = "x.x.x.x"
PORT_SERVER = xxxx
TIMEOUT_SOCKET = 10
SIZE_PACKAGE = 4096


IMAGE_HEIGHT = 480
IMAGE_WIDTH = 640
COLOR_PIXEL = 3  # RGB


if __name__ == '__main__':
    connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    connection.settimeout(TIMEOUT_SOCKET)
    connection.connect((IP_SERVER, PORT_SERVER))

    while True:
        try:
            fileDescriptor = connection.makefile(mode='rb')
            result = fileDescriptor.readline()
            fileDescriptor.close()
            result = base64.b64decode(result)
            frame = np.fromstring(result, dtype=np.uint8)
            frame_matrix = np.array(frame)
            frame_matrix = np.reshape(frame_matrix, (IMAGE_HEIGHT, IMAGE_WIDTH,COLOR_PIXEL))
            cv2.imshow('Window title', frame_matrix)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        except Exception as e:
            print("[Error] " + str(e))

    connection.close()

最佳答案

  1. to set the resolution.

您必须在服务器端和客户端这两个地方进行更改。您遇到的错误很可能来自 reshape 函数。此函数将从图像中获取数据并对其进行整形,这意味着数据将保持不变,只有大小会发生变化......在这种情况下,它用于将一维数据数组更改为二维矩阵 3 channel 矩阵(但是数据顺序不变)。怎么改,得先在server部分改。

它说的地方

ret, frame = self.device.read()

之后可以添加OpenCV的resize功能:

frame = cv2.resize(frame ,(width/2, height/2), interpolation = cv2.INTER_LINEAR )

这将是大小的一半。现在在客户端你可以减少到:

IMAGE_HEIGHT = 480 / 2
IMAGE_WIDTH = 640 / 2
  1. why dtype uint8 is used?

这来自 OpenCV (BGR) 默认使用的图像表示,这意味着每个像素颜色由 3 个 channel 表示,蓝绿色和红色。每个 channel 的值都在 0-255 之间,这意味着它可以用 8 位表示,这就是 dtype uint8 的原因。稍后函数 reshape 将从 3 个连续值(COLOR_PIXEL 值)创建像素。

在这部分中,代码读取一行文本,这是图像数据并将其放入一维数组中。这将表明该行的每个 8 位都是一个值,应该被视为一个整数。

  1. what is role fileDescriptor?

这是一种从套接字读取数据的方法。查看documentation .这样你就可以使用 readline,并获得由换行符限制的数据 block 。在你的情况下 '\r\n'。查看行:

a = b'\r\n'
data = frame.tostring()
da = base64.b64encode(data)
self.conn.sendall(da + a)

a为回车符,在整张图片数据以字符串表示,base 64编码后发送。

关于python - 使用 python 3.4 opencv 3.2 使用 usbcam 进行套接字编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46092658/

相关文章:

python - 如何使用 PyAIML 设置聊天机器人的主人名称?

python - 对于较大的交叉或外积,NumPy 比 PyTorch 更快

python - Anaconda: cannot import cv2 even though opencv is installed (how to install opencv3 for python3)

opencv - 如何在 opencv 中将图像从 CV_8UC1 类型转换为 CV_32FC1 类型?

matlab - 扩展matlab中的subplot函数

python - 使用多个 AND 语句的 Pandas read_sql_query

python - Django:按基于类的 View 重定向已经登录的用户

c++ - findHomography with RANSAC 错误异常值

c++ - opencv库加载(C++)

python - 检查像素(RGB 或 HSV)是否包含在色标范围内,如何