Python Opencv depth error in Image transmission 项目
Python Opencv depth error in Image transimission project
首先,我正在尝试执行屏幕共享之类的操作,但遇到错误。我试图逐行发送图像,但我发现它只能在 LAN 中工作,因为连接速度要快得多。然后我专门传输每个像素并自行构建阵列,这会非常慢。这是代码:
服务器端:
def getImg(socket,y,x):
pixels = []
print(x*y*3)
for a in range(x*y*3):
pixels.append(struct.unpack('i', socket.recv(4))[0])
if a%(x*y)==0:
pass
return np.array(pixels).reshape(y,x,3)
客户端:
def sendSS(img):
y, x, color = img.shape
print(y*x*3)
for a in range(y):
for b in range(x):
for m in img[a][b]:
socket.send(struct.pack('i', m))
错误是这样的:
(<class 'cv2.error'>, error("OpenCV(4.5.1) c:\users\appveyor\appdata\local\temp\1\pip-req-build-wvn_it83\opencv\modules\imgproc\src\color.simd_helpers.hpp:94: error: (-2:Unspecified error) in function '__cdecl cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0xeee51b91::Set<3,4,-1>,struct cv::impl::A0xeee51b91::Set<0,2,5>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'\n> Unsupported depth of input image:\n> 'VDepth::contains(depth)'\n> where\n> 'depth' is 4 (CV_32S)\n"), <traceback object at 0x0000023221307740>)
我构建 numpy 数组的方式工作正常:
import pyautogui
import cv2
import numpy as np
import pickle
import struct
from pprint import pprint as pp
ss = np.array(pyautogui.screenshot())
y,x,color = ss.shape
pixels = []
for a in range(y):
for b in range(x):
for m in ss[a][b]:
pixels.append(struct.pack('i',m))
pixels2 = []
for val in pixels:
pixels2.append(struct.unpack('i',val)[0])
pixels2 = np.array(pixels2).reshape((1080,1920,3))
cv2.imwrite('name.png',pixels2)
如何传输更快并解决这个问题?
编辑:
这是发生错误的代码部分,它说深度是 4,但我确定图像的尺寸是 1080,1920,3,因为我可以打印它。
image = getImg(aSocket,y,x)
SS = cv2.cvtColor(image,cv2.COLOR_RGB2BGR) # error occurs in this line
aSocket.send('image is gotten'.encode('utf-8'))
print('image is gotten')
cv2.imwrite(f'{ip[0]}\{count}.png',SS)
您需要将新形状作为元组而不是 reshape
传递,例如。 arr.reshape((y,x,3))
。如果 OpenCV 期望的数据类型(每通道 8 位,无符号)与它从程序中获得的数据类型(32 位有符号整数)不同,您可能还会遇到另一个错误,请参见 documentation for cvtColor()
。创建数组时可以指定数据类型np.array(..., dtype=np.uint8)
.
关于性能,在 Python for
中,大量数据的循环可能很慢,如果您可以避免循环并改用库例程,通常可以使您的代码显着加快。此外,您应该使用 send()
和 recv()
读写更大的块。如果您不熟悉套接字编程,您至少应该查看 python 文档 Socket Programming HOWTO。您可以通过直接将数据解释为字节来消除图像数据的循环。套接字代码遵循链接文档页面中的示例。
def send_im(sock, im):
totalsent = 0
im_bytes = im.tobytes()
while totalsent < len(im_bytes):
sent = sock.send(im_bytes[totalsent:])
if sent == 0:
raise RuntimeError("socket error")
totalsent += sent
接收方需要知道预期输入的大小。
def recv_im(sock, dtype, shape):
# expected number of bytes
size = np.dtype(float).itemsize * np.prod(shape)
im_bytes = bytearray(size) # received bytes
bytes_recvd = 0
chunk_size = 2048
while bytes_recvd < size:
chunk = sock.recv(min(size-bytes_recvd, chunk_size))
if chunk == b'':
raise RuntimeError("socket connection broken")
im_bytes[bytes_recvd:(bytes_recvd+chunk_size)] = memoryview(chunk)
bytes_recvd += len(chunk)
# intrepret bytes in correct data type and shape and return image
return np.frombuffer(im_bytes, dtype=dtype).reshape(shape)
一般来说,您应该始终使用序列化库而不是直接通过网络发送原始字节,因为这些库通常会处理各种重要的细节,例如字节顺序、消息大小、数据类型、转换等。
首先,我正在尝试执行屏幕共享之类的操作,但遇到错误。我试图逐行发送图像,但我发现它只能在 LAN 中工作,因为连接速度要快得多。然后我专门传输每个像素并自行构建阵列,这会非常慢。这是代码: 服务器端:
def getImg(socket,y,x):
pixels = []
print(x*y*3)
for a in range(x*y*3):
pixels.append(struct.unpack('i', socket.recv(4))[0])
if a%(x*y)==0:
pass
return np.array(pixels).reshape(y,x,3)
客户端:
def sendSS(img):
y, x, color = img.shape
print(y*x*3)
for a in range(y):
for b in range(x):
for m in img[a][b]:
socket.send(struct.pack('i', m))
错误是这样的:
(<class 'cv2.error'>, error("OpenCV(4.5.1) c:\users\appveyor\appdata\local\temp\1\pip-req-build-wvn_it83\opencv\modules\imgproc\src\color.simd_helpers.hpp:94: error: (-2:Unspecified error) in function '__cdecl cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0xeee51b91::Set<3,4,-1>,struct cv::impl::A0xeee51b91::Set<0,2,5>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'\n> Unsupported depth of input image:\n> 'VDepth::contains(depth)'\n> where\n> 'depth' is 4 (CV_32S)\n"), <traceback object at 0x0000023221307740>)
我构建 numpy 数组的方式工作正常:
import pyautogui
import cv2
import numpy as np
import pickle
import struct
from pprint import pprint as pp
ss = np.array(pyautogui.screenshot())
y,x,color = ss.shape
pixels = []
for a in range(y):
for b in range(x):
for m in ss[a][b]:
pixels.append(struct.pack('i',m))
pixels2 = []
for val in pixels:
pixels2.append(struct.unpack('i',val)[0])
pixels2 = np.array(pixels2).reshape((1080,1920,3))
cv2.imwrite('name.png',pixels2)
如何传输更快并解决这个问题?
编辑: 这是发生错误的代码部分,它说深度是 4,但我确定图像的尺寸是 1080,1920,3,因为我可以打印它。
image = getImg(aSocket,y,x)
SS = cv2.cvtColor(image,cv2.COLOR_RGB2BGR) # error occurs in this line
aSocket.send('image is gotten'.encode('utf-8'))
print('image is gotten')
cv2.imwrite(f'{ip[0]}\{count}.png',SS)
您需要将新形状作为元组而不是 reshape
传递,例如。 arr.reshape((y,x,3))
。如果 OpenCV 期望的数据类型(每通道 8 位,无符号)与它从程序中获得的数据类型(32 位有符号整数)不同,您可能还会遇到另一个错误,请参见 documentation for cvtColor()
。创建数组时可以指定数据类型np.array(..., dtype=np.uint8)
.
关于性能,在 Python for
中,大量数据的循环可能很慢,如果您可以避免循环并改用库例程,通常可以使您的代码显着加快。此外,您应该使用 send()
和 recv()
读写更大的块。如果您不熟悉套接字编程,您至少应该查看 python 文档 Socket Programming HOWTO。您可以通过直接将数据解释为字节来消除图像数据的循环。套接字代码遵循链接文档页面中的示例。
def send_im(sock, im):
totalsent = 0
im_bytes = im.tobytes()
while totalsent < len(im_bytes):
sent = sock.send(im_bytes[totalsent:])
if sent == 0:
raise RuntimeError("socket error")
totalsent += sent
接收方需要知道预期输入的大小。
def recv_im(sock, dtype, shape):
# expected number of bytes
size = np.dtype(float).itemsize * np.prod(shape)
im_bytes = bytearray(size) # received bytes
bytes_recvd = 0
chunk_size = 2048
while bytes_recvd < size:
chunk = sock.recv(min(size-bytes_recvd, chunk_size))
if chunk == b'':
raise RuntimeError("socket connection broken")
im_bytes[bytes_recvd:(bytes_recvd+chunk_size)] = memoryview(chunk)
bytes_recvd += len(chunk)
# intrepret bytes in correct data type and shape and return image
return np.frombuffer(im_bytes, dtype=dtype).reshape(shape)
一般来说,您应该始终使用序列化库而不是直接通过网络发送原始字节,因为这些库通常会处理各种重要的细节,例如字节顺序、消息大小、数据类型、转换等。