Analisi anomalie foto Apollo con strumenti matematici

Di più
7 Anni 8 Mesi fa #8964 da FranZeta

doktorenko ha scritto: la fase 2 (forza bruta) funziona, pero` trova piu` combinazioni di angoli per cui le rette individuate concorrono: a me invece servirebbe una posizione unica.

Per questo ti invitavo a chiarire quello che vuoi ottenere! Applicando omografie "casuali" puoi far convergere le rette in molti modi, e verso punti diversi. Prima di parlare meglio dei procedimenti per ricostruire la scena 3D è il caso di linkare questa esposizione dell'argomento, molto chiara e non eccessivamente tecnica (per confronto questa invece è un'esposizione tecnica), in un prossimo messaggio voglio esporre la sintesi con allegato l'esempio pratico fatto sulle due foto Apollo 15.

A pagina 248 del primo documento linkato trovi il tuo metodo delle rette concorrenti, tieni presente che tutte le rette individuate da punti corrispondenti convergono verso un unico punto, che rappresenta la direzione della traslazione fra i due scatti, o meglio il punto all'infinito corrispondente al vettore traslazione. Anche in questo caso quindi la complanarità non c'entra. Inoltre la condizione di concorrenza delle rette è sufficiente ma non necessaria: se c'è solo uno spostamento perpendicolare alla direzione delle inquadrature (quindi la traslazione è solo nelle due direzioni individuate dal piano della foto, destra-sinistra e alto-basso) le rette convergono verso un punto all'infinito nel piano dell'immagine, vale a dire che sono parallele. Quest'ultimo caso però fortunatamente non si verifica nelle foto prese in considerazione.

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa #8980 da kamiokande

doktorenko ha scritto: Sto ricostruendo il modulo (semplificato) perche` i modelli liberamente disponibili mi sembrano poco accurati nelle misure.

Forse potrebbe esserti utile questo sito www.ehartwell.com/LM/SCATSystems.htm


"La stampa è morta" (Egon Spengler - Ghostbuster)

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #8994 da FranZeta
Come promesso inizio a esporre una sintesi del processo matematico usato per trattare immagini stereoscopiche, lo scopo del quale è ricostruire per quanto possibile la scena 3D ripresa da due fotocamere. Il testo di riferimento è quello già linkato sopra, si tratta del capitolo di un libro che purtroppo non possiedo, era nei riferimenti bibliografici nella pagina di wikipedia sulla matrice fondamentale, che come suggerisce il nome è l'oggetto cardine di tutta la teoria. Cercherò di fare il possibile per sorvolare gli aspetti tecnici che lascio alla vostra voglia di approfondire, qui più che altro voglio applicare il metodo alla coppia di foto di Apollo 15.

Un minimo di teoria però è necessario introdurla, quindi partiamo da questa figura del documento di riferimento:



La situazione dunque è questa: due fotocamere riprendono la stessa scena da due diverse posizioni (C e C') puntate verso direzioni qualunque, seguendo la notazione del libro indichiamo con X il punto della scena 3D che viene mappato nel punto x della prima immagine e x' della seconda. Nelle due immagini esistono due punti fondamentali: gli epipoli e ed e', questi risultano essere i due punti corrispondenti alla posizione della fotocamera che scatta rispettivamente la seconda e la prima immagine. Ora vediamo il motivo della loro importanza. Supponiamo di sovrapporre le due immagini (cosa che faremo tra breve), al punto x della prima corrisponderà un qualche punto x' della seconda, questo punto deve per forza trovarsi su una retta l' che parte dall'epipolo e', l' rappresenta il raggio che congiunge la fotocamera 1 col punto X della scena 3D. Stessa cosa vale invertendo i ruoli con x, e, l (si vede la rappresentazione grafica nella figura 9.1 b).

Quindi ad ogni punto x della prima immagine (d'ora in poi semplicemente 1) corrisponde una retta l' in 2 e viceversa ad x' in 2 corrisponde l in 1. Qui entra in gioco la matrice fondamentale F che rappresenta la funzione x-->l', mentre la funzione opposta x'-->l è data da F^T (trasposta), risulta perciò:
Code:
l'=F*x l=F^T*x'
Per ragguagli sulle coordinate da usare in queste formule consiglio di guardare nel documento, non mi pare il caso di appesantire ulteriormente. Ci basti sapere che F è una matrice 3x3 di rango 2 ed è un oggetto proiettivo proprio come le omografie, quindi con una coordinata in più dell'effettiva dimensione, questi due fatti fanno sì che i coefficienti liberi di F da 9 passino a 7 (-1 perchè è proiettiva e -1 perchè det(F)=0). La matrice F stabilisce anche la seguente relazione basilare fra punti corrispondenti x e x':
Code:
1) x'^T*F*x=0
L'equazione qui sopra esprime algebricamente quanto già detto, ossia che x sta sulla retta l e x' su l'. Ogni coppia (x,x') che soddisfi la 1) rappresenta due punti immagini dello stesso punto X nella scena reale. Siccome sviluppando la 1) si ottiene un'equazione lineare nelle 9 incognite (F)_ij dei coefficienti della matrice, e siccome solo 7 di questi sono indeterminati, la matrice F può essere ricavata stabilendo 7 corrispondenze fra punti delle due immagini, cioè si risolve il sistema:
Code:
x1'^T*F*x1=0 ...... x7'^T*F*x7=0
cosa che adesso facciamo subito per la coppia di immagini Apollo 15. Iniziamo con l'incollare le due immagini una sull'altra senza alcuna modifica (io l'ho fatto in Matlab usando la funzione imfuse):



Poi individuiamo 7 coppie di punti "comodi" corrispondenti, per esempio il primo punto che ho scelto è la stellina in basso a sinistra della bandiera americana. Una nota sulle coordinate: per fare questo lavoro ho copiato l'immagine sopra in geogebra, l'ho ridimensionata a 40x40 (la misura originale in mm) e poi l'ho leggermente spostata in modo da allineare la croce centrale con l'origine degli assi, visto che non era perfettamente centrata. Infine ho preso pari pari le coordinate dei punti con due decimali e ho passato il tutto al caro Maple che ha fatto i calcoli per me, ecco il risultato:



Come si può vedere per prima cosa calcolo la matrice F, si tenga presente che essendo proiettiva se moltiplico tutto per una costante diversa da 0 si ottiene sempre la stessa matrice, poi sotto ho verificato che det(F)=0 (circa!), mentre sotto ancora ci sono altri calcoli che vado a spiegare subito. Serve solo ancora un pochino di teoria, abbiate pazienza...
...allora una volta nota F è conveniente decomporla nella somma di una matrice simmetrica S e una antisimmetrica A, esplicitamente si fa così:
Code:
F=S+A S=(F+F^T)/2 A=(F-F^T)/2
L'espressione esplicita delle due matrici è la seconda parte del calcolo riportato sopra. Alla matrice S corrisponde una conica nel piano delle due immagini incollate, mentre ad A corrisponde il punto x_a nello stesso piano. Avendo a disposizione conica e punto si possono fare le seguenti costruzioni geometriche:



Nella figura 9.10 a) vediamo la prima costruzione: la retta l_a è la polare di x_a rispetto alla conica F_S, questa retta interseca F_S in due punti che risultano essere i nostri epipoli. Gli epipoli possono essere calcolati direttamente risolvendo i sistemi:
Code:
F*e=0 F^T*e'=0
e questa è l'ultima parte del calcolo riportato sopra, le coordinate [x,y] sono quelle di e e le [X,Y] di e', se abbiamo fatto le cose bene queste devono corrispondere a quelle dei due punti trovati con la costruzione geometrica della retta polare, cosa che in effetti avviene con buona approssimazione, ecco infatti l'immagine finale:



Oltre agli oggetti già spiegati, nella figura ci sono due rette arancioni che corrispondono alla costruzione della figura 9.10 b): dato il punto x (nel nostro caso è P2) nella prima immagine, per trovare la retta l' ad esso associata si traccia prima la retta l passante per x ed e (P2 e E nell'immagine Apollo), questa interseca la conica in un punto x_c, infine la retta l' cercata è la retta passante per x_c ed e' (E'). In pratica se abbiamo fatto le cose per bene, per ogni coppia di punti Pi,Pi' sull'immagine deve valere che le due rette PiE e Pi'E' si intersecano in un punto della conica. Qui c'è la verifica per alcuni dei punti utilizzati:



Come sempre, in questi casi, bisogna tenere presente che da una parte c'è l'iperuranio, cioè il mondo platonico delle idee matematiche astratte e perfette, dall'altra c'è il mondo reale con tutte le sue imperfezioni, nello specifico la realtà ha le fattezze delle nostre foto Apollo e le intersezioni evidenziate dai circoletti sono solo approssimativamente sulla conica, ingrandendo le parti evidenziate si troverebbero delle discrepanze. Per chi fosse interessato questo è il link per il file di geogebra e questo per fare delle eventuali modifiche ad un file gemello modificabile a piacere.

Per ora mi fermerei qui, nella prossima puntata vedremo di cercare di ricavare una coppia di possibili matrici camera per le due foto Apollo.

FranZη
Ultima Modifica 7 Anni 8 Mesi fa da FranZeta. Motivo: sistemati un paio di apostrofi invertiti

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #8996 da doktorenko
@FranZeta
nell`attesa della seconda parte, ho provato a calcolare la matrice fondamentale F con il modulo OpenCV, usando questo codice:

Geometria epipolare

A parte naturalmente il nome delle immagini (sx=11601; dx=11602), ho dovuto modificare solo questa riga:
Code:
sift = cv2.SIFT()
in:
Code:
sift = cv2.xfeatures2d.SIFT_create()

Risultato (mi ha trovato un sacco di punti utili!):


Matrice F:
Code:
array([[ 1.54590733e-08, 1.31312522e-06, -2.31504371e-03], [ -1.29520987e-06, 7.64118313e-08, -1.06896770e-03], [ 2.74047832e-03, 5.50595730e-04, 1.00000000e+00]])


Aggiungo il codice (in python/numpy) della prima parte dei tuoi calcoli:
Code:
F=np.matrix([[0.0002249705489,0.02234261333,-0.1725523678],\ [-0.01959259243,0.005407583090,-0.2555901116],\ [0.2428871895,0.2098212272,1]]) S=(F+F.transpose())/2 A=(F-F.transpose())/2 M=np.delete(np.array(F),1,0) a=M[:,:-1] b=-M[:,2] x,y=np.linalg.solve(a,b) M=np.delete(np.array(F).transpose(),1,0) a=M[:,:-1] b=-M[:,2] X,Y=np.linalg.solve(a,b) >>> x -10.883432648836861 >>> y 7.8326029740642245 >>> X -12.357155656359714 >>> Y 12.254998631089576

Invece, con la matrice F che ho calcolato io, le coordinate dei punti epipolari sono:
Code:
>>> px=4175 >>> mm=55.44 >>> X/px*mm -7.1978876554283415 >>> Y/px*mm 28.010637232681304 >>> x/px*mm -9.5717150249253162 >>> y/px*mm 23.523676064212165

Il risultato e` parecchio diverso, forse dipende anche dal fatto che dovrei filtrare la scelta in modo da avere meno coppie di punto, ma individuate piu` precisamente.
Ultima Modifica 7 Anni 8 Mesi fa da doktorenko. Motivo: Aggiunto codice python

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa #8997 da doktorenko
Ho provato a costruire il grafico con la soluzione che mi da` Opencv:
Code:
F=np.matrix([[ 1.57550907e-05, -7.16872070e-05, 1.09271677e-01], [ 7.84514021e-05, -8.04395058e-06, -2.95069542e-02], [ -1.72668082e-01, 5.65996434e-02, 1.00000000e+00]]) e= (544.7,1644) e'= (555, 2089.5) S=(F+F.transpose())/2

Conica:
Code:
a11,a12,a13,a12,a22,a23,a13,a23,a33=np.array(S).flatten() print ("%.9fx^2+2 * %.9fxy+%.9fy^2+2 * %.9fx+2 * %.9fy+%.9f=0" % (a11,a12,a22,a13,a23,a33) ) >>> 0.000015755x^2+2 * 0.000003382xy+-0.000008044y^2+2 * -0.031698203x+2 * 0.013546345y+1=0

Coppie di punti:
Code:
A1(342, 2184) B1(364, 2485) A2(583, 951) B2(677, 1375) A3(910, 1488) B3(948, 1867) A4(844, 2629) B4(737, 2860)

Risultato (ho cambiato le proporzioni degli assi):


Allora anche questa soluzione dovrebbe andare bene? e come si fa a passare dalla matrice S all`equazione della conica?

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #8998 da FranZeta

doktorenko ha scritto: Allora anche questa soluzione dovrebbe andare bene? e come si fa a passare dalla matrice S all`equazione della conica?

No, la soluzione è una sola e visto che quella che ho trovato è verificata empiricamente con le intersezioni dei punti (seppure approssimate), la soluzione reale deve essere molto vicina.
La conica associata a una matrice simmetrica S si trova, posto X=(x,y,1) sviluppando il prodotto:
Code:
X^T*S*X=0
In geogebra c'è il comando Conica[<Numero>...<Numero>] dove bisogna inserire 6 numeri, sono, nell'ordine i coefficienti S_11,S_22,S_33,2*S_12,2*S_13,2*S_23 della matrice S.

PS Poi non so esattamente come hai trovato la conica, non sono stato lì a controllare il codice, comunque la direzione della camera dovrebbe essere il centro dell'immagine, a meno che il programma non tenga già conto dello spostamento, altrimenti è normale trovare risultati differenti. Inoltre ho fatto i conti in mm, non in pixel. Conta anche l'ordine in cui si prendono le due immagini, non per la conica ma per la matrice F.

PPS I punti Pi e Pi' devono essere corrispondenti!!! Altrimenti puoi fare convergere le rette dove vuoi (come sembrerebbe dalla tua ultima figura)!

FranZη
Ultima Modifica 7 Anni 8 Mesi fa da FranZeta.

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #8999 da doktorenko


Le differenze tra i due grafici dovrebbero essere:

1) i miei calcioli sono i pixel e non in mm (10 mm = 753 px)
2) il centro dell`immagine non e` all`origine degli assi ma a O(4175/2, 4175/2)
3) l`asse y e` positivo verso il basso (convenzione delle immagini informatiche)
4) forse ho usato come riferimento l`altra immagine rispetto alla tua (ordine dei punti e-e')
5) la precisione nell`individuazione dei punti di OpenCV e ` intera.

Adesso cerchero` di usare la tua convenzione per tracciare il grafico.

