学习鱼眼相机的总结
提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔
文章目錄
- 理論知識(shí)
- 1.魚眼鏡頭的投影模型
- 1.1 幾種投影模型的特點(diǎn)
- 1.1.1 針孔投影模型
- 1.1.2 體視投影模型
- 1.1.3 等距投影模型
- 1.1.4 等積投影模型
- 1.1.5 正交投影模型
- 1.2 幾種投影模型的區(qū)別
- 2.魚眼相機(jī)成像過程
- 3.魚眼圖像的畸變矯正
- 程序
- 總結(jié)
理論知識(shí)
1.魚眼鏡頭的投影模型
??魚眼鏡頭一般是由十幾個(gè)不同的透鏡組合而成的,如下圖所示,在成像的過程中,入射光線經(jīng)過不同程度的折射,投影到尺寸有限的成像平面上,使得魚眼鏡頭與普通鏡頭相比起來?yè)碛辛烁蟮囊曇胺秶?br />
魚眼相機(jī)的成像模型近似為球面投影模型
魚眼相機(jī)的成像過程可近似分解成兩步:
由上圖可知,魚眼相機(jī)的設(shè)計(jì)引入了畸變,而且所成影像存在非常嚴(yán)重的畸變,特別是徑向畸變,因此畸變模型主要考慮徑向畸變。
魚眼相機(jī)的投影函數(shù)是為了盡可能將龐大的場(chǎng)景投影到有限的圖像平面所設(shè)計(jì)的。根據(jù)投影函數(shù)的不同將魚眼相機(jī)的設(shè)計(jì)模型大致分為等距投影模型、等立體角投影模型、正交投影模型和體視投影模型四種。相機(jī)的成像模型實(shí)際上表征的是成像的像高與入射角之間的映射關(guān)系。
1.1 幾種投影模型的特點(diǎn)
1.1.1 針孔投影模型
針孔投影模型為相似性投影模型,其滿足物點(diǎn)、成像中心、像點(diǎn)的共線關(guān)系,其理想成像公式為:
rd=ftanθr_d=ftan\theta rd?=ftanθ
1.1.2 體視投影模型
體視投影模型相比之下畸變最小,球形物面上的微小面元經(jīng)過體視投影后,其像仍然是一個(gè)小圓。所以體視投影對(duì)微小物體成像有相似性。但正是這種成像的相似性,使得該投影方式不能提供足夠的桶形畸變,影響成像視場(chǎng)。其模型如下:
rd=2ftanθ2r_d=2ftan\frac \theta2 rd?=2ftan2θ?
1.1.3 等距投影模型
等距投影模型的投影關(guān)系在入射光線之間的角度相同時(shí),保持其對(duì)應(yīng)各投影點(diǎn)之間的間距相同。其投影模型為:
rd=fθr_d=f\theta rd?=fθ
1.1.4 等積投影模型
等積投影模型的特點(diǎn)是相等立體角的入射面會(huì)產(chǎn)生相等面積的像,其畸變程度介于等距模型與正交模型之間。其模型如下:
rd=2fsinθ2r_d=2fsin\frac \theta2 rd?=2fsin2θ?
1.1.5 正交投影模型
正交投影模型的畸變很大,近180度處的圖像信息幾乎全部丟失,且180度之外的場(chǎng)景區(qū)域?qū)o法進(jìn)行描述。采用這種模型的鏡頭拍出的圖片即使在視角較小的區(qū)域也會(huì)比其他模型鏡頭的畸變更明顯。因此,針對(duì)藝術(shù)攝影類的廣角鏡頭,該模型的校正效果更好。其模型如下:
rd=fsinθr_d=fsin\theta rd?=fsinθ
| 透視投影 | rd=ftanθr_d=ftan\theta rd?=ftanθ | 針孔模型 |
| 體視投影 | rd=2ftanθ2r_d=2ftan\frac \theta2 rd?=2ftan2θ? | 任何直線相交的角度,在變換后保持不變 |
| 等距投影 | rd=fθr_d=f\theta rd?=fθ | 入射光線之間的角度相同時(shí),保持其對(duì)應(yīng)各投影點(diǎn)之間的間距相同 |
| 等積投影 | rd=2fsinθ2r_d=2fsin\frac \theta2 rd?=2fsin2θ? | 相等立體角的入射面會(huì)產(chǎn)生相等面積的像 |
| 正交投影 | rd=fsinθr_d=fsin\theta rd?=fsinθ | 視角不能大于180° |
1.2 幾種投影模型的區(qū)別
四種畸變模型畸變量從大到小依次為:正交投影、等立體角投影、等距投影、體視投影
2.魚眼相機(jī)成像過程
假設(shè)Pw(xw,yw,zw)P_w(x_w,y_w,z_w)Pw?(xw?,yw?,zw?)是世界坐標(biāo)系下的一3D點(diǎn),Pc(xc,yc,zc)P_c(x_c,y_c,z_c)Pc?(xc?,yc?,zc?)是PwP_wPw?在相機(jī)坐標(biāo)系下的點(diǎn):
Pc=RPw+tP_c=RP_w+tPc?=RPw?+t
[xcyczc]=R[xwywzw]+t\begin{bmatrix} x_c \\ y_c \\z_c \\ \end{bmatrix}=R \begin{bmatrix} x_w \\ y_w \\z_w \\ \end{bmatrix}+t???xc?yc?zc?????=R???xw?yw?zw?????+t
如果沒有畸變,直接按照小孔成像投影到像平面上投影點(diǎn)為P0P_0P0?,P0P_0P0?到成像中心OOO的距離為rrr:
r=a2+b2r=\sqrt{a^2+b^2}r=a2+b2?
由相似三角形得:
xca=ycb=zcf\frac {x_c}a=\frac {y_c}b=\frac {z_c}faxc??=byc??=fzc??
因此:
r=f(xczc)2+(yczc)2r=f\sqrt{(\frac {x_c}{z_c})^2+(\frac {y_c}{z_c})^2}r=f(zc?xc??)2+(zc?yc??)2?
所以,可以求出入射角θ\thetaθ,也可以直接由PcP_cPc?的坐標(biāo)直接求出:
tanθ=rf=(xczc)2+(yczc)2=xc2+yc2zctan\theta=\frac rf=\sqrt{(\frac {x_c}{z_c})^2+(\frac {y_c}{z_c})^2}=\frac {\sqrt{x_c^2+y_c^2}}{z_c}tanθ=fr?=(zc?xc??)2+(zc?yc??)2?=zc?xc2?+yc2???
由于發(fā)生畸變,3D點(diǎn)投影時(shí)不可能按照小孔成像的模型進(jìn)行投影,投影點(diǎn)P0P_0P0?到成像中心的距離rrr就被壓縮成rdr_drd?,像點(diǎn)的位置從P0(a,b)P_0(a,b)P0?(a,b)變成實(shí)際位置p′(x′,y′)p'(x',y')p′(x′,y′)
因此:
tanθd=rdftan\theta_d=\frac {r_d}ftanθd?=frd??
由于xxx趨于0時(shí),tanx=xtanx=xtanx=x,成像過程中,實(shí)際得相機(jī)成像面很小只有幾毫米,θd\theta_dθd?比較小,tanθdtan\theta_dtanθd?可近似與θd\theta_dθd?
因此:
lim?n→0tanθd=θd\lim_{n \to 0} tan\theta_d =\theta_d n→0lim?tanθd?=θd?
所以:
rd=ftanθd=θdr_d=ftan\theta_d=\theta_drd?=ftanθd?=θd?
可根據(jù)等距投影模型rd=fθr_d=f\thetard?=fθ,由于魚眼相機(jī)的四種投影模型都是奇函數(shù),使用泰勒展開式
rd=fθ≈k0θ+k1θ3+k2θ+k3θ7+k4θ9r_d=f\theta\approx k_0\theta+k_1\theta^3+k_2\theta+k_3\theta^7+k_4\theta^9rd?=fθ≈k0?θ+k1?θ3+k2?θ+k3?θ7+k4?θ9
第一個(gè)系數(shù)k0k_0k0?可以設(shè)置成1,所以:
θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)\theta_d=\theta(1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8)θd?=θ(1+k1?θ2+k2?θ4+k3?θ6+k4?θ8)
由相識(shí)三角形得:
rdr=x′a=y′b\frac {r_d}r=\frac {x'}a=\frac {y'}brrd??=ax′?=by′?
這里rd{r_d}rd?與rrr的比值直接消去焦距fff,說明與fff無關(guān),上面的公式可以直接把fff當(dāng)成單位1.
所以可以得到:
rdr=θdr\frac {r_d}r=\frac {\theta_d}rrrd??=rθd??
畸變后的點(diǎn)p′p'p′的坐標(biāo)為:
{x′=θdray′=θdrb\begin{cases} x'=\frac {\theta_d}r a \\ y'=\frac {\theta_d}r b \end{cases} {x′=rθd??ay′=rθd??b?
利用相機(jī)內(nèi)參將像平面上的點(diǎn)轉(zhuǎn)換到像素坐標(biāo)系得到最終圖像上的點(diǎn):
{u=fxx′+cxv=fyy′+cy\begin{cases} u=f_xx'+c_x \\ v=f_yy'+c_y \end{cases} {u=fx?x′+cx?v=fy?y′+cy??
3.魚眼圖像的畸變矯正
輸入:魚眼圖像中一像點(diǎn)p(u,v)p(u,v)p(u,v)
輸出:矯正后的像點(diǎn)坐標(biāo)
step1:已知相機(jī)內(nèi)參,把像點(diǎn)ppp轉(zhuǎn)為物理距離(由像素轉(zhuǎn)為米)
{x=(u?cx)/fxy=(v?cy)/fy\begin{cases} x=(u-cx)/f_x \\ y=(v-cy)/f_y \end{cases} {x=(u?cx)/fx?y=(v?cy)/fy??
step2:求出實(shí)際像點(diǎn)到成像中心的距離rdr_drd?,以及等效的折射角
{rd=x2+y2θd=arctan(rd)\begin{cases} r_d=\sqrt{x^2+y^2} \\ \theta_d=arctan(r_d) \end{cases} {rd?=x2+y2?θd?=arctan(rd?)?
step3:已知相機(jī)畸變系數(shù)(k1,k2,k3,k4)(k_1,k_2,k_3,k_4)(k1?,k2?,k3?,k4?),和step2得到的θd\theta_dθd?,求出實(shí)際得θ\thetaθ
θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)\theta_d=\theta(1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8)θd?=θ(1+k1?θ2+k2?θ4+k3?θ6+k4?θ8)
可以使用牛頓迭代法求解一元高次方程:
令f(θ)=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)?θdf(\theta)=\theta(1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8)-\theta_df(θ)=θ(1+k1?θ2+k2?θ4+k3?θ6+k4?θ8)?θd?
{θ0=θdθn+1=θnf(θn)f′(θn)\begin{cases} \theta_0=\theta_d \\ \theta_{n+1}=\theta_n \frac {f(\theta_n)}{f'(\theta_n)}\end{cases} {θ0?=θd?θn+1?=θn?f′(θn?)f(θn?)??
循環(huán)迭代求出θ\thetaθ
step4:得到θ\thetaθ后可以求得未畸變得像點(diǎn)帶成像中心得距離rrr
r=tanθr=tan\thetar=tanθ
step5:求出未畸變像點(diǎn)的坐標(biāo)
{x′=rθdxy′=rθdy\begin{cases}x'=\frac r{\theta_d}x \\ y'=\frac r{\theta_d}y \end{cases} {x′=θd?r?xy′=θd?r?y?
step6:根據(jù)相機(jī)內(nèi)參得到矯正后的坐標(biāo)
{u=fxx′+cxv=fyy′+cy\begin{cases} u=f_xx'+c_x \\ v=f_yy'+c_y \end{cases} {u=fx?x′+cx?v=fy?y′+cy??
程序
按照魚眼相機(jī)的成像模型寫的畸變矯正的函數(shù)
/*已知無畸變圖像的像素點(diǎn),通過魚眼相機(jī)投影模型,找到畸變圖像上的位置,隨后賦值計(jì)算出無畸變圖像*/ //srcImage 輸入的魚眼圖像 //dstImage 輸出矯正后的圖像 void undistortImagess(cv::Mat& srcImage, cv::Mat& dstImage) {cv::Mat src = srcImage.clone();cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);double k1 = distCoeffs.at<double>(0, 0);double k2 = distCoeffs.at<double>(1, 0);double k3 = distCoeffs.at<double>(2, 0);double k4 = distCoeffs.at<double>(3, 0);double fx = cameraMatrix.at<double>(0, 0);double fy = cameraMatrix.at<double>(1, 1);double cx = cameraMatrix.at<double>(0, 2);double cy = cameraMatrix.at<double>(1, 2);int rows = src.rows;int cols = src.cols;cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC1);for (int v = 0; v < rows; v++){for (int u = 0; u < cols; u++){double u_distorted = 0, v_distorted = 0;//(x1,y1)相機(jī)坐標(biāo)系下的坐標(biāo) (x2,y2)畸變后的坐標(biāo)double x1, y1, x2, y2;x1 = (u - cx) / fx;y1 = (v - cy) / fy;double r, theta, thetad;r = sqrt(pow(x1, 2) + pow(y1, 2));theta = atan(r);double theta2 = theta * theta;double theta4 = theta2 * theta2;double theta6 = theta2 * theta2 * theta2;double theta8 = theta4 * theta4;thetad = theta * (1 + k1 * theta2 + k2 * theta4 + k3 * theta6 + k4 * theta8);x2 = thetad / r * x1;y2 = thetad / r * y1;;u_distorted = fx * x2 + cx;v_distorted = fy * y2 + cy;// 賦值 (最近鄰插值)if (u_distorted >= 0 && v_distorted >= 0 && u_distorted < cols && v_distorted < rows) {image_undistort.at<uchar>(v, u) = ROIimage.at<uchar>((int)v_distorted, (int)u_distorted);}else {image_undistort.at<uchar>(v, u) = 0;}}}dstImage = image_undistort.clone(); } /*已知畸變圖像的像素點(diǎn),通過反投影模型,計(jì)算出投影到無畸變圖像的位置,隨后賦值計(jì)算出無畸變圖像*/ //srcImage 輸入的魚眼圖像 //dstImage 輸出矯正后的圖像 void unfold::undistortImagess(cv::Mat& srcImage, cv::Mat& dstImage) {cv::Mat src = srcImage.clone();cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);double fx = cameraMatrix.at<double>(0, 0);double fy = cameraMatrix.at<double>(1, 1);double cx = cameraMatrix.at<double>(0, 2);double cy = cameraMatrix.at<double>(1, 2);double k1 = distCoeffs.at<double>(0, 0);double k2 = distCoeffs.at<double>(1, 0);double k3 = distCoeffs.at<double>(2, 0);double k4 = distCoeffs.at<double>(3, 0);int rows = src.rows;int cols = src.cols;cv::Mat image_undistort = cv::Mat(rows, rows, CV_8UC1);for (int v = 0; v < rows; v++){for (int u = 0; u < cols; u++){double uu = 0, vv = 0;//(x1,y1)相機(jī)坐標(biāo)系下的坐標(biāo) (x2,y2)投影到球面的坐標(biāo)double x1, y1, x2, y2;x1 = (u - cx) / fx;y1 = (v - cy) / fy;double rd, thetad;rd = sqrt(pow(x1, 2) + pow(y1, 2));thetad = atan(rd);double theta = thetad;double xx = NewTonFunction(theta, thetad); double rrr = tan(xx);//x2 = rrr * x1 / rd;y2 = rrr * y1 / rd;uu = fx * x2 + cx;vv = fy * y2 + cy;// 賦值 (最近鄰插值)if (uu >= 0 && vv >= 0 && uu < cols && vv < rows) {image_undistort.at<uchar>(vv, uu) = ROIimage.at<uchar>((int)v, (int)u);}else {image_undistort.at<uchar>(vv, uu) = 0;}}}dstImage = image_undistort.clone(); }總結(jié)
由于我做的項(xiàng)目,需要把魚眼圖片展開,然后拼接,但是魚眼圖片的畸變矯正,直接把邊緣部分給去掉了,導(dǎo)致最有用的部分丟失,因此,我覺得魚眼相機(jī)通過畸變矯正后把它最大的優(yōu)勢(shì)給丟掉了(視野廣),不太實(shí)用。最后也沒有用畸變矯正的程序,但是通過學(xué)習(xí)了解魚眼相機(jī)的投影模型,使我知道3D點(diǎn)如何通過投影得到魚眼圖片,已知魚眼圖片如何通過反投影得到3D點(diǎn)等,在后續(xù)的工作部分起到了很大的作用,真的是我學(xué)到了很多。
總結(jié)
- 上一篇: csv文件查找指定内容
- 下一篇: 删除Management Data Wa