通常摄像机的镜头都会有镜头畸变,尤其是广角镜头,在做图像处理中往往会通过摄像机标定获取镜头的畸变系数,然后进行畸变校正。而在某些特殊的情况下,你可能会需要往图像中加入畸变,下面简单实现了一个向无畸变图像中人为加入径向畸变。
仍然以这幅风景图为例,我用手机拍摄的,畸变程度可以忽略:
1.人为加入桶形畸变(边缘放大率小于中心放大率,导致边缘像素点向图像中心移动)
视场缩放
2.人为加入枕形畸变(边缘放大率大于中心放大率,导致边缘像素点远离图像中心移动)
视场缩放
代码实现如下,使用3D warping和双线性插值。加入桶形畸变disK=0.5,加入枕形畸变disk=-0.5,改变归一化焦距fx,fy实现视场的缩放,如fx=fx*scale和fy=fy*scale。
1 #include <iostream> 2 #include <string> 3 #include <opencv2/opencv.hpp> 4 5 using namespace std; 6 using namespace cv; 7 8 void distortImg(const Mat &srcImg, Mat &dstImg, const float fx, const float fy, const float cx, const float cy) 9 { 10 int imgHeight=srcImg.rows; 11 int imgWidth=srcImg.cols; 12 13 float disK=0.5; 14 15 uchar* pSrcData=(uchar*)srcImg.data; 16 uchar* pDstData=(uchar*)dstImg.data; 17 for (int j=0; j<imgHeight; j++) 18 { 19 for (int i=0; i<imgWidth; i++) 20 { 21 //转到摄像机坐标系 22 float X=(i-cx)/fx; 23 float Y=(j-cy)/fy; 24 float r2=X*X+Y*Y; 25 //加上畸变 26 float newX=X*(1+disK*r2); 27 float newY=Y*(1+disK*r2); 28 //再转到图像坐标系 29 float u=newX*fx+cx; 30 float v=newY*fy+cy; 31 //双线性插值 32 int u0=floor(u); 33 int v0=floor(v); 34 int u1=u0+1; 35 int v1=v0+1; 36 37 float dx=u-u0; 38 float dy=v-v0; 39 float weight1=(1-dx)*(1-dy); 40 float weight2=dx*(1-dy); 41 float weight3=(1-dx)*dy; 42 float weight4=dx*dy; 43 44 int resultIdx=j*imgWidth*3+i*3; 45 if (u0>=0 && u1<imgWidth && v0>=0 && v1<imgHeight) 46 { 47 pDstData[resultIdx+0]=weight1*pSrcData[v0*imgWidth*3 + u0*3+0]+weight2*pSrcData[v0*imgWidth*3+u1*3+0] 48 +weight3*pSrcData[v1*imgWidth*3 +u0*3+0]+weight4*pSrcData[v1*imgWidth*3 + u1*3+0]; 49 pDstData[resultIdx+1]=weight1*pSrcData[v0*imgWidth*3 + u0*3+1]+weight2*pSrcData[v0*imgWidth*3+u1*3+1] 50 +weight3*pSrcData[v1*imgWidth*3 +u0*3+1]+weight4*pSrcData[v1*imgWidth*3 + u1*3+1]; 51 pDstData[resultIdx+2]=weight1*pSrcData[v0*imgWidth*3 + u0*3+2]+weight2*pSrcData[v0*imgWidth*3+u1*3+2] 52 +weight3*pSrcData[v1*imgWidth*3 +u0*3+2]+weight4*pSrcData[v1*imgWidth*3 + u1*3+2]; 53 } 54 } 55 } 56 } 57 58 void main() 59 { 60 string imgPath="data/source_images/"; 61 Mat srcImg = imread(imgPath+"moon.jpg"); 62 pyrDown(srcImg, srcImg); 63 pyrDown(srcImg, srcImg); 64 65 Mat dstImg = srcImg.clone(); 66 dstImg.setTo(0); 67 68 namedWindow("showImg",0); 69 imshow("showImg", srcImg); 70 waitKey(0); 71 72 float fx=930.965; 73 float fy=930.884; 74 float cx=513.823; 75 float cy=385.656; 76 77 distortImg(srcImg, dstImg, fx, fy, cx, cy); 78 79 imshow("showImg", dstImg); 80 waitKey(0); 81 }