p.s.
come hai fatto a calcolare la dimensione di 40 mm di lato? Perche` io la tua non la vedo tagliata: i 40 mm corrispondo al quadrato interno alla griglia di 5x5 crocette.

aggiungo anche il codice per trovare la matrice fondamentale partendo dai punti:
Code:
import numpy as np import cv2 pts1 = np.array(\ [[ -15.21, 7.15],\ [ -12.95, 5.57],\ [ -9.77,7.73],\ [ -8.05, 7.65],\ [ -2.88, 0.8],\ [ 9.63, 8.17],\ [ 12.13, 8.86]]) pts2 = np.array(\ [[ -16.23, 11.48],\ [ -13.75, 9.74],\ [ -10.44, 12.08],\ [ -8.5, 12.02],\ [ -2.78, 4.62],\ [ 11.51, 12.98],\ [ 14.95, 13.98]]) F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS) F=np.matrix(F[0:3]) >>> F matrix([[ 2.24970008e-04, 2.23427304e-02, -1.72553143e-01], [ -1.95926949e-02, 5.40761741e-03, -2.55590089e-01], [ 2.42888271e-01, 2.09820763e-01, 1.00000000e+00]]) >>> x, y (-10.883362887762464, 7.8325956676863848) >>> X,Y (-12.357087076459413, 12.254990884928457)


Con i tuoi punti ottengo gli stessi risultati, anche se non so perche` il programma mi restituisce addirittura 3 coniche (nel codice ho mostrato solo la prima).
Ultima Modifica 7 Anni 8 Mesi fa da doktorenko. Motivo: aggiunte

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa #9000 da FranZeta

doktorenko ha scritto: Le differenze tra i due grafici dovrebbero essere:

1) i miei calcioli sono i pixel e non in mm (10 mm = 753 px)
2) il centro dell`immagine non e` all`origine degli assi ma a O(4175/2, 4175/2)
3) l`asse y e` positivo verso il basso (convenzione delle immagini informatiche)
4) forse ho usato come riferimento l`altra immagine rispetto alla tua (ordine dei punti e-e')
5) la precisione nell`individuazione dei punti di OpenCV e ` intera.


In realtà io mi riferivo alla differenza nelle matrici, il grafico dovrebbe essere pressochè identico perchè la posizione sull'immagine della conica e degli epipoli non dipende dal sistema di coordinate usato. Infatti nella tua immagine ci sono evidenti discrepanze:




Qui ho tracciato le due epilinee passanti per due punti corrispondenti sulla zampa del LEM che sono ben lontane dall'intersecarsi sulla conica.

p.s.
come hai fatto a calcolare la dimensione di 40 mm di lato? Perche` io la tua non la vedo tagliata: i 40 mm corrispondo al quadrato interno alla griglia di 5x5 crocette.

Sono andato a memoria, mi pareva di ricordare che la pellicola fosse 40x40. Questo però non modifica la sostanza dei calcoli fatti sopra, è solo un cambio di unità di misura. Già che ci siamo, qual era la dimensione effettiva della pellicola?

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #9001 da doktorenko
Non ti preoccupare troppo dei miei esperimenti: sono fatti per capire se e` possibile affidare ad un algoritmo la scelta dei punti.
In questa prova ho cercato di rispettare la tua convenzione: dopo la scelta dei punti (automatica) ho trasformato le coordinate in questo modo:
Code:
px=4175. mm=55.44 pts1=(((pts1-px/2)*[1,-1])*55.44)/px pts2=(((pts2-px/2)*[1,-1])*55.44)/px

La matrice F calcolata dalle 12000 (!) coppie di punti individuati :
Code:
F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS) >>> F matrix([[ 7.17589983e-05, -5.93437573e-03, 2.09125440e-02], [ 5.89581319e-03, 3.53392050e-04, 2.15287984e-01], [ 1.01037585e-02, -2.04270651e-01, 1.00000000e+00]])

La conica
Code:
c: 0.29x² - 0.16x y + 1.43y² + 127.06x + 45.14y = -4096

Il grafico:



Non si riesce a vedere, ma i punti che hai individuato come errati precedentemente ora convergono (approssimativamente) sulla conica.
Come ho scritto in precedenza, bisognerebbe abbassare il numero dei punti, aumentandone pero` la precisione nella scelta; purtroppo non ho ancora capito bene su quali parametri agire per ottenere questo risultato.

La dimensione della diapositiva originale la calcolo in questo modo:
Code:
spazio (10 mm) tra due crocette = 753 px dimensione immagine: 4175 px 4175 px / 753 px * 10 mm = 55.44 mm
Ultima Modifica 7 Anni 8 Mesi fa da doktorenko.

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #9003 da doktorenko
Sto cercando di capire come ricavare i punti Pxyz partendo dai punti corrispondenti Puv e P'uv.

Procedimento:

1) ricavare la matrice essenziale E (la mat. F l`abbiamo calcolata in precedenza):
Code:
lunghezza focale f = 0.0611 m sensore f = 0.05544 m K=np.matrix([ [ f, 0, l/2 ], [ 0.0, f, l/2 ], [ 0.0, 0.0, 1.0 ] ]) E = K**-1* F * K

A questo punto posso usare la funzione OpenCV recoverPose:
Code:
points, R, t, mask = cv2.recoverPose(E, pts1, pts2)

R, t: matrice di rotazione e vettore traslazione di una camera rispetto all`altra
(ma non capisco perche` per calcolarle ha bisogno ancora delle coppie di punti pts1 e pts2)

Risultato:
Code:
>>> R array([[ 0.99302249, -0.11715838, 0.01342568], [ 0.11557984, 0.94435246, -0.30796062], [ 0.0234016 , 0.30736355, 0.95130437]])
Code:
>>> t array([[-0.99929059], [-0.03747715], [ 0.00371336]])


Con questi dati ora si possono ottenere i punti tridimensionali mediante triangolazione: io uso la funzione OpenCV triangulatePoints:
Code:
X = cv2.triangulatePoints( P1, P2, pts1.transpose(), pts2.transpose() ) X /= X[3]

Pn = matrice di proiezione della camera n
X = punti in coordinate (x,y,z,w).


L`ultima cosa che mi serve capire e` come ottenere la matrice 4x3 di proiezione P della camera; dovrebbe essere composta da:
Code:
K: matrice calibrazione 3x3 R: matrice rotazione 3x3 t: traslazione 3x1 P= K*[R|t]
Ultima Modifica 7 Anni 8 Mesi fa da doktorenko. Motivo: correzione

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #9006 da FranZeta

doktorenko ha scritto: Sto cercando di capire come ricavare i punti Pxyz partendo dai punti corrispondenti Puv e P'uv.

Questo è l'obiettivo dichiarato di tutta la procedura, ma è anche l'ultimo dei problemi, note le matrici fondamentale e essenziale come si fa è spiegato qui . Uno dei problemi veri è che se non si conosce almeno una misura sulla scena reale, sia questa la distanza fra i due scatti o le coordinate 3D di un punto, non ci sono santi nè madonne nè opencv che possano fare il calcolo. Il vettore spostamento fra i due scatti è noto solo a meno di un fattore di proporzionalità, vale a dire che si può conscere solo la retta della spostamento, per ricavare i numeri giusti pensavo di usare le misure della larghezza del lunar rover.

Per quanto riguarda le matrici rotazione quelle possibili sono due e non c'è modo a priori di scegliere la migliore, l'unica è fare delle verifiche. Cosa che pian pianino sto facendo. Altra cosa: per come sono sistemate le fotocamere la conica di cui si parlava sopra deve essere un'iperbole.

PS A me risulta E=K'^T*F*K, se K'=K: E=K^T*F*K.

