OpenCV 图像深度被 JSON 损坏

OpenCV Image Depth is Corrupted by JSON

我正在开展一个项目,该项目需要使用 JSON 传输 OpenCV 帧,其中帧在接收端的 CascadeClassifier 中使用。我遇到了CascadeClassifier的错误:

Kyles-MBP:facial_detection kyle$ python3 badcv.py
Traceback (most recent call last):
  File "badcv.py", line 30, in <module>
    doesnt()
  File "badcv.py", line 26, in doesnt
    faces = cascade.detectMultiScale(imgnew)
cv2.error: OpenCV(3.4.2) /Users/travis/build/skvark/opencv-python/opencv/modules/objdetect/src/cascadedetect.cpp:1376: error: (-215:Assertion failed) scaleFactor > 1 && _image.depth() == 0 in function 'detectMultiScale'

Kyles-MBP:facial_detection kyle$

我已经提炼了我的代码以隔离下面的错误。显然我做错了什么,但我没有足够的 OpenCV 经验来知道在这里做什么。我做了一些搜索,图像深度 0 对应于 CV_8U,但是我不知道如何设置这样的深度(我做了一些搜索并得出结论,这不重要,因为 cv2 本机将图像表示为 ndarray,但这可能是一个错误的假设)。此外,我无法确定 pre 和 post jsonified ndarray 之间的任何区别;根据我的估计,除了内存中的物理位置之外的所有度量,pre 和 post 数组是相同的。我在下面包含了调查数据结构的解释器输出。

我做错了什么,如何避免遇到这个特定错误?谢谢!

代码:

# badcv.py
import cv2
import json
import numpy as np
import os
import sys

cascade_file_path = os.path.dirname(
    os.path.realpath(__file__)) + '/default.xml'

def works():
    img = cv2.imread(sys.argv[1])
    imgnew = img

    rows, cols = imgnew.shape[:2]
    cascade = cv2.CascadeClassifier(cascade_file_path)

    faces = cascade.detectMultiScale(imgnew)

def doesnt():
    img = cv2.imread(sys.argv[1])
    data = { 'file': json.dumps(img.tolist()) }
    imgnew = np.array(json.loads(data['file']))

    if not (img is imgnew):
        print("Not the same object")

    rows, cols = imgnew.shape[:2]
    cascade = cv2.CascadeClassifier(cascade_file_path)

    faces = cascade.detectMultiScale(imgnew)

if __name__ == "__main__":
    works()
    doesnt()

作为附录:default.xml 文件是 OpenCV 附带的 Haar xml 分类器,我使用的是一个 10px X 20px 的简单测试文件,但是这个脚本仍然失败图片大小,包括 jpg 和 png。

平等:

我也检查了对象是否相等,下面的断言是有效的:

>>> if (img == imgnew).all(): print("element-wise equality)
'element-wise equality'

但是对象级别的相等性无效(这是有道理的,因为 json.loads 将 return 一个新字典,而不是内存中的缓存字典):

>>> if not (img is imgnew): print("not the same object")
'not the same object'

imgimgnew的类型都是ndarray,形状相同:

>>> if type(img) is type(imgnew): print("same type")
'same type'
>>> type(img)
<class 'numpy.ndarray'>
>>> if img.shape == imgnew.shape: print("same shape")
'same shape'

I did some searching, and an image depth 0 corresponds to CV_8U, however I have no idea how to set such a depth

你在正确的轨道上。这是图像的位深度,每个像素的数据类型。 img 将加载一个数据类型 np.uint8,一个无符号的 8 位整数,与 CV_8U.

相同

当你通过 json 时,像素值变为 Python 整数,创建的 numpy 数组将具有 np.int64 dtype。

因此问题:

>>> img.dtype == imgnew.dtype
False

可以通过以下方式纠正:

# Create an array with 8-Bit unsigned integers
imgnew_u8 = imgnew.astype(np.uint8)