短焦镜头通常会产生桶形失真,以下是校正算法的matlab代码:
img_origin1 = imread('Still001.bmp');
img_origin = rgb2gray(img_origin1);
k1 = -0.00000037; % 形变参数,根据实际情况调整
k2 = -0.00000037;
img_size = size( img_origin );
img_undist = zeros( img_size );
img_undist = uint8( img_undist );
for l1 = 1:img_size(1) % 垂直方向
y = l1 - img_size(1)/2;
for l2 = 1:img_size(2) % 水平方向
x = l2 - img_size(2)/2;
x1 = round( x * ( 1 + k1 * x * x + k2 * y * y ) );
y1 = round( y * ( 1 + k1 * x * x + k2 * y * y ) );
y1 = y1 + img_size(1)/2;
x1 = x1 + img_size(2)/2;
img_undist(l1,l2) = img_origin(y1, x1);
end
end
figure(1);
subplot(121); imshow(img_origin);
subplot(122); imshow(img_undist);
imwrite(img_origin,'1.bmp');
imwrite(img_undist,'2.bmp');
在实时视频处理中,如果对每帧图像都要重复进行坐标转换运算,就是个很大的浪费,我们可以在初始化过程中先将坐标对应关系建立一个二维查找表,之后每帧处理只需要查表,C++代码如下(用到了OpenCV):
// 镜头径向畸变校正初始化
void LensCorrectInit( double k1 = -0.00000035, double k2 = -0.00000035 );
// 镜头径向畸变校正初始化
void LensCorrectInit( double k1, double k2 )
{
int imgWidth = camera.GetWidth(); // 获得摄像头图像尺寸
int imgHeight = camera.GetHeight();
int imgWd2 = imgWidth>>1;
int imgHd2 = imgHeight>>1;
int it;
int jt;
int it2;
int jt2;
for( int i=0; i<imgHeight; i++ )
{
it = ( i + 1 ) - imgHd2; // (i+1) 是其真正的图像坐标
for( int j=0; j<imgWidth; j++ )
{
double temp;
jt = ( j + 1 ) - imgWd2; // (j+1) 是其真正的图像坐标
temp = 1 + k1*it*it + k2*jt*jt;
it2 = (int)(temp * it);
jt2 = (int)(temp * jt);
it2 = it2 + imgHd2 + 1;
jt2 = jt2 + imgWd2 + 1;
CorrInd[i][j].x = jt2;
CorrInd[i][j].y = it2;
}
}
}
// 镜头径向畸变校正
void LensCorrect( IplImage* src, IplImage* dst )
{
int imgWidth = dst->width;
int imgHeight = dst->height;
int it2;
int jt2;
for( int i=0; i<imgHeight; i++ )
{
uchar *pdstdata = (uchar*)(dst->imageData) + i*dst->widthStep;
for( int j=0; j<imgWidth; j++ )
{
it2 = CorrInd[i][j].y;
jt2 = CorrInd[i][j].x;
uchar * psrcdata = cvPtr2D( src, it2, jt2 );
*(pdstdata++) = *(psrcdata++);
*(pdstdata++) = *(psrcdata++);
*(pdstdata++) = *(psrcdata++);
}
}
}