FranZη
Ultima Modifica 7 Anni 8 Mesi fa da FranZeta.

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #9009 da doktorenko

FranZeta ha scritto: Questo è l'obiettivo dichiarato di tutta la procedura, ma è anche l'ultimo dei problemi, note le matrici fondamentale e essenziale come si fa è spiegato qui . Uno dei problemi veri è che se non si conosce almeno una misura sulla scena reale, sia questa la distanza fra i due scatti o le coordinate 3D di un punto, non ci sono santi nè madonne nè opencv che possano fare il calcolo.


Sarebbe, come dicono i tedeschi, zu schoen, um wahr zu sein.

Il vettore spostamento fra i due scatti è noto solo a meno di un fattore di proporzionalità, vale a dire che si può conscere solo la retta della spostamento, per ricavare i numeri giusti pensavo di usare le misure della larghezza del lunar rover.


La modifica nel mio messaggio precedente era proprio per questo motivo: prima avevo scritto "distanza", poi ho corretto con "vettore traslazione"; intendendo il vettore unitario.

Per ricavare il fattore di scala lambda , ho trovato questa equazione:
Code:
(sx2, sy2, 1) = K(R|lambda*T)(X,Y,Z)

sx,sy dovrebbero essere le coordinate sulla proiezione; X,Y,Z il corrispondente punto tridimensionale di cui si conoscono i valori.

PS A me risulta E=K'^T*F*K, se K'=K: E=K^T*F*K.

Si`, ho sbagliato a copiarla:

Correlazione tra matrice fondamentale e essenziale (9.12)

Pero` non riesco lo stesso a ricavarla correttamente; cosi` me la faccio calcolare da OpenCV dalle coppie di punti:
Code:
E=cv2.findEssentialMat(pts1,pts2,focale,(cx,cy))[0]

Questa e` l`immagine dei punti tridimensionali ricostruiti:



Potrebbe essere utile per ricavare con maggiore precisione l`altimetria nella zona ai piedi del fotografo, dove i punti sono piu` densi.

p.s.
Aggiungo il codice che ottiene il risultato apparentemente corretto dell` immagine sopra:

Calcolo matrice K (metto le misure in px):
Code:
l_px=4175. f_mm=61.1 l_mm=55.44 f_px=f_mm/l_mm*l_px K=np.matrix([ [ f_px, 0, l_px/2 ], [ 0.0, f_px, l_px/2 ], [ 0.0, 0.0, 1.0 ] ])

Calcolo e scomposizione matrice E in matrice R e t:
Code:
E=cv2.findEssentialMat(pts1,pts2,f,(px/2,px/2))[0] points, R, t, mask = cv2.recoverPose(E, pts1, pts2)

Valori R e t (quelli del messaggio precedente sono errati):
Code:
>>> R array([[ 0.99953627, -0.01286357, 0.02760033], [ 0.01063138, 0.99677412, 0.07955081], [-0.02853461, -0.07922049, 0.99644864]]) >>> t array([[-0.49655057], [ 0.00879161], [ 0.86796327]])

Triangolazione:
Code:
R1 = np.eye(3) R2 = R t1=np.zeros(3)[:,np.newaxis] t2=t P1=np.matmul(K,np.hstack((R1,t1))) P2=np.matmul(K,np.hstack((R2,t2))) X = cv2.triangulatePoints( P1[:3], P2[:3], pts1.transpose(), pts2.transpose() ) X /= X[3]
Ultima Modifica 7 Anni 8 Mesi fa da doktorenko. Motivo: aggiunta codice

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa #9011 da FranZeta
Anche se devo ancora controllare i calcoli e fare un'animazione gif delle due immagini per vedere se effettivamente la corrispondenza è buona, a questo punto anticipo quello che avevo trovato perchè i valori sono abbastanza diversi dai tuoi. Questa è la prima parte:



