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)

一般来说,您应该始终使用序列化库而不是直接通过网络发送原始字节,因为这些库通常会处理各种重要的细节,例如字节顺序、消息大小、数据类型、转换等。