Algoritmo de correção de distorção de barril para corrigir lente FishEye - falha ao implementar com Java
Eu tenho um grande volume de fotografias tiradas com uma lente olho de peixe. Como eu quero fazer algum processamento de imagem (por exemplo, detecção de borda) nas fotos, eu quero remover a distorção de barril que afeta meus resultados fortemente.
Depois de algumas pesquisas e muitos artigos lidos eu encontrei estepágina: Eles descrevem um algoritmo (e algumas fórmulas) para resolver este problema.
M = a * rcorr ^ 3 + b * rcorr ^ 2 + c * rcorr + d
rsrc = (a * rcorr ^ 3 + b * rcorr ^ 2 + c * rcorr + d) * rcorr
rsrc = distância de um pixel do centro da imagem de origem
rcorr = distância de um pixel do centro na imagem corrigida
a, b, c = distorção da imagem d = escala linear da imagem
Eu usei essas fórmulas e tentei implementar isso em um aplicativo Java. Infelizmente não funciona e eu não consegui fazê-lo funcionar. A imagem "Corrigida" não se parece com a fotografia original e, em vez disso, mostra alguns círculos misteriosos no meio. Olhe aqui:
http://imageshack.us/f/844/barreldistortioncorrect.jpg/ (isso costumava ser uma fotografia de uma vaca branca na frente de uma parede azul)
Aqui está o meu código:
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;
}
Minhas perguntas são:
1) Esta fórmula está correta?
2) Eu cometi um erro ao transformar essa fórmula em um software?
3) Existem outros algoritmos lá fora (por ex.Como simular o efeito de lente olho de peixe por openCV? ou wiki / Distortion_ (óptica)), eles são melhores?
Obrigado pela ajuda!