图像传输项目中的Python Opencv深度错误

2024-09-27 19:25:01 发布

您现在位置:Python中文网/ 问答频道 /正文

首先,我试图做一些类似屏幕共享的事情,我遇到了一个错误。我试图一行一行地发送图像,但我发现它只能在局域网中工作,因为连接速度要快得多。然后我只传输每个像素,然后自己构建阵列,这会非常慢。代码如下: 服务器端:

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,但我确定图像的尺寸是10801920,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)

Tags: inimageimportfor错误nprangeerror
1条回答
网友
1楼 · 发布于 2024-09-27 19:25:01

您需要将新形状作为tuple传递给reshape,例如arr.reshape((y,x,3))。如果OpenCV期望的数据类型(每个通道8位,无符号)与它从程序中获得的数据类型(32位有符号整数)不同,则还可能会出现另一个错误,请参见documentation了解cvtColor()。您可以在创建数组np.array(..., dtype=np.uint8)时指定数据类型

关于性能,在Python for中,对大量数据的循环可能会很慢,如果可以避免循环而改用库例程,通常可以使代码大大加快。此外,您应该使用send()recv()读取和写入较大的块。如果您不熟悉socket编程,至少应该查看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)

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

相关问题 更多 >

    热门问题