Prima ci sono le due matrici di calibrazione (il centro delle mie immagini ha coordinate (0,0) quindi non c'è nessuna traslazione e le matrici sono diagonali), con queste ricavo E, mentre l'ultima parte è la fattorizzazione SVD di E che serve per trovare le sue due componenti R e t, che poi calcolo qui:



Ogni volta che compare una matrice di rotazione verifico che sia effettivamente ortogonale (A*A^T=I), l'ho fatto per U,V e R, questi sono gli altri conti che compaiono sopra.

Il vettore t trovato non mi dà preoccupazioni perchè mi sembra coerente con la scena, diciamo che corrisponde per esempio ad uno spostamento in avanti di 40 cm, a sinistra di 10 e in alto di altri 10 fra i due scatti, la rotazione invece è quella che mi sembra più consona delle due possibili, l'ultima parte del calcolo è per trovare l'angolo in gradi e l'asse di rotazione associati. Come vedi ci sono differenze non marginali con i tuoi risultati, prima di pensare a ricostruire la scena 3D sarebbe meglio verificare il tutto, quando riesco faccio una gif delle due immagini sovrapposte dopo la rotazione, mi sembra il controllo migliore, però sulla parte precedente dei calcoli (conica ed epipoli) ho pochi dubbi, fossi in te verificherei se con i tuoi dati ottieni risultati simili, per esempio se ti risultano ancora gli epipoli fuori dall'immagine c'è qualcosa che non va.

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 8 Mesi fa - 7 Anni 8 Mesi fa #9012 da doktorenko

FranZeta ha scritto: Come vedi ci sono differenze non marginali con i tuoi risultati, prima di pensare a ricostruire la scena 3D sarebbe meglio verificare il tutto, quando riesco faccio una gif delle due immagini sovrapposte dopo la rotazione, mi sembra il controllo migliore, però sulla parte precedente dei calcoli (conica ed epipoli) ho pochi dubbi, fossi in te verificherei se con i tuoi dati ottieni risultati simili, per esempio se ti risultano ancora gli epipoli fuori dall'immagine c'è qualcosa che non va.


Faccio solo questa puntualizzazione: i risultati che ho pubblicato sopra non li considero propriamente "miei", perche` non ho fatto altro che usare il codice di esempio di OpenCV, senza modificarne i parametri; la mia rotazione- ottenuta cioe` con il sistema della collimazione della foto con il modello ricavato dai dati altimetrici- e` quella allegata all`ultima omografia.

Lo spostamento lo sto calcolando con la "forza bruta" applicata ad un modello LM con misure piu` accurate, da usare per la comparazione con lo scatto Apollo.
Ultima Modifica 7 Anni 8 Mesi fa da doktorenko.

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 7 Mesi fa #9261 da FranZeta
Dopo lunga sosta ho trovato un po' di tempo per controllare i risultati qui sopra, partiamo da quelli del mio commento #9011. I calcoli sono corretti (vabbè ci mancherebbe, li ha fatti il computer...però l'impostazione è umana), il risultato finale però, soprattutto la rotazione trovata, è incompatibile con le due immagini. Il problema è che questa impostazione, cioè geometria epipolare + matrici fondamentale ed essenziale, è molto sensibile alle condizioni iniziali, vale a dire ai dati che inseriamo noi e in particolare alle coordinate dei punti che andiamo ad identificare. Ora, nel commento #8994 avevo scelto 7 coppie di punti corrispondenti nelle due immagini, poi usando queste avevo ricavato la matrice fondamentale F che consente di trovare gli epipoli e la conica associata alle due foto. Per ogni punto Pi, tracciata la corrispondente linea epipolare, valeva la proprietà che questa passava con ottima approssimazione per il punto Pi', e con ciò pensavo che la verifica fosse sufficiente ad escludere grossi errori (si tenga presente ad esempio che cinque punti sono quanto basta per individuare una conica), approfondendo le cose però mi sono accorto che non è affatto così.

Quindi l'unico modo per affinare i risultati (e controllare che siano simili a quelli trovati da OpenCV, cosa che semplificherebbe molto tutto quanto) è rimasto quello di aumentare il numero di punti. Stavolta ne ho scelti 12, 7 sono quelli vecchi più altri 5, due dei quali appartenenti allo sfondo, cosa che non accadeva per nessuno dei primi 7 e che credo abbia un ruolo non secondario nella precisione del procedimento. Prima di approfondire però darei un momento un'occhiata alle due foto così come sono:



A sinistra la 15602 che ho preso come immagine fissa, a destra la 15601 che è quella mobile. Vediamo di fare un paio di considerazioni banali per noi ma ignote - a priori - agli algoritmi che stiamo usando: innanzitutto la seconda immagine (a dx) punta un po' più in basso rispetto alla prima, ricordiamoci sempre che per come impostiamo le cose l'orientamento della prima foto è anche quello degli assi di riferimento del quadro tridimensionale. Poi la seconda è chiaramente scattata più avanti, cioè più vicina alla scena. Altrettanto chiaramente si vede uno spostamento verso sinistra, anche se dev'essere di non più di qualche decina di centimetri, direi 30 cm al massimo, visto che la ruota posteriore del rover nella prima foto è praticamente parallela alla direzione della foto, mentre nella seconda è sì leggermente angolata ma di molto poco, tanto che si riesco solo a malapena a scorgere il mozzo. Questo ci porta anche a concludere che la parallasse per gli oggetti più lontani della scena deve essere in ogni caso molto contenuta, anche se lo sfondo si trovasse solo a qualche decina di metri e non km. Tra l'altro la possibilita di discernere lo sfondo dagli altri elementi è un'altra di quelle facoltà che abbiamo noi ma non gli algoritmi.

Veniamo ora alla geometria epipolare. Usando anche i nuovi 5 punti trovo questo risultato:



La conica è diventata un'ellisse, gli epipoli sono finiti fuori dall'immagine e quindi il risultato sembra molto simile a quello trovato dal computer. Non solo: usando la nuova matrice F e rifacendo i calcoli già tentati sopra, ottengo uno spostamento T fra le due immagini praticamente identico a openCV:
Code:
T=[-.500, .070, .863]
Qua c'è il nuovo file di geogebra utilizzato con le coordinate dei punti e tutto quanto. Sembrerebbe tutto a posto e invece per quanto riguarda la rotazione trovata siamo ancora parecchio lontani dai risultati del programma, e pure dalla realtà, ecco qua cosa salta fuori:



C'è una rotazione attorno all'asse z (l'asse verso cui punta l'obiettivo) decisamente eccessiva e non è dovuta ad errori di calcolo ma alla precisione intrinseca del procedimento. Per confronto questo è il risultato con la rotazione trovata da OpenCV:



Quest'ultima è molto simile all'immagine di Oleynik (e di Kamiokande), quindi forse tutto questo casino è servito se non altro per capire che accidenti di algoritmo usa: OpenCV! O comunque una sua variante.

Ora Oleynik attribuisce la rotazione che si vede nello sfondo a effetti di parallasse, io su questo punto ci andrei molto più cauto invece. La mia sensazione (sensazione matematica, cosa diversa da una dimostrazione) è che c'entrino invece le matrici con cui si fanno i calcoli che non permettono una precisione accettabile per i nostri scopi nell'individuare la rotazione.

A questo punto ho deciso di fare un'altra prova, cioè di ricavare la rotazione direttamente, alla "vecchia maniera", sfruttando però anche il lavoro fin qui fatto. Quindi nel foglio già impostato di geogebra ho segnato il punto P0=(0,0), cioè la croce centrale, ho tracciato la corrispondente epilinea e infine ho individuato su questa il punto P0' corrispondente (secondo me) a quello della prima foto, il tutto si vede nello screenshot di geogebra postato sopra. Poi ho ricostruito la rotazione a partire dallo scostamento fra questi due punti, per trovare la rotazione attorno all'asse z ho usato la traslazione dello sfondo sull'estrema destra delle foto. Risultato:



...e la rotazione è sparita! Come ultimo confronto ecco cosa saltava fuori usando il vecchio metodo dei 4 punti:



Anche qui si può notare una forte somiglianza fra le ultime due immagini. In conclusione la mia migliore stima per la rotazione fra le due immagini è quella descritta sopra, per la cronaca la rotazione è questa:
Code:
[0,999634149 0,020790914 -0,017300485] R=[-0,022218207 0,995971755 -0,086871252] [0,015424662 0,087223856 0,996069314] ax=0.0873 ay=0.0154 az=-0.0222
mentre il vettore spostamento è quello già indicato sopra, cioè lo stesso fornito da OpenCV. Le matrici fondamentale ed essenziale da cui saltava fuori il vettore (ma non la rotazione corretta!) sono queste:
Code:
[.1565203692e-3 .1002680620e-1 .2953812161e-2] F=[-.1035880582e-1 .2305792649e-2 -.2592214824] [.4094473436e-1 .2480372470 1.] [.3041773160 19.48581526 .1302149517] E=[-20.13101405 4.481013067 -11.42744053] [1.804995144 10.93439812 1.]

Per completezza aggiungo qui due script di matlab che ho usato per velocizzare i procedimenti di creazione delle coppie di immagini, il primo funziona con il metodo dei 4 punti corrispondenti sullo sfondo:
Code:
%projHper4pt.m %trasformazione proiettiva della foto img2 per sovrapporla %a img1 mediante corrispondenza di 4 punti sullo sfondo. Le coordinate dei %punti sono in pixel così come compaiono sull'immagine (es. il centro %dell'immagine ha coordinate (sizex/2,sizey/2)). %Trascrive le immagini finali nella cratella work fixed = imread('D:\Immagini\Temp\img1.jpg'); moving = imread('D:\Immagini\Temp\img2.jpg'); fixedPoints=input('fixedPoints=[.. ..;.. ..;.. ..;.. ..]'); movingPoints=input('movingPoints=[.. ..;.. ..;.. ..;.. ..]'); tform = fitgeotrans(movingPoints, fixedPoints, 'projective'); registered = imwarp(moving, tform,'FillValues', 255); figure, imshow(registered); Rfixed = imref2d(size(fixed)); registered1 = imwarp(moving,tform,'FillValues', 255,'OutputView',Rfixed); figure, imshowpair(fixed,registered1,'blend'); blend=imfuse(fixed,registered1,'blend'); imwrite(blend,'imgblend.jpg'); imwrite(fixed,'img1.jpg'); imwrite(registered1,'img2.jpg');
e il secondo che chiede l'inserimento di un'omografia H e poi permette di centrare le due immagini traslando la seconda (il metodo dei 4 punti centra automaticamente la sovrapposizione, questo no):
Code:
%projH.m %carica le due immagini img1, img2 dalla cartella D:\Immagini\Temp, applica %l'omografia H a img2, permette di traslare la seconda immagine per %sovrapporla alla prima e salva le immagini finali nella cartella work fixed = imread('D:\Immagini\Temp\img1.jpg'); moving = imread('D:\Immagini\Temp\img2.jpg'); SIZE=size(moving); a=SIZE(2)/2;b=SIZE(1)/2; T1=[[1 0 -a];[0 1 -b];[0 0 1]]; T2=[[1 0 a];[0 1 b];[0 0 1]]; H=input('omografia H=?'); H=H' H1=H; H1(:,1)=1/a*H1(:,1);H1(:,2)=1/b*H(:,2); H2=[[a 0 0];[0 b 0];[0 0 1]]; H3=T2*H2*H1*T1; tform=projective2d(H3'); registered = imwarp(moving, tform,'FillValues', 255); figure, imshow(registered); Rfixed = imref2d(size(fixed)); registered1 = imwarp(moving,tform,'FillValues', 255,'OutputView',Rfixed); figure, imshowpair(fixed,registered1,'blend'); check=input('traslare la seconda immagine? 1=SI 0=NO....'); while check > 0 tx=input('tx=?'); ty=input('ty=?'); T2=[[1 0 a+tx];[0 1 b+ty];[0 0 1]]; H3=T2*H2*H1*T1; tform=projective2d(H3'); registered1 = imwarp(moving,tform,'FillValues', 255,'OutputView',Rfixed); figure, imshowpair(fixed,registered1,'blend'); check=input('traslare ancora la seconda immagine? 1=SI 0=NO....'); end A=imfuse(fixed,registered1,'blend'); imwrite(A,'imgblend.jpg'); imwrite(fixed,'img1.jpg'); imwrite(registered1,'img2.jpg');

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 7 Mesi fa #9280 da doktorenko
MI fa piacere rileggerti; pero` mi ci vuole un po` per riprendere l`argomento perche` in questo periodo l`ho trascurato. Comunque, da quello che ho capito, tu confermi il risultato dell`algoritmo di OpenCV? Io direi che e` comprovato anche dalla ricostruzione tridimensionale mediante triangolazione dei punti, a prima vista sufficientemente corretta.

Ricostruzione che non ottengo (in nessun modo, neanche approssimativo) ricavando gli angoli della camere con la collimazione di punti lontani (crateri sullo sfondo).
Questo mi sembra un punto interessante da approfondire.

Questo ci porta anche a concludere che la parallasse per gli oggetti più lontani della scena deve essere in ogni caso molto contenuta, anche se lo sfondo si trovasse solo a qualche decina di metri e non km. Tra l'altro la possibilita di discernere lo sfondo dagli altri elementi è un'altra di quelle facoltà che abbiamo noi ma non gli algoritmi.


Come ho detto prima, dovrei riprendere i miei esperimenti: pero` mi ricordo che la parallasse era abbastanza evidente, anche per spostamenti di qualche decina di centimetri, fino a 4/5km.

Si prega Accesso a partecipare alla conversazione.

Di più
7 Anni 7 Mesi fa #9286 da FranZeta

doktorenko ha scritto: Comunque, da quello che ho capito, tu confermi il risultato dell`algoritmo di OpenCV? Io direi che e` comprovato anche dalla ricostruzione tridimensionale mediante triangolazione dei punti, a prima vista sufficientemente corretta.

Lo spostamento è praticamente identico, se escludiamo improbabili coincidenze direi che è confermato. La conica e gli epipoli sono solo qualitativamente simili, si assomigliano soltanto. Questo comporta differenze sostanziali nelle rotazioni trovate, sicuramente quella che trovo io è più sbagliata, ma la differenza fra le due rotazioni e fra queste e la rotazione effettiva sembra sempre essere attorno all'asse z, la direzione della fotocamera. Avevo pensato di provare a correggere manualmente queste rotazioni in eccesso ma non avrebbe molto senso.

Per quanto riguarda la ricostruzione 3D francamente non si riesce a capire molto, secondo me sarebbe interessante capire dove viene posizionata la parte dello sfondo piuttosto che i punti vicini.

Ricostruzione che non ottengo (in nessun modo, neanche approssimativo) ricavando gli angoli della camere con la collimazione di punti lontani (crateri sullo sfondo).
Questo mi sembra un punto interessante da approfondire.

Qui non ti seguo molto. Da quello che ho capito l'algoritmo trova una marea di punti corrispondenti, molti di questi saranno punti dello sfondo. In realtà non è una pecca usare i punti lontani, anzi, più sono lontani maggiore è la precisione nel determinare la rotazione, questo indipendentemente dal fatto che lo sfondo sia vero o finto, di sicuro i punti dello sfondo sono i più lontani che si vedono nell'immagine.

Quando non avevo usato punti dello sfondo nel primo tentativo la rotazione risultante era ancora più sballata, questo non perchè usavo meno punti: alla fine invece che risolvere un sistema sovradeterminato mi è bastato risolvere un sistema da 7 punti sostituendo a due di quelli vecchi i nuovi punti P8 e P11 dello sfondo, così facendo sono venuti a coincidere perfettamente (sempre nei limiti di una precisione accettabile) tutti i 12 punti scelti, in pratica mi sono risparmiato un'impostazione coi minimi quadrati.

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 11 Mesi fa #12101 da FranZeta
@doktorenko
Rispondo qui al tuo post per non appesantire la discussione sul film.

Il mio appunto precedente era al fatto che la corrispondenza fra due immagini stereoscopiche non è mai un'omografia, cosa che invece si evincerebbe da quanto scrivi qui:

Con una omografia e` possibile ottenere, da due foto prese da posizioni leggermente diverse, una coppia di immagini stereoscopiche "raddrizzando" una di esse.


e qui:

premessa teorica:

a) la proiezione dell'immagine sul piano del sensore introduce una deformazione (di tipo appunto proiettivo)
b) due scatti (A e B) presi dallo stesso punto, ma con diversa angolazione, proiettano diversamente (sul piano del sensore) la stessa porzione sovrapponibile dell'inquadratura (Ab, Ba)
c) posso trasformare Ab in Ba (e viceversa) a tavolino, applicando una matrice di deformazione 3x3 ad Ab o a Ba
d) Ab e Ba sono quindi omografie


