Korrekturalgorithmus für die Fassverzerrung zur Korrektur des FishEye-Objektivs - Implementierung mit Java fehlgeschlagen
Ich habe eine große Menge Fotos mit einem Fischaugenobjektiv aufgenommen. Da ich einige Bildbearbeitungen (z. B. Kantenerkennung) an den Fotos vornehmen möchte, möchte ich die Laufverzerrung entfernen, die sich stark auf meine Ergebnisse auswirkt.
Nach einigen Recherchen und vielen gelesenen Artikeln habe ich dies gefundenSeite: Sie beschreiben einen Algorithmus (und einige Formeln), um dieses Problem zu lösen.
M = a * rcorr ^ 3 + b * rcorr ^ 2 + c * rcorr + d
rsrc = (a * rcorr ^ 3 + b * rcorr ^ 2 + c * rcorr + d) * rcorr
rsrc = Abstand eines Pixels von der Mitte des Quellbilds
rcorr = Abstand eines Pixels von der Mitte im korrigierten Bild
a, b, c = Verzerrung des Bildes d = lineare Skalierung des Bildes
Ich habe diese Formeln verwendet und versucht, dies in einer Java-Anwendung zu implementieren. Leider funktioniert es nicht und ich habe es nicht geschafft. "Korrigiertes" Bild ähnelt nicht dem Originalfoto und zeigt stattdessen einige mysteriöse Kreise in der Mitte. Schau hier:
http://imageshack.us/f/844/barreldistortioncorrect.jpg/ (Früher war dies ein Foto einer weißen Kuh vor einer blauen Wand.)
Hier ist mein Code:
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;
}
Meine Fragen sind:
1) Ist diese Formel korrekt?
2) Habe ich einen Fehler gemacht, als ich diese Formel in eine Software verwandelt habe?
3) Es gibt andere Algorithmen (z.Wie simuliert man den Effekt eines Fischaugenobjektivs mit openCV? oder wiki / Distortion_ (Optik)), sind sie besser?
Danke für Ihre Hilfe!