我正在做一个项目,需要在服务器端使用 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
更新的问题:
- 在服务器端 - 我遇到类似的问题(需要按两次 ctrl+c 才能停止服务器 - 为什么会这样) - new
- 服务器或者成功运行(即,第一次未连接,并且第二次 connecting ,第三次 停止,第四次 运行好 - 为什么会这样? - 新
- 如何减少延迟? - 新
让我们看看谁会回答所有这些问题!!!
服务器:
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()
最佳答案
- 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
- why dtype uint8 is used?
这来自 OpenCV (BGR) 默认使用的图像表示,这意味着每个像素颜色由 3 个 channel 表示,蓝绿色和红色。每个 channel 的值都在 0-255 之间,这意味着它可以用 8 位表示,这就是 dtype uint8 的原因。稍后函数 reshape 将从 3 个连续值(COLOR_PIXEL 值)创建像素。
在这部分中,代码读取一行文本,这是图像数据并将其放入一维数组中。这将表明该行的每个 8 位都是一个值,应该被视为一个整数。
- 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/