In particolare il fatto che esista una "porzione sovrapponibile" delle due immagini è la conseguenza del fatto che quelle due porzioni siano su uno stesso piano, eventualmente il piano all'infinito per quanto riguarda i punti lontani. Quindi il punto b) non è una premessa ma una conseguenza del punto d). Questo ha una certa rilevanza in tutto il discorso anche perchè, è bene ricordarsi, l'assenza di parallasse non implica che lo sfondo dell'immagine sia reale e lontano, vale solo il viceversa. Venendo a Oleynik:

Metodo Oleynik:

1) calcolo di milioni di H con la forza bruta
2) si sceglie la matrice H che fa coincidere il massimo numero di punti S1h e S2
3) il risultato finale non è soddisfacente (non ci sono abbastanza punti in sovrapposizione)
4) S1 e S2 non sono quindi omografie

conclusione:

5) S subisce la parallasse (o anche altre deformazioni)

possibili obiezioni:

1) O. ha sbagliato a calcolare H (non dettaglia l'operazione)
2) le deformazioni sono introdotte dalla lente



Bisogna subito dire che in effetti non dettaglia l'algoritmo, ma spiega il metodo: la sottrazione delle immagini. Cioè sottrae i valori RGB della prima immagine e della seconda, omografia per omografia, e sceglie quella che minimizza la sottrazione, ossia quella col maggior numero di "punti neri". Al di là del metodo effettivo con cui risolva il problema (quello che non descrive), che dal punto di vista geometrico è come trovare il punto più basso di una ipersuperficie di dimensione 8 (no, dico: 8!), la quale a priori potrebbe non essere nemmeno continua, figuriamoci differenziabile...a parte questo dicevo, il suo metodo dal punto di vista teorico è sbagliato, perchè non c'è nulla che ci assicuri che questo punto di minimo corrisponda alla proiettività che cerchiamo, potrebbero anche essercene più di uno, e potrebbe anche darsi che a nessuno di questi corrisponda l'omografia cercata.

