攝像機成像、畸變模型


一 攝像機成像模型

成像的過程實質上是幾個坐標系的轉換。首先空間中的一點由世界坐標系轉換到攝像機坐標系,然后再將其投影到成像平面(攝像機的CCD),最后再將成像平面上的數據轉換到圖像平面(最后生成的圖像)。


  圖1-1

世界空間內的一個點在圖像上成像的過程稱為投影成像過程,這中間轉換過程構成的矩陣M稱為投影矩陣


攝像機的畸變參數與相機成像時采用的分辨率無關,而fx,fy和光心位置cx,cy與分辨率有關,但是成倍數關系,例如在分辨率320×240分辨率標定得到內參數為fx0,fy0,cx0,cy0,那么在分辨率640×480下對應的參數則為2fx0,2fy0,2cx0,2cy0。


上面這些參數中,f,t所采用的量綱都是mm,而dx和dy指的是每個像素個數的大小,即mm/pixel,那么經過換算最后得到的u、v的量綱自然也就是像素。fx和fy是由f/dx,f/dy計算而來,表示的是長度值為f時對應的像素個數,也即長度值為f(mm)時,在圖像平面的x方向和y方向的像素個數,fx、fy、u0、v0構成A,A右邊的數據為[R|t]M’,看起來[R|t]M’對應的數據的量綱好像是mm,因為M’和t的量綱都是mm,這樣A里面的量綱又為像素,這樣乘起來的量綱就是mm*pixel了,這顯然不對。但是事實情況並不是真的這樣,最后[R|t]M’與A相乘的時候,[R|t]M’的結果是需要進行歸一化的,即[xc yc zc 1] →[xc/zc yc/zc 1],這個時候它的量綱其實就只是倍數了。整個過程如下圖


圖 1-2


OpenCV標定出來的內參數矩陣一般為(分辨率為640×480)

<Camera_Matrix type_id="opencv-matrix">

 <rows>3</rows>

 <cols>3</cols>

 <dt>d</dt>

 <data>

   5.3193633829444082e+002 0. 3.1950000000000000e+002 0.

   5.3193633829444082e+002 2.3950000000000000e+002 0. 0. 1.</data></Camera_Matrix>


這里的fx≈531.9,fy≈531.9,u0=319.5,v0=239.5。u0和v0比較好理解,差不多就是圖像的中心,但是這里的fx和fy為500多還是有點抽象,雖然前面已經說了表示焦距長度對應的像素個數。根據上圖中u和v的計算公式,還有標定的內參矩陣值,其實可以反推出x’、y’的大致大小,這里u的最大值是640,v的最大值為480,用這些值可以算出x’和y’的最大值分別為0.6025和0.4521,它們分別代表經過Z值歸一化后的比例值,這個值實質上反映了相機的視角


二 成像畸變

在沒有畸變的情況下,理想的成像的過程是如圖1-2所示


但是在實際的情況中,真正的鏡頭通常有一些形變,主要的變形為徑向形變,也會有輕微的切向形變。所以上面的模型需要擴展為


                                       圖2-1

k1和k2是徑向形變系數,p1和p2是切向形變系數。OpenCV中沒有考慮高階系數。形變系數跟拍攝的場景無關,因此它們是內參數,而且與拍攝圖像的分辨率無關。參見opencv中文wiki


opencv計算得到的畸變參數形式為:

<Distortion_Coefficients type_id="opencv-matrix">

 <rows>5</rows>

 <cols>1</cols>

 <dt>d</dt>

 <data>

   6.7442695842244271e-002 2.4180872220967919e-001 0. 0.

   -3.3970575589699975e-001</data></Distortion_Coefficients>

對應存放的畸變參數為[k1,k2,p1,p2[,k3[,k4,k5,k6]]


三 畸變校正

根據前面的說明,可以知道攝像機拍下來的圖片是存在畸變的,現在需要根據內參矩陣和畸變參數對存在畸變的圖像進行校正。校正的過程就是就是圖2-1描述的過程。


首先是根據拍攝得到的存在畸變圖像的坐標,計算出根據畸變模型得到的校正圖像對應的坐標,這樣就建立了畸變圖像坐標和校正圖像坐標之間的映射關系。同時計算出來的校正坐標存在小數,所以就需要對其插值。

例如XYsrc(1,1)<-->XYrect(1.5,1.0),那么假如采用簡單的線性插值的話,Irect(1.5,1.0)=[Isrc(1,1)+Isrc(2,1)]*0.5

Irect就是算出來的校正后的像素值。


進行畸變的matlab校正代碼(參見stackoverflow)如下:

 

[cpp]  view plain  copy
 
  1. clear;  
  2. clc;  
  3. A =[5.9418398977142772e+002 0 3.1950000000000000e+002;  
  4.     0    5.941839897714e+002 2.3950000000000000e+002;  
  5.     0 0 1];  
  6. D = [6.7442695842244271e-002 2.4180872220967919e-001 0 0 -3.3970575589699975e-001];  
  7. fx = A(1,1);  
  8. fy = A(2,2);  
  9. cx = A(1,3);  
  10. cy = A(2,3);  
  11. k1 = D(1);  
  12. k2 = D(2);  
  13. k3 = D(5);  
  14. p1 = D(3);  
  15. p2 = D(4);  
  16.   
  17. K = A;  
  18. Idistorted = imread('logi.jpg');  
  19. Idistorted = rgb2gray(Idistorted);  
  20. Idistorted = im2double(Idistorted);  
  21. I = zeros(size(Idistorted));  
  22. [i j] = find(~isnan(I));  
  23.   
  24. % Xp = the xyz vals of points on the z plane  
  25. Xp = inv(K)*[j i ones(length(i),1)]';  
  26.   
  27. % Now we calculate how those points distort i.e forward map them through the distortion  
  28. r2 = Xp(1,:).^2+Xp(2,:).^2;  
  29. x = Xp(1,:);  
  30. y = Xp(2,:);  
  31.   
  32. x = x.*(1+k1*r2 + k2*r2.^2) + 2*p1.*x.*y + p2*(r2 + 2*x.^2);  
  33. y = y.*(1+k1*r2 + k2*r2.^2) + 2*p2.*x.*y + p1*(r2 + 2*y.^2);  
  34.   
  35. % u and v are now the distorted cooridnates  
  36. u = reshape(fx*x + cx,size(I));  
  37. v = reshape(fy*y + cy,size(I));  
  38.   
  39. % Now we perform a backward mapping in order to undistort the warped image coordinates  
  40. I = interp2(Idistorted, u, v);  
  41. subplot(121); imagesc(Idistorted);  
  42. subplot(122); imagesc(I);  

 


得到的結果圖為:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM