距离这篇文章发布一年了,感谢评论区朋友让我又沉下心研究了一下这个问题,我认为这个回答已经基本解释了问题发生的浅层逻辑。
懒人版:使用np.ascontiguousarray(array)重整你报错的变量
python opencv TypeError: Layout of the output array incompatible with cv::Mat - Stack Overflow
这是最早报错的提示,一开始我以为是读入的prob类型不匹配(这个思路误导了我一个周末),在这个思路下我对prob进行了相当多的调试(包括上面注释掉的部分,当时怀疑是数组尺度问题,专门又回去复习了一遍数组reshap和transpose的区别),然后又怀疑是normalize识别的prob是不是因为不是标准BGR或者HSV不能识别,最后意外之下看了另外一个类似的报错才考虑到了是不是变量本身的问题。
Traceback (most recent call last):
File "D:/learnOpenCV4_Python-main/chapter12/NeuralStyle.py", line 48, in <module>
cv.normalize(prob, prob, 0, 255, cv.NORM_MINMAX) # 这里应当读入一个图像格式
cv2.error: OpenCV(4.5.3) :-1: error: (-5:Bad argument) in function 'normalize'
> Overload resolution failed:
> - Layout of the output array dst is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
> - Expected Ptr<cv::UMat> for argument 'dst'
这里用了一个copy函数对prob进行深拷贝,避免了normalize中同时存在两个同一地址的变量(但是我看到的对normalize函数介绍的文章中都指出其支持原地运算,这点和我的猜想不符,我从该函数的声明中也没有找到这种说法,如果看到这篇文章的人有了解请告诉我),我还测试了直接使用np.zero构建一个同样shape的新array,也是可以的(但是需要调整数据类型使之与输入数组也一致,本文是float32)。
import cv2 as cv import numpy as np import sys if __name__ == '__main__': image = cv.imread('./images/lena.jpg') # 判断是否成功读取图像 if image is None: print('Failed to read lena.jpg.') sys.exit() cv.imshow('Origin', image) # 计算图像均值 image_mean = np.mean(image) # 计算图像尺寸 h, w = image.shape[:-1] # 设置需要进行迁移的图像风格 styles = ['the_wave.t7', 'mosaic.t7', 'feathers.t7', 'candy.t7', 'udnie.t7'] for i in range(len(styles)): # 加载模型 net = cv.dnn.readNet('./data/styles/{}'.format(styles[i])) # 调整图像尺寸 blob = cv.dnn.blobFromImage(image, 1.0, size=(512, 512), mean=image_mean, swapRB=False, crop=False) # 计算网络对图像的处理结果 net.setInput(blob) prob = net.forward() # 尝试绕过问题 # prob = prob.reshape(prob.shape[2], prob.shape[3], 3) # 恢复图像减掉的均值 # prob += image_mean # 对图像进行归一化 # prob = prob/255.0 # 没有解决问题,但是可以输出错误的图像 prob = prob.reshape(3, prob.shape[2], prob.shape[3]) # 恢复图像减掉的均值 prob += image_mean # 对图像进行归一化 prob = prob / 255.0 prob = prob.transpose(1, 2, 0) prob = np.clip(prob, 0.0, 1.0) # 下面是解决问题的关键行 prob = prob.copy() # 上面是解决问题的关键行 cv.normalize(prob, prob, 0, 255, cv.NORM_MINMAX) # 这里应当读入一个图像格式 # 调整到最终需要显示的图像尺寸 result = np.uint8(cv.resize(prob, (w, h))) cv.imshow('{}'.format(styles[i]), result) cv.waitKey(0) cv.destroyAllWindows()