通常摄像机的镜头都会有镜头畸变,尤其是广角镜头,在做图像处理中往往会通过摄像机标定获取镜头的畸变系数,然后进行畸变校正。而在某些特殊的情况下,你可能会需要往图像中加入畸变,下面简单实现了一个向无畸变图像中人为加入径向畸变。
仍然以这幅风景图为例,我用手机拍摄的,畸变程度可以忽略:
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 }