影像镜头畸变校正

Posted

技术标签:

【中文标题】影像镜头畸变校正【英文标题】:Image lens distortion correction 【发布时间】:2015-08-07 13:31:39 【问题描述】:

我正在使用带有鱼眼镜头的 Aptina 5Mp 传感器来捕捉图像。

我正在使用以下算法来校正镜头失真。

http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/

这没有正确校正图像。

任何帮助将不胜感激。

//code----
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace cv;
using namespace std;


// globals
Mat src, dst;
Mat map_x, map_y;
#define REMAP_WINDOW "Remap Circle"

void make_circle_map(float , float , float , float );

int main(int argc, char** argv) 
        // load image
        src = imread(argv[1], 1);
        float qvDepth = atof(argv[2]);
    float fixStrength = atof(argv[3]);
    float fixZoom = atof(argv[4]);
    float lensRadius = atof(argv[5]);
        // create destination and the maps
        dst.create(src.size(), src.type());
        map_x.create(src.size(), CV_32FC1);
        map_y.create(src.size(), CV_32FC1);

        // create window
       // namedWindow(REMAP_WINDOW, CV_WINDOW_AUTOSIZE);

        make_circle_map(qvDepth, fixStrength, fixZoom, lensRadius);
        remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0));
        //imshow(REMAP_WINDOW, dst);
        imwrite("got1.jpg",dst);
       // while(27 != waitKey()) 
                // just wait
      //  
      //  cvDestroyWindow(REMAP_WINDOW);
        return 0;


void make_circle_map(float qvDepth, float fixStrength, float fixZoom, float lensRadius ) 

//ApplyLensCorrection(double fixStrength, double fixZoom, double lensRadius, long long edgeHandling, long long superSamplingAmount

cout<<"qvDepth :"<<qvDepth<<" fixStrength :"<<fixStrength<<" fixZoom :"<<fixZoom<<" lensRadius :"<<lensRadius<<endl;
//float qvDepth = 32;//24;
//float fixStrength = 4.5; // has to utilized further
//float fixZoom = 0.5;
//float lensRadius =2;

//Calculate the center of the image
    //double midX = 0;
    //double midY = 0;
long tWidth = 1944;
long tHeight = 2580;

// the center 
        double midX = (double)src.cols/2;
        double midY = (double)src.rows/2;

//Rotation values
    double theta = 0;
    double sRadius = 0;
    double sRadius2 = 0;
    double sDistance = 0;
    double radius = 0;


    double j = 0;
    double k = 0;
//X and Y values, remapped around a center point of (0, 0)
    double nX = 0;
    double nY = 0;
    double QuickVal =0;
    float ssX;
    float ssY;

//Source X and Y values, which may or may not be used as part of a bilinear interpolation function
    double srcX = 0;
    double srcY = 0;

    sRadius = sqrt(tWidth * tWidth + tHeight * tHeight) / 2;
cout<<"sRadius :"<<sRadius<<endl;

    double refDistance = 0;//modified 0 to 2
    if (fixStrength == 0)
    
        fixStrength = 0.00000001;
    
    refDistance = sRadius * 2 / fixStrength;

    sRadius = sRadius * (lensRadius / 100);
    sRadius2 = sRadius * sRadius;
cout<<"refDistance :"<<refDistance<<" sRadius :"<<sRadius<<" sRadius2 :"<<sRadius2<<endl;
float sampleIndex =1; //has to be changed in future
for (int x = 0; x <= tWidth; x++)
    
        QuickVal = x * qvDepth;
    for (int y = 0; y <= tHeight; y++)
    

//Remap the coordinates around a center point of (0, 0)
        nX = x - midX;
        nY = y - midY;

//Offset the pixel amount by the supersampling lookup table
 for(int ii = 1; ii<4;ii++)
            j = nX + ii;
            k = nY + ii;

            //Calculate distance automatically
            sDistance = (j * j) + (k * k);
//cout<<"nx :"<<nX<<" ny :"<<nY<<" j :"<<j<<" k :"<<k<<" sDistance :"<<sDistance<<" sRadius2 :"<<sRadius2<<endl;
            if (sDistance <= sRadius2)
            

                sDistance = sqrt(sDistance);
                radius = sDistance / refDistance;

                if (radius == 0)
                
                    theta = 1;
                
                else
                
                    theta = atan(radius) / radius;
                

//srcX = midX + theta * j * fixZoom;
//srcY = midY + theta * k * fixZoom;

     map_x.at<float>(x,y) = midX + cos(fabs(theta)) * j * fixZoom;

     map_y.at<float>(x,y) = midY + sin(fabs(theta)) * k * fixZoom;
            

else
            

            map_x.at<float>(x,y) = x + cos(fabs(theta))  ;//* fixZoom;//x;
            map_y.at<float>(x,y) = y + sin(fabs(theta)) ;//* fixZoom;//y;

            






图片

【问题讨论】:

你能给我们看看图片+你得到的结果吗?为什么不正确? 由于***的限制,我无法上传图片。你能从onlinephotoinstitute.files.wordpress.com/2013/01/…下载一张图片吗? 拜托,还有结果。我们想看看它为什么不工作。 非常感谢,它现在工作正常,并且消除了镜头失真。问题是:在将极坐标转换为笛卡尔坐标后,我再次改变了极坐标值。 【参考方案1】:

替换以下行。

  map_x.at<float>(x,y) = midX + theta * j * fixZoom;

     map_y.at<float>(x,y) = midY + theta * k * fixZoom;
            

else
            

            map_x.at<float>(x,y) = x   ;//* fixZoom;//x;
            map_y.at<float>(x,y) = y  ;//* fixZoom;//y;

使用参数可执行[图像名称]、BBP、校正参数、缩放参数、应用比例。

ex-> ./lensdistortcorrect image.jpg 24 6.2 2.2 100

【讨论】:

以上是关于影像镜头畸变校正的主要内容,如果未能解决你的问题,请参考以下文章

我在这个镜头畸变校正程序中不断得到一张白色的照片

基于GPU的高分一号影像正射校正的设计与实现

利用GDAL实现影像的几何校正

相机标定中镜头的畸变系数是否必须小于1

R语言Logistic回归模型案例(绘制列线图校正曲线):研究低出生体重婴儿的核心影像因素

影像数据位置明显不对,如何在arcgis中如何修改空间参考