OpenCV и Numpy плохо взаимодействуют
Может ли кто-нибудь объяснить, почему импорт cv и numpy изменит поведение python struct.unpack? Вот что я наблюдаю:
Python 2.7.3 (default, Aug 1 2012, 05:14:39)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from struct import pack, unpack
>>> unpack("f",pack("I",31))[0]
4.344025239406933e-44
Это правильно.
>>> import cv
libdc1394 error: Failed to initialize libdc1394
>>> unpack("f",pack("I",31))[0]
4.344025239406933e-44
Все еще хорошо, после импорта cv
>>> import numpy
>>> unpack("f",pack("I",31))[0]
4.344025239406933e-44
И ОК после импорта cv, а затем numpy
Теперь я перезапускаю python:
Python 2.7.3 (default, Aug 1 2012, 05:14:39)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from struct import pack, unpack
>>> unpack("f",pack("I",31))[0]
4.344025239406933e-44
>>> import numpy
>>> unpack("f",pack("I",31))[0]
4.344025239406933e-44
До сих пор так хорошо, но теперь я импортирую cv после импорта numpy:
>>> import cv
libdc1394 error: Failed to initialize libdc1394
>>> unpack("f",pack("I",31))[0]
0.0
Я повторял это несколько раз, в том числе на нескольких серверах, и это всегда происходит одинаково. Я также пробовал это с struct.unpack и struct.pack, что тоже не имеет значения.
Я не могу понять, как импорт numpy и cv может вообще иметь какое-либо влияние на вывод struct.unpack(пакет остается тем же, btw).
"libdc1394" - это, я считаю, красная селедка: ошибка ctypes: ошибка libdc1394: не удалось инициализировать libdc1394
Любые идеи?
tl; dr: импортирует numpy, а затем opencv изменяет поведение struct.unpack.
ОБНОВЛЕНИЕ: нижеприведенный ответ Пауло показывает, что это воспроизводимо. Комментарий Seborg предполагает, что это как-то связано с тем, как python обрабатывает субнормальные значения, что звучит правдоподобно. Я рассмотрел Контексты, но это, похоже, не было проблемой, так как контекст был таким же после импорта, как и до них.
Ответы
Ответ 1
Это не ответ, но он слишком большой для комментария. Я немного играл со значениями, чтобы найти пределы.
Без загрузки numpy
и cv
:
>>> unpack("f", pack("i", 8388608))
(1.1754943508222875e-38,)
>>> unpack("f", pack("i", 8388607))
(1.1754942106924411e-38,)
После загрузки numpy
и cv
первая строка будет такой же, но вторая:
>>> unpack("f", pack("i", 8388607))
(0.0,)
Вы заметите, что первым результатом является нижний предел для 32-битных поплавков. Затем я попробовал то же самое с d
.
Без загрузки библиотек:
>>> unpack("d", pack("xi", 1048576))
(2.2250738585072014e-308,)
>>> unpack("d", pack("xi", 1048575))
(2.2250717365114104e-308,)
И после загрузки библиотек:
>>> unpack("d",pack("xi", 1048575))
(0.0,)
Теперь первым результатом является нижний предел для точности 64-битного float.
Похоже, что по какой-то причине загрузка библиотек numpy
и cv
в этом порядке ограничивает unpack
для использования 32 и 64-битной точности и возвращает 0 для более низких значений.