Per esempio se le due immagini non sono perfettamente a fuoco potrebbe esserci un'omografia che lega i punti all'infinito delle due foto ma questa difficilmente realizzerebbe il minimo di Oleynik. Stesso discorso si potrebbe fare se gli scatti non sono proprio in sequenza ravvicinata, per esempio se varia un poco l'illuminazione della scena. Francamente non capisco perchè non abbia usato il metodo, questo sì derivato direttamente dalla teoria degli spazi proiettivi, dei 4 punti sullo sfondo. Che tra l'altro può essere anche esteso a un numero arbitrario di punti, se si vuole aumentare la precisione, trovando poi l'omografia che risolve il sistema sovradeterminato col metodo dei minimi quadrati, in modo da avere a che fare con un sistema di qualche decina di incognite, non il numero stratosferico che usa Oleynik.

PS Per una ipersuperficie di dimensione 8, usando un reticolo di 100 punti per lato (cioè ogni variabile può assumere un insieme discreto di 100 valori), sono 1016 le combinazioni di valori da esplorare per trovare il minimo, sempre ammesso che esista...

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 8 Mesi fa #17053 da FranZeta
Uso questo spazio per rispondere al post di HumanClone, dato che siamo stati sfrattati dall'altro thread. Se doktorenko ha qualcosa in contrario traslocheremo nuovamente, però il discorso si riaggancia al lavoro fatto qui, inoltre fra poco chiamerò anche in causa lo stesso doktorenko. Veniamo a noi:

HumanClone ha scritto: Sono d'accordo sul fatto che gli anaglifi non permettono di misurare la pendenza dei dislivelli, ma quantomeno permettono di apprezzarne la presenza e smentire chi parla di campo da tennis. Cioè sono probanti in senso qualitativo ma non quantitativo.


Forse aiuterà capire come ho ottenuto le immagini e cosa intendevo dimostrare in questo modo. Innanzitutto riporto per comodità il tuo anaglifo (1) e il mio (2) di seguito:

(1)


(2)


Per ottenere la (2) innanzitutto ho dovuto modificare la luminosità delle due foto Apollo di partenza (A14-9486 e -9487) usando un particolare plug-in, perchè intervenendo solo sul contrasto non ottenevo un effetto simile a quello della foto NASA (1). Già questo accorgimento fa parecchio, perchè usando le foto originali senza correzioni il risultato sarebbe questo:

(3)


...e già buona parte delle irregolarità del terreno sembrano svanite. Con ciò non voglio per forza dire che l'immagine (3) è una ricostruzione della scena 3D più fedele della (1) o della (2), ma di sicuro è più fedele alle reali immagini Apollo che abbiamo a disposizione. Comunque, a partire dalla coppia di foto così elaborate, per costruire l'anaglifo ho fissato la posizione della bandiera e dell'astronauta, in modo che coincidessero nelle due immagini da sovrapporre, poi ho deciso del tutto arbitrariamente di aggiungere un tot di parallasse perfettamente orizzontale a due pietre in primo piano, infine con qualche aggiustamento di fino ho eliminato la parallasse dallo sfondo.

Il risultato quindi mi dà una profondità 3D arbitraria, perchè decisa a tavolino, e in più non mi dà nessuna informazione sulla zona dell'ombra del LEM, dato che è una zona a parallasse zero. Incidentalmente è anche la zona che andrebbe davvero esaminata, dato che l'ombra anomala nella scena è proprio quella del LEM, quelle delle pietre vicine, dossi o non dossi, sono tutte coerenti tra loro. Se proprio direi che questa operazione conferma, se davvero ce ne fosse stato bisogno, che davanti al fotografo non si presenta nessuna "rampa" in grado di modificare sostanzialmente tutte le ombre vicine.

Con l' ultima immagine postata invece ho voluto dimostrare che, sempre agendo arbitrariamente sulla quantità di parallasse, la si può praticamente annullare anche per gli oggetti vicini. Se avessi perso un po' di tempo avrei anche potuto far scomparire quasi del tutto la parallasse dello sfondo. Questo sta a significare che le due immagini sono effettivamente riprese a pochi cm di distanza una dall'altra e che l'anaglifo NASA è uno fra i tanti possibili. Non restituisce un immagine attendibile della reale conformazione del terreno, per i motivi appena esposti, inoltre aggiungo che credo sia al limite della parallasse ottenibile "artificialmente" prima che inizi a manifestarsi una evidente parallasse nello sfondo. Per la verità è un po' oltre questo limite, dato che la parallasse in effetti si vede, come ripeto è la striscia rossa sulle colline di destra.

Ricapitolando la NASA, nel generare l'immagine stereoscopica ha

1) alterato la luminosità delle foto originali, creando così l'illusione di maggior asperità del terreno;
2) impostato artificialmente la parallasse al massimo livello possibile, e anche qualcosa di più del massimo;
3) ha infine ulteriormente traslato le due immagini, giocando su un effetto della visione stereoscopica, in modo da "far uscire dallo schermo" le pietre in primo piano, togliendo così ulteriore profondità e dando l'idea di un terreno ancora più sconnesso, ricordo infatti che l'originale foto NASA è questa .

Diciamo insomma che si sono dati un bel da fare per dare l'illusione di un terreno particolarmente accidentato, quando le foto originali suggerirebbero il contrario.

Quindi farai un'analisi fotogrammetrica della scena?

"A mano", come avevo provato a fare in questo thread, no di certo, anche perchè la distanza tra le due foto è talmente piccola che non porterebbe a nulla di significativo. L'errore sarebbe troppo grande rispetto ai piccoli dislivelli che vorremmo misurare, inoltre sarebbe del tutto inutile per la zona dell'ombra del LEM che, ripeto, è la causa dei problemi con le ombre. Però - e qui entra in causa doktorenko - se guardi qualche commento più sopra vedrai che ci sarebbe un programmino già bello pronto che fa questo tipo di analisi. Io non riesco a farlo girare perchè mi mancano delle librerie, inoltre con Python sono una completa frana e non mi ci metto neanche lì, ma se doktorenko volesse fare la prova potremmo avere qualche dato in più sulla reale conformazione del terreno in primo piano. Anche se, ripeto, le immagini sono davvero molto vicine, dubito che ne esca fuori qualcosa di utile.

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 8 Mesi fa #17062 da doktorenko

FranZeta ha scritto: Però - e qui entra in causa doktorenko - se guardi qualche commento più sopra vedrai che ci sarebbe un programmino già bello pronto che fa questo tipo di analisi. Io non riesco a farlo girare perchè mi mancano delle librerie, inoltre con Python sono una completa frana e non mi ci metto neanche lì, ma se doktorenko volesse fare la prova potremmo avere qualche dato in più sulla reale conformazione del terreno in primo piano. Anche se, ripeto, le immagini sono davvero molto vicine, dubito che ne esca fuori qualcosa di utile.


Ti riferisci a quest'immagine? (purtroppo sono sparite: per rivederle bisogna cambiare l'indirizzo da *.postimg.org a *.postmg.cc)



