Se eu correr:
import numpy as np
import cv2
def changes():
rmat=np.eye(4)
tvec=np.zeros(3)
(rvec, jacobian)=cv2.Rodrigues(rmat)
print rvec
for i in range(2):
changes()
Eu recebo:
[[6.92798859e-310]
[2.19380404e-316]
[1.58101007e-322]]
[[0.]
[0.]
[0.]]
Então, o resultado das changes()
mudanças.
Eu não entendo por que isso é, e o fato de ele parar de mudar se a tvec=np.zeros(3)
linha for comentada, me faz sentir que isso é um bug no sistema.
np.zeros(3)
em duas variáveis diferentes . Se eu não armazenar o resultado ou usar a mesma variável duas vezes, não será. Talvez alguém com um conhecimento mais entorpecido possa esclarecer isso.Respostas:
É 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: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: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 1Drmat
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:fonte
np.empty
esse comportamento é bem conhecido, porque leva os bytes de memória à medida que eles chegam, sem atualizar os valores existentes. Mas acv2.Rodrigues
função deve retornar alguns valores significativos, após um cálculo rigoroso. Além disso, os valores estranhos apresentados no OP dificilmente podem ser considerados lixo, pois estão todos muito próximos de zero.Definitivamente, é um bug na função Rodrigues ...
Se você ler o documento correspondente , poderá ver que
cv2.Rodrigues
possui 2 interfaces diferentes:aquele que imita a interface C ++, onde o vetor de rotação (e opcionalmente o jacobiano) é passado por referência e modificado pela função
e um (mais Pythonic) onde o vetor de rotação e o jacobiano são retornados como uma tupla
Se você usar a primeira interface, o pb desaparece ...
Resultado:
EDITAR após uma investigação mais aprofundada:
A função é ainda mais incorreta conforme o esperado: ao usar a primeira interface, os parâmetros
dst
ejacobian
não são modificados, o que contraria totalmente a doutrina:Em outras palavras, isso claramente requer um relatório de erro ...
fonte
np.eye(4)
. O método requer vetor de rotação (3x1 ou 1x3) ou matriz de rotação (3x3). Aqui com np.eye (4) a função cria dst com algum tamanho. Mas como o formato de entrada está errado, o método não faz nada e o deixa unitizado. Além disso, você está apontando para uma versão obsoleta do OpenCV. É melhor usar a versão principal ou apontar para uma versão específica: consulte docs.opencv.org .