ValueError:序列太大;不能大于32 [英] ValueError: sequence too large; cannot be greater than 32
问题描述
我写了这段代码:
from Crypto.Cipher import AES
import numpy as np
import cv2, base64
BLOCK_SIZE = 16
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
secret = "youwanttoknowmysecretdontyouhaha"
cipher = AES.new(secret)
video = cv2.VideoCapture(0)
a = 0
while True:
a = a + 1
check, frame = video.read()
encrypted = EncodeAES(cipher, str(frame))
img = DecodeAES(cipher, encrypted)
cv2.imshow("Capturing", np.ndarray(img))
key = cv2.waitKey(1)
if key == ord('q'):
break
但是它不能像预期的那样工作.
But it doesnt work like it supposed to.
我希望它播放我的实时摄像机,但它给我以下错误:
I want it to play my live camera, but it gives me the following error:
回溯(最近一次通话最后一次):文件"tester.py",第28行,在 cv2.imshow("Captureing",np.ndarray(img))ValueError:序列太大;不能大于32
Traceback (most recent call last): File "tester.py", line 28, in cv2.imshow("Capturing", np.ndarray(img)) ValueError: sequence too large; cannot be greater than 32
我真的很想知道我做错了什么,不只给我解决方案,而是请我解释一下,我仍然在学习
I really would like to know what Im doing wrong and dont give me only the solution but explain to please, im still learning
编辑
我使用python 2.7
I use python 2.7
编辑
以下代码有效,但是我在主机将加密后的密码发送到另一台计算机的程序中使用了它.在这种情况下,您不能使用frame.dtype
.
The following code works, but I use it in a program where the host sends the encrypted to an other computer. In this case you cant use frame.dtype
.
from Crypto.Cipher import AES
import numpy as np
import cv2, base64
BLOCK_SIZE = 16
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
secret = "youwanttoknowmysecretdontyouhaha"
cipher = AES.new(secret)
video = cv2.VideoCapture(0)
a = 0
while True:
a = a + 1
check, frame = video.read()
encrypted = EncodeAES(cipher, frame.tobytes())
decrypted = DecodeAES(cipher, encrypted)
img = np.frombuffer(decrypted, dtype=frame.dtype).reshape(frame.shape)
cv2.imshow("Capturing", img)
key = cv2.waitKey(1)
if key == ord("q"):
break
video.release()
但是我可以将frame.dtype发送到另一台计算机.
However I can send frame.dtype to the other computer.
当我将frame.dtype
和frame_shape
的加密形式发送到计算机并对其进行解密并在其中使用时,出现以下错误
When I send the the encrypted form of frame.dtype
and frame_shape
to the computer and decrypt it and use it there, I get the following error
img = np.frombuffer(decod_ed, dtype=img_dtype).reshape(img_shape)
TypeError: data type "ûÿùùÖÿùÖÿùÖÿÖÖÿÖÖÿÜÜÖøøÜ£ÜÖ£ÜÖÜÜÖÜÜÖÿÜÜÿÜÜÿÜøÖø£øøøøøøØ£ÿØ£ÿØ£ÿƒ×ÜØ×Ü׃ø؃ÖøØùØØùØØùƒ£ÿ×øùƒ£ÿƒ£ÿƒø܃øÜíØ£íØ£íØ£ó×Øó×Øó×Øóƒøóƒøúá£óƒøáƒøáƒø׃ø׃ø£ƒø£ƒø£ƒø£ƒøƒ×ÜáƒøúíøúíøÑáøÑáøñ×øу£ñØ×Ñ׃ñáƒñáƒóíØíá£áó£ƒíø×áÜ×áÜøƒÖ£áÜ£ƒø£ƒøƒØ£ƒØ£á×Øá×ØØØ£ØØ£××؃ƒ×ƒƒ×××Ø׃ø׃ø£ƒø£ƒø£×Ø£×Ø£×Ø£×ØØá£Øá£ØíøØíøáó£áó£×ó£Øíø܃øù£ÿôÜÿôÜÿÿÜÜÿÜÜøøøØØØíƒ×óáƒíƒ×íƒ×óáƒóáƒñúƒñúƒªÑíñúƒñúƒñúƒúó×úó×úó×úó×óó£óó£úñøúñøúúØññ×óñ×óñ×óúƒóúƒóóíóóíóúƒñÑíóªááñ××ñ××ñ××úƒáÑí׺á׺á£ñƒ£ñƒáúƒáúƒññúóóíúíáúíáííáññúññúññúñÑíñÑíóúƒñÑíñÑíñÑíóÑíóÑíóúƒóúƒñÑíñÑíñÑíóúƒáúƒóÑíóÑíáúƒƒó×áúƒóÑíóÑíóÑíáúƒáúƒƒó׃ó××íØØíøØíøØóÖØóÖØíø£áÜáá܃ƒÖíƒÖƒØùØ×òƒáùØáùÜØöÜØöÜØöÖ×òÿØöù£ôù£ôûÜöûÜööÜööÜöÆøöÆøööÜööÜöûÜööÿÆûùôûùôÿûòûöôÆöôöûòöûòöûòöûòÆöôÉòæÉòæÉûÉÉûÉÅòÅÅòÅæòÅÉöÄÉöÄÉöÄÉöÄÅôìÉÆîÅæïææïÉÉèÉÅåÉÅåîÅåèìäçîâåïéêîüêîüçï~çï~àïÇàïÇë|å|" not understood
推荐答案
I'm assuming that frame is a [SciPy.Docs]: numpy.ndarray. There are 2 problems. Below is an example:
code00.py :
#!/usr/bin/env python3
import sys
from Crypto.Cipher import AES
import numpy as np
import cv2
import base64
BLOCK_SIZE = 16
PADDING = b"{"
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
CIPHER_MODE = AES.MODE_CBC
SECRET = b"youwanttoknowmysecretdontyouhaha"
def main():
img0 = cv2.imread("c:/valmand.png")
encrypt_cipher = AES.new(SECRET, CIPHER_MODE) # Python 2: AES.new(SECRET)
print("Original image data - Type: {:}, Size: {:d}, Attrs: {:}".format(type(img0), img0.size, img0.shape))
img_stream_wrong = str(img0).encode()
print("\nWrong img0 stream length: {:}".format(len(img_stream_wrong)))
print("\nWrong img0 stream: {:}".format(img_stream_wrong))
img_stream = img0.tobytes()
print("\nCorrect img0 stream length: {:}".format(len(img_stream)))
encrypted = EncodeAES(encrypt_cipher, img_stream)
print("\nEncrypted length: {:d}".format(len(encrypted)))
decrypt_cipher = AES.new(SECRET, CIPHER_MODE) # Python 2: AES.new(SECRET)
decrypted = DecodeAES(decrypt_cipher, encrypted)
print("\nDecrypted length: {:d}".format(len(decrypted)))
img1 = np.frombuffer(decrypted, dtype=img0.dtype).reshape(img0.shape)
print("\nFinal image data - Type: {:}, Size: {:d}, Attrs: {:}".format(type(img1), img1.size, img1.shape))
#cv2.imshow("Capturing", img1)
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
注释:
- 我简化了示例,仅加载图像
- 由于我没有在 Python 2 上安装所有必需的软件包,因此我使用了 Python 3 .这就是为什么需要进行一些与问题无关的更改的原因:
- 从 string 切换为 bytes
- AES 更改:
-
AES.new
签名已更改( [ReadTheDocs.PyCryptodome]:AES ) - 相同的密码在用于加密后不能再用于解密,因此请创建具有相同属性的另一个密码(也许有一些更简洁的方法,但是我没有花太多时间在上面) li>
- I simplified the example to only load an image
- Since I don't have all the required packages installed on Python 2, I used Python 3. That's why some changes unrelated to the question were required:
- Switch from string to bytes
- AES changes:
AES.new
signature changed ([ReadTheDocs.PyCryptodome]: AES)- Same cipher can't be used for decryption after it was used for encryption, so create another with the same properties (maybe there's some cleaner way of doing this, but I didn't spend too much time on it)
错误:
- 如所见,在 ndarray 上应用 str ,可以方便地表示该 ndarray ,而不是其内容,因此它将 语法上正确,但语义上错误
- 要解决此问题,应使用其 tobytes 方法 对阵列进行正确的序列化
- As seen, applying str on an ndarray, gives a user friendly representation of that ndarray, rather than its contents, so it will be syntactically correct, but semantically wrong
- To fix that, the array should be properly serialized using its tobytes method
相反,在尝试反序列化时,在字节流上调用 ndarray 构造函数(它被悄悄地转换为 tuple int s的em>-构造函数期望-与流的长度相同)
Conversely, when deserialization is attempted, the ndarray constructor is invoked on the byte stream, (which is silently converted to a tuple of ints - that the constructor expects - having the same length as the stream)
-
这里的问题是构造函数不接受大于 32 的序列:
The problem here is that the constructor doesn't accept sequences larger than 32:
>>> np.ndarray([0] * 32) array([], shape=(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), dtype=float64) >>> np.ndarray([0] * 33) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: sequence too large; cannot be greater than 32
-
要修复此问题,请 [SciPy.Docs]:应该使用numpy.frombuffer .为了使新的 ndarray 等于原始的 ,还需要2件事(原始数据需要数据):
To fix it, [SciPy.Docs]: numpy.frombuffer should be used. For the new ndarray to be equal to the original one, 2 more things are required (data needed from the original):
- 应指定其 dtype (默认为 float ,我们需要 uint8 )
- 需要重塑
- Its dtype should be specified (default is float and we need uint8)
- Needs to be reshaped
输出:
e:\Work\Dev\StackOverflow\q054326620>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code00.py Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32 Original image data - Type: <class 'numpy.ndarray'>, Size: 1493331, Attrs: (799, 623, 3) Wrong img0 stream length: 629 Wrong img0 stream: b'[[[255 255 255]\n [255 255 255]\n [255 255 255]\n ...\n [255 255 255]\n [255 255 255]\n [255 255 255]]\n\n [[255 255 255]\n [255 255 255]\n [255 255 255]\n ...\n [255 255 255]\n [255 255 255]\n [255 255 255]]\n\n [[255 255 255]\n [255 255 255]\n [255 255 255]\n ...\n [255 255 255]\n [255 255 255]\n [255 255 255]]\n\n ...\n\n [[255 255 255]\n [255 255 255]\n [255 255 255]\n ...\n [255 255 255]\n [255 255 255]\n [255 255 255]]\n\n [[255 255 255]\n [255 255 255]\n [255 255 255]\n ...\n [255 255 255]\n [255 255 255]\n [255 255 255]]\n\n [[255 255 255]\n [255 255 255]\n [255 255 255]\n ...\n [255 255 255]\n [255 255 255]\n [255 255 255]]]' Correct img0 stream length: 1493331 Encrypted length: 1991128 Decrypted length: 1493331 Final image data - Type: <class 'numpy.ndarray'>, Size: 1493331, Attrs: (799, 623, 3)
@ EDIT0 :
@EDIT0:
显然,存在一些兼容性问题.我使用 Python 3 和 pycrpytodome 3.7.2 开发了答案.我升级到最新版本( 3.7.3 ),也将其安装在 Python 2 上,并且上面的代码有效.这是我在控制台中得到的:
Apparently, there are some compatibility problems. I developed the answer using Python 3 and pycrpytodome 3.7.2. I upgraded to latest (3.7.3), I've also installed it on Python 2, and the code above works. Here's what I get in the console:
>>> from Crypto.Cipher import AES >>> AES <module 'Crypto.Cipher.AES' from 'e:\Work\Dev\VEnvs\py_064_02.07.15_test0\lib\site-packages\Crypto\Cipher\AES.pyc'> >>> AES.new("") Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: new() takes at least 2 arguments (1 given) >>> import Crypto >>> Crypto.__version__ '3.7.3'
因此,您可能有一个非常旧的 pycryptodome 版本.无论如何,我会盲目发布您的代码所需的更改,以合并这些修复程序( while 循环仅):
So, you probably have a terribly old pycryptodome version. Anyway, I'm blindly posting the changes required by your code, to incorporate the fixes (the while loop only):
# The rest of your code (exactly as in the question) while True: a = a + 1 check, frame = video.read() original_meta = frame.dtype.name, frame.shape encrypted_meta = EncodeAES(cipher, bytes(original_meta)) encrypted_data = EncodeAES(cipher, frame.tobytes()) # Here is the separation decrypted_meta = DecodeAES(cipher, encrypted_meta) decrypted_data = DecodeAES(cipher, encrypted_data) meta = ast.literal_eval(decrypted_meta) img = np.frombuffer(decrypted_data, dtype=np.dtype(meta[0])).reshape(meta[1]) cv2.imshow("Capturing", img) key = cv2.waitKey(1) if key == ord("q"): break
这篇关于ValueError:序列太大;不能大于32的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-