Ho una grande quantità di fotografie scattate con un obiettivo fisheye. Poiché desidero eseguire alcune operazioni di elaborazione delle immagini (ad es. Rilevamento dei bordi) sulle foto, desidero rimuovere la distorsione a barilotto che influisce pesantemente sui miei risultati.Algoritmo di correzione della distorsione a barilotto per correggere l'obiettivo FishEye - impossibile implementare con Java
Dopo alcune ricerche e molti articoli letti ho trovato questo page: descrivono un algoritmo (e alcune formule) per risolvere questo problema.
M = a * Rcorr^3 + b * Rcorr^2 + c * Rcorr + d
rsrc = (a * Rcorr^3 + b * Rcorr^2 + c * Rcorr + d) * Rcorrrsrc = distanza di un pixel dal centro dell'immagine sorgente
Rcorr = distanza di un pixel dal centro dell'immagine corretta
a, b, c = distorsione dell'immagine d = scala lineare dell'immagine
Ho usato questi formule e ha cercato di implementarlo in un'applicazione Java. Sfortunatamente non funziona e non sono riuscito a farlo funzionare. L'immagine "corretta" non assomiglia alla foto originale e mostra invece alcuni cerchi misteriosi nel mezzo. Guardate qui:
http://imageshack.us/f/844/barreldistortioncorrect.jpg/ (questo era una fotografia di una mucca bianca di fronte a una parete blu)
Ecco il mio codice:
protected int[] correction(int[] pixels) {
//
int[] pixelsCopy = pixels.clone();
// parameters for correction
double paramA = 0.0; // affects only the outermost pixels of the image
double paramB = -0.02; // most cases only require b optimization
double paramC = 0.0; // most uniform correction
double paramD = 1.0 - paramA - paramB - paramC; // describes the linear scaling of the image
//
for(int x = 0; x < dstView.getImgWidth(); x++) {
for(int y = 0; y < dstView.getImgHeight(); y++) {
int dstX = x;
int dstY = y;
// center of dst image
double centerX = (dstView.getImgWidth() - 1)/2.0;
double centerY = (dstView.getImgHeight() - 1)/2.0;
// difference between center and point
double diffX = centerX - dstX;
double diffY = centerY - dstY;
// distance or radius of dst image
double dstR = Math.sqrt(diffX * diffX + diffY * diffY);
// distance or radius of src image (with formula)
double srcR = (paramA * dstR * dstR * dstR + paramB * dstR * dstR + paramC * dstR + paramD) * dstR;
// comparing old and new distance to get factor
double factor = Math.abs(dstR/srcR);
// coordinates in source image
double srcXd = centerX + (diffX * factor);
double srcYd = centerY + (diffX * factor);
// no interpolation yet (just nearest point)
int srcX = (int)srcXd;
int srcY = (int)srcYd;
if(srcX >= 0 && srcY >= 0 && srcX < dstView.getImgWidth() && srcY < dstView.getImgHeight()) {
int dstPos = dstY * dstView.getImgWidth() + dstX;
pixels[dstPos] = pixelsCopy[srcY * dstView.getImgWidth() + srcX];
}
}
}
return pixels;
}
Le mie domande sono:
1) Questa formula è corretta?
2) Ho fatto un errore trasformando quella formula in un software?
3) Ci sono altri algoritmi là fuori (ad esempio How to simulate fisheye lens effect by openCV? o wiki/Distortion_ (ottica)), sono meglio?
Grazie per il vostro aiuto!
La griglia quadrata di pixel vicino al bordo dice molto su quale sia il problema probabile. Che il tuo algoritmo funzioni o meno per qualsiasi foto, non ne ho idea. Una probabile ragione per cui non funziona è che potresti essere in grado di sovrascrivere la distorsione. – AJMansfield
Come ho detto di seguito, ho provato a impostare b su un valore infinitamente piccolo. Dà un risultato diverso (nessuna correzione sferica più) ma non visualizza ancora la stessa immagine. Vedi qui: http://imageshack.us/f/191/barreldistortioncorrect.jpg/ – Lucas
È possibile che un valore b infinitamente piccolo si annulli eccessivamente nella direzione _other_? – AJMansfield