【问题标题】:Python Opencv depth error in Image transimission project图像传输项目中的Python Opencv深度错误
【发布时间】:2021-08-12 19:49:22
【问题描述】:

首先,我正在尝试执行屏幕共享之类的操作,但遇到了一个错误。我试图逐行发送图像,但我发现它只能在 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)

【问题讨论】:

标签: python opencv sockets image-processing


【解决方案1】:

您需要将新形状作为元组传递给reshape,例如。 arr.reshape((y,x,3))。如果 OpenCV 期望的数据类型(每通道 8 位,无符号)与从程序中获得的数据类型(32 位有符号整数)不同,您可能还会收到另一个错误,请参阅 documentation 以获取 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)

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

【讨论】:

    猜你喜欢
    • 2013-10-06
    • 2019-08-06
    • 2021-07-28
    • 2019-08-03
    • 2015-02-27
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多