Нормализация, сохраняя значение dst как пустой массив - PullRequest
0 голосов
/ 19 марта 2019

Я пытался нормализовать простой массив NumPy a следующим образом:

a = np.ones((3,3))

cv2.normalize(a)

При запуске этого OpenCV выдает ошибку, говорящую TypeError: Required argument 'dst' (pos 2) not found.Поэтому я поставил аргумент dst, как также упоминалось в документации .Вот как я это сделал:

b = np.asarray([])
cv2.normalize(a, b)

Этот вызов возвращает нормализованный массив, но значение b все еще пусто.Почему это так?

С другой стороны, если я попробую следующее:

b = np.copy(a)

cv2.normalize(a,b)

Значения в b теперь заполнены нормализованными значениями.Я просто хотел понять это поведение OpenCV.Почему он не заполняет b, когда он пуст / форма не совпадает с a?Почему OpenCV не выдает ошибку?

1 Ответ

2 голосов
/ 19 марта 2019

Вам потребуется присвоить результат cv2.normalize обратно переменной, в первом примере. С документы , подпись для cv2.normalize():

dst = cv.normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]])

Вы заметите, что dst является как входным, так и возвращаемым значением функции. Это означает, что вы можете либо ввести массив dst в функцию, и он будет изменен на месте, или , вы можете передать None или пустой массив для этого аргумента при вызове функции и новый массив будет создан и возвращен.


Чтобы быть более конкретным, если вы не очень хорошо знакомы с C ++: в C ++ вы, как правило, возвращаете только примитивы (например, целые числа) или указатели из функций. Это не так просто, как в Python, где вы можете просто вернуть любое количество любых объектов, которые вы хотите; Вы должны поместить их в контейнер и вернуть указатель на этот контейнер, например. Итак, более распространенная вещь для вас - передать объект функции напрямую, и функция просто изменит объект, вместо того, чтобы беспокоиться о возвратах и ​​всей этой чепухе. Кроме того, это означает, что функция не создает объекты за кадром, о которых вы не знаете. Вместо этого вы управляете созданием и созданием объектов и передаете их в функцию.

Гораздо реже (хотя все еще возможно) в Python передавать изменяемые аргументы в функции с пониманием того, что они будут изменены.

Поскольку привязки для OpenCV автоматически генерируются из библиотек C ++, функции могут использоваться любым из этих способов; Вы можете инициализировать массив правильного размера / формы, передать его и мутировать (стандартным способом C ++), или , который вы можете передать None или пустой массив, и он будет возвращает выходной массив (стандартным способом Python).

На самом деле это очень распространено во всей библиотеке OpenCV. Если вы видите тот же вход, что и один из выходов, и вам не нужно использовать его для инициализации функции, вы в основном всегда можете отправить None для этого аргумента.


Я не уверен, что философская причина почему OpenCV решает не выдавать ошибку, если вы передаете туда полностью поддельные массивы, хотя этот тип вопроса не совсем подходит для этого сайта , Кроме того, ошибки не очень согласованы в OpenCV, где они чрезвычайно строги в отношении утверждений для проверки аргументов функции, но с радостью вернут нулевой указатель, если вы попытаетесь прочитать изображение, которое не существует. В любом случае, в случае неправильной формы / типа происходит просто то, что аргумент игнорируется. Аргумент изменяется только в том случае, если это правильная форма / тип. Вы можете вообразить что-то подобное:

In [29]: a = np.eye(3, dtype=np.float64)

In [30]: b = np.eye(3, dtype=np.uint8)  # different dtype

In [31]: c = np.eye(2)  # different shape

In [32]: d = 'asdf'  # not even an array

In [33]: cv2.normalize(a, b)
Out[33]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

In [34]: b  # not modified because different dtype
Out[34]:
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]], dtype=uint8)

In [35]: cv2.normalize(a, c)
Out[35]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

In [36]: c  # not modified because different shape
Out[36]:
array([[1., 0.],
       [0., 1.]])

In [37]: cv2.normalize(a, d)  # error because it's not convertible to a `cv::UMat`
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-642f9bb78a6b> in <module>
----> 1 cv2.normalize(a, d)

TypeError: Expected cv::UMat for argument 'dst'

Но когда у нас есть правильная комбинация формы и типа:

In [38]: e = np.empty_like(a)   # same dtype/shape as a

In [39]: cv2.normalize(a, e)
Out[39]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

In [40]: e  # mutated
Out[40]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...