É muito provável que uma matriz não inicializada, como retornada por np.empty
. Isso, juntamente com a reciclagem da memória, pode levar ao tipo de efeito que você está vendo. Um exemplo mínimo seria:
for a in range(5):
y = np.empty(3,int)
x = (np.arange(3)+a)**3
print(x,y)
del x
# [0 1 8] [94838139529536 0 0]
# [ 1 8 27] [0 1 8]
# [ 8 27 64] [ 1 8 27]
# [ 27 64 125] [ 8 27 64]
# [ 64 125 216] [ 27 64 125]
Observe como na primeira iteração y
contém lixo e a cada iteração subseqüente, ele contém o valor do anterior, x
porque é atribuída sua memória que foi liberada pouco antes.
Podemos verificar facilmente que, no exemplo original, também é o anterior tvec
que aparece:
def changes():
rmat=np.eye(4)
tvec=np.array([4,0.0,2.5])
(rvec, jacobian)=cv2.Rodrigues(rmat)
print(rvec)
for i in range(3):
changes()
# [[4.6609787e-310]
# [0.0000000e+000]
# [0.0000000e+000]]
# [[4. ]
# [0. ]
# [2.5]]
# [[4. ]
# [0. ]
# [2.5]]
Podemos especular ainda que é a escolha peculiar de rmat
quem desencadeia o erro.
Provavelmente, é um erro eye(4)
aceito, porque, oficialmente, rmat
deve ser 3x1 1x3 ou 3x3. De fato, um 1D rmat
que não possui 3 elementos é corretamente rejeitado pelo wrapper Python. Minha suspeita é que os 2D´rmat`s não são devidamente verificados no nível do Python. O código C, em seguida, detecta que a forma incorreta não faz nada, exceto retornar um código de erro que o código Python não verifica.
De fato, usar um rmat=eye(3)
efeito desaparece:
def changes():
rmat=np.eye(3)
tvec=np.array([4,0.0,2.5])
(rvec, jacobian)=cv2.Rodrigues(rmat)
print(rvec)
for a in range(3):
changes()
# [[0.]
# [0.]
# [0.]]
# [[0.]
# [0.]
# [0.]]
# [[0.]
# [0.]
# [0.]]