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.

Другие вопросы по тегам