Però mi devi dare il tempo di ripassare tutta la procedura. Come coppia di immagini userei due fotografie scattate da un punto più vicino al modulo lunare, se quello che interessa ricostruire sono gli eventuali dossi che nasconderebbero/deformerebbero l'ombra dello stesso.

p.s.: OpenCv è disponibile anche per C++ :wink:

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 7 Mesi fa #17071 da FranZeta

doktorenko ha scritto: Ti riferisci a quest'immagine?

No più che altro mi riferivo a questo codice che ricava la matrice fondamentale della coppia di immagini, poi da quella si può trovare lo spostamento fra i due scatti ed eventualmente la reale posizione di alcuni punti vicini. L'immagine che generava dovrebbe essere questa:



ma, appunto, più che l'immagine stessa sarebbe utile la matrice.

PS Anche C++ non lo uso dai tempi dell'università, e non mi manca affatto!

FranZη

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 7 Mesi fa - 6 Anni 7 Mesi fa #17075 da doktorenko
Se non ho invertito la destra e la sinistra, la matrice F risultante dagli scatti A1-9486 e 9487 dovrebbe essere questa:
Code:
array([[ 3.00659770e-08, -2.61855429e-06, 1.14838140e-02], [ 2.61810120e-06, 2.75747709e-08, -1.30691859e-02], [-1.21837463e-02, 1.33374620e-02, 1.00000000e+00]])

Il programma ha trovato circa 5000 punti in comune utili:
Code:
>>> len(pts1) 5159

Scomposizione di F in R e t:
Code:
>>> px=3900 >>> f_mm=61.1 >>> l_mm=55.44 >>> f_px=f_mm/l_mm*px >>> E=cv2.findEssentialMat(pts1,pts2,f_px,(px/2,px/2))[0] >>> E array([[ 7.95300899e-03, -7.06852016e-01, -1.51034058e-02], [ 7.06889467e-01, 7.80103436e-03, 1.24125113e-02], [-9.70207321e-03, 8.19079896e-03, 8.55695945e-06]]) >>> points, R, t, mask = cv2.recoverPose(E, pts1, pts2) >>> R array([[ 0.99951476, 0.01062017, 0.0292823 ], [-0.01164179, 0.99932154, 0.03494172], [-0.02889134, -0.03526566, 0.99896027]]) >>> t array([[0.01173584], [0.01359077], [0.99983877]])

t è un versore? come si fa a ricavare lo spostamento effettivo?

p.s.:

ho provato a triangolare i punti con le matrici calcolate, ma non sono riuscito ad ottenere un'immagine apparentemente corretta.
Ultima Modifica 6 Anni 7 Mesi fa da doktorenko. Motivo: aggiunto scomposizione matrice - p.s.

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 7 Mesi fa - 6 Anni 7 Mesi fa #17082 da doktorenko
Forse sono riuscito a ottenere qualcosa utilizzando due immagini con una risoluzione più alta, scaricate da questo album .

Allego il codice perché è leggermente modificato rispetto a quello del tutorial, che si riferisce ad una versione precedente.
Code:
import numpy as np import cv2 from matplotlib import pyplot as plt def drawlines(img1,img2,lines,pts1,pts2): ''' img1 - image on which we draw the epilines for the points in img2 lines - corresponding epilines ''' r,c = img1.shape img1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR) img2 = cv2.cvtColor(img2,cv2.COLOR_GRAY2BGR) for r,pt1,pt2 in zip(lines,pts1,pts2): color = tuple(np.random.randint(0,255,3).tolist()) x0,y0 = map(int, [0, -r[2]/r[1] ]) x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ]) img1 = cv2.line(img1, (x0,y0), (x1,y1), color,1) img1 = cv2.circle(img1,tuple(pt1),5,color,-1) img2 = cv2.circle(img2,tuple(pt2),5,color,-1) return img1,img2 img1 = cv2.imread('as14-68-9487.jpg',0) #queryimage # left image img2 = cv2.imread('as14-68-9486.jpg',0) #trainimage # right image sift = cv2.xfeatures2d.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) # FLANN parameters FLANN_INDEX_KDTREE = 1 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params,search_params) matches = flann.knnMatch(des1,des2,k=2) good = [] pts1 = [] pts2 = [] # ratio test as per Lowe's paper for i,(m,n) in enumerate(matches): if m.distance < 0.8*n.distance: good.append(m) pts2.append(kp2[m.trainIdx].pt) pts1.append(kp1[m.queryIdx].pt) pts1 = np.int32(pts1) pts2 = np.int32(pts2) F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS) # We select only inlier points pts1 = pts1[mask.ravel()==1] pts2 = pts2[mask.ravel()==1] lines1 = cv2.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F) lines1 = lines1.reshape(-1,3) img5,img6 = drawlines(img1,img2,lines1,pts1,pts2) # Find epilines corresponding to points in left image (first image) and # drawing its lines on right image lines2 = cv2.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F) lines2 = lines2.reshape(-1,3) img3,img4 = drawlines(img2,img1,lines2,pts2,pts1) plt.subplot(121),plt.imshow(img5) plt.subplot(122),plt.imshow(img3) plt.show() np.save("/tmp/punti1.npy",pts1) np.save("/tmp/punti2.npy",pts2)
Code:
>>> F array([[ 1.98602311e-08, 2.29862063e-07, -1.02489430e-03], [-1.61345636e-07, -2.61852456e-09, -1.46165956e-03], [ 7.70671415e-04, 1.15212704e-03, 1.00000000e+00]]) >>> R array([[ 0.98192603, 0.00442368, 0.18921337], [ 0.00119167, 0.9995625 , -0.02955327], [-0.18926132, 0.02924461, 0.98149116]]) >>> t array([[-0.67234328], [ 0.24372482], [ 0.69896547]]) >>> E array([[ 0.03320617, 0.48898699, -0.18375618], [-0.39533195, -0.0160898 , -0.56013648], [ 0.16979116, 0.47597287, 0.01855876]])
Ultima Modifica 6 Anni 7 Mesi fa da doktorenko.

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 7 Mesi fa #17091 da HumanClone
@FranZeta

per costruire l'anaglifo ho fissato la posizione della bandiera e dell'astronauta, in modo che coincidessero nelle due immagini da sovrapporre

Non mi torna. Da quello che avevi detto, avevo capito che a sovrapporsi dovesse essere solo la parte della scena a parallasse nulla, cioè lo sfondo. Bandiera e astronauta un po’ di parallasse ce l’hanno.

Si prega Accesso a partecipare alla conversazione.

Di più
6 Anni 7 Mesi fa #17109 da FranZeta
Grazie "dok" per la celerità, direi di tenere buona la rotazione e traslazione del tuo secondo commento.

HumanClone ha scritto: Non mi torna. Da quello che avevi detto, avevo capito che a sovrapporsi dovesse essere solo la parte della scena a parallasse nulla, cioè lo sfondo. Bandiera e astronauta un po’ di parallasse ce l’hanno.

In teoria si userebbe lo sfondo, ma dato che non ci sono riferimenti precisi e dato che non c'è assolutamente nessuna parallasse alla distanza della bandiera e dell'astronauta si può fare così. Per la precisione ho usato l'angolo del riquadro stellato e dello scarpone, puoi vedere da te che sono a parallasse zero anche nella tua immagine. Vediamo se riusciamo a misuarare la distanza fra i due scatti con i dati di doktorenko, ma sarà roba di qualche centimetro.

FranZη

Si prega Accesso a partecipare alla conversazione.

Tempo creazione pagina: 0.430 secondi
Powered by Forum Kunena