通常攝像機的鏡頭都會有鏡頭畸變,尤其是廣角鏡頭,在做圖像處理中往往會通過攝像機標定獲取鏡頭的畸變系數,然后進行畸變校正。而在某些特殊的情況下,你可能會需要往圖像中加入畸變,下面簡單實現了一個向無畸變圖像中人為加入徑向畸變。
仍然以這幅風景圖為例,我用手機拍攝的,畸變程度可以忽略:

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 }
