np.rot90() повреждает изображение opencv
При попытке повернуть пейзажное изображение в портретное, после применения поворота я не могу нарисовать изображение.
img1 = cv2.imread('a.jpg')
cv2.circle(img1, tuple([10,10]),radius = 3, color = (255,0,0))
работает отлично.
Тогда я пытаюсь:
img2 = np.rot90(img1,3)
cv2.circle(img2, tuple([10,10]),radius = 3, color = (255,0,0))
и я получаю ошибку:
TypeError: Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
Смотря на type(img2)
а также img2.dtype
это похоже на img1. размеры также кажутся хорошими (первые два измерения переворачиваются, третье остается "3")
Кстати, это похоже на работу. (Зачем?):
img2 = np.rot90(img1,3)
img3 = img2.copy()
cv2.circle(img3, tuple([10,10]),radius = 3, color = (255,0,0))
2 ответа
У меня была та же проблема, и я никогда не доходил до ее сути. Обходной путь, который я использовал, заключался в том, чтобы сделать вращение / отражение изображения с помощью OpenCV, например:
# flip image vertically
img = cv2.flip(img, 0)
# flip image horizontally
img = cv2.flip(img, 1)
# transpose image
img = cv2.transpose(img)
Обратите внимание, что вращение эквивалентно выполнению транспонирования и переворачивания.
не совсем портит изображение как таковое. Причина этого в том, что OpenCV не может работать с «представлениями» массивов numpy.
np.rot90
, а также несколько других операций с numpy фактически не изменяют базовый массив, а вместо этого возвращают модифицированное «представление» в массив. Обычно это вызывает следующую ошибку с OpenCV ops:
Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
Expected Ptr<cv::UMat> for argument 'img'
Такие операции, как
np.rot90(img1)
,
np.fliplr(img1)
,
np.flipud(img1)
,
np.transpose(img1, (1, 0, 2))
и т. д. все просто возвращают представления и все выдают ту же ошибку выше.
Причина, по которой добавление устраняет ошибку, заключается в том, что при вызове представления оно сохраняется в памяти как новый массив, отличный от исходного массива. На самом деле вы можете проверить это довольно просто:
import numpy as np
img = np.random.choice(256, (50, 100, 3)).astype(np.uint8)
img_r = np.rot90(img)
print(img_r == img)
# False
print(np.shares_memory(img, img_r))
# True
img_r = img_r.copy()
print(np.shares_memory(img, img_r))
# False
Как видите, хотя
img_r == img
показывает
False
, они по-прежнему используют одну и ту же память - как и в представлении. Но после звонка
.copy()
, вид
img_r
становится собственным массивом и больше не разделяет память с исходным
img
.