日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

鱼眼图像的校正(Python实现)

發布時間:2023/12/14 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 鱼眼图像的校正(Python实现) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題描述

本文承接上文《魚眼圖像提取有效區域》,鏈接:https://blog.csdn.net/Megurine_Luka_/article/details/110563049

相對于常規鏡頭,魚眼鏡頭拍攝的圖像視角廣,能看到很大范圍的東西。但這會以所拍攝的圖像產生一定程度的扭曲為代價(畸變)。圖像校正就是修正畸變圖像的過程。

方案

本文的校正策略仍是參考論文《魚眼成像全景漫游系統的研究》,鏈接:https://xueshu.baidu.com/usercenter/paper/show?paperid=5a422997f595ef7b2d4dbe5f64b541ee&site=xueshu_se

一種傳統的魚眼校正方法是經緯度映射法,就是先將魚眼圖像映射在一個球面上。這樣做不無道理,因為魚眼鏡頭成像的時候,光線就是從一個球面經過折射,投射在成像平面上的(雖然事實并沒有那么簡單,但大體可以看作這樣),如下圖所示。而現在就是將成像過程反過來做。

之后,通過一系列坐標變換,將空間坐標轉換為經緯度坐標,再根據經緯度坐標直接投射到二維平面上,完成校正。

但這樣的效果并不理想,畸變仍然十分嚴重。舉個例子,格陵蘭島的面積不大,但它所跨的緯度很大,所以如果直接以經緯度為坐標投射在二維平面的話,它的面積會遠遠超過澳大利亞的面積。

首先,經度對畸變其實沒什么影響,直接映射即可,如下圖。我們需要處理的是緯度的問題。

對此,論文提出,將球面上的點經過一定的偏折,再映射到圖像平面上。下圖中(注意,此圖是從上向下看的,圖中的坐標軸與字母表示跟上圖是不對應的,從這里開始是緯度,是經度),是一個常數,它表示線段AC(點A就是要映射的點)與出射光線的夾角,最大為3/4Π,論文以及本文代碼中,將其設定為Π/2。實際上,如果光線不發生偏折,其映射結果是最精確的,但這需要一個無窮大的平面。偏折的意義在于將映射結果限定在一定范圍內。

經過一系列復雜的推導,可以得出如下結論:

推導過程詳見論文原文。其實是我沒看懂。

代碼

函數l

def ll(omiga,fai):x=math.sin(omiga)*math.sqrt(math.cos(fai)**2+(1-math.sin(fai))**2)y=math.sin(math.pi-omiga-math.atan((1-math.sin(fai))/abs(math.cos(fai))))return x/y

插值處理

映射完畢后的圖片并不完整,因為算法是將球面上的點映射到一個平面上,但并不能保證平面上的每個點都被填滿,所以會存在一些縫隙,如下圖所示。

故此,需要對圖片進行插值處理。以下是我亂寫的插值算法,我也不知道它叫什么插值。

#data是二維數組,表示圖片,n,m表示大小 def inter(data,n,m):datat=np.copy(data)datas=np.copy(data)for j in range(m):sta=0if(data[0][j]==0):for i in range(n):if(data[i][j]!=0):sta=ibreakfor i in range(sta,0,-1):datat[i][j]=data[sta][j]end=0 if(data[n-1][j]==0):for i in range(n-1,0,-1):if(data[i][j]!=0):end=ibreakfor i in range(end,n,1):datat[i][j]=data[end][j]for i in range(n):if(data[i][j]!=0):x=data[sta][j]y=data[i][j]for k in range(sta,i,1):datat[k][j]=x+int((y-x)*(float(k-sta)/float(i-sta))) sta=ifor i in range(n):sta=0if(data[i][0]==0):for j in range(m):if(data[i][j]!=0):sta=jbreakfor j in range(sta,0,-1):datas[i][j]=data[i][sta]end=0 if(data[i][m-1]==0):for j in range(m-1,0,-1):if(data[i][j]!=0):end=jbreakfor j in range(end,m,1):datas[i][j]=data[i][end]for j in range(m):if(data[i][j]!=0):x=data[i][sta]y=data[i][j]for k in range(sta,j,1):datas[i][k]=x+int((y-x)*(float(k-sta)/float(j-sta))) sta=jfor i in range(n):for j in range(m):data[i][j]=int((datas[i][j]+datat[i][j])/2)return data

主函數

再次說明,關于R,(u0,v0)的求解,詳見上一篇文章:https://blog.csdn.net/Megurine_Luka_/article/details/110563049

此代碼部分借鑒于https://blog.csdn.net/huoxingrenhdh/article/details/89057928,鳴謝。

#截取目標圖像,R為圓半徑,(u0,v0)為圓心img=cv2.imread(opt.path)img_valid=img[int(u0-R):int(u0+R+1),int(v0-R):int(v0+R+1)]#cv2.imwrite(opt.res_path,img_valid)m,n,k=img_valid.shape[:3]result=np.zeros((int(m*3),int(n*3),k))l=0w=0for i in range(m):for j in range(n):#經緯變換u=j-Rv=R-ir=math.sqrt(u*u+v*v)if(r==0):fi=0elif(u>=0):fi=math.asin(v/r)else:fi = math.pi - math.asin(v/r)f = R * 2 / math.pitheta = r / fx=f * math.sin(theta) * math.cos(fi)y=f * math.sin(theta) * math.sin(fi)z=f * math.cos(theta)#sita經度,fai緯度rr= math.sqrt(x * x + z * z)sita = math.pi / 2 - math.atan( y /rr)if(z>=0):fai = math.acos(x/rr)else:fai= math.pi - math.acos(x/rr)xx=round(f*sita)#opt.omiga取Π/2h=ll(opt.omiga,0)if fai<(math.pi/2):yy=round(f*(h-ll(opt.omiga,fai)))else:yy=round(f*(h+ll(opt.omiga,fai)))if ((xx < 1) | (yy < 1) | (xx > m) | (yy > n)):continuel=max(l,xx)w=max(w,yy)result[xx,yy,0] = img_valid[i, j, 0]result[xx,yy,1] = img_valid[i, j, 1]result[xx,yy,2] = img_valid[i, j, 2]result=result[0:l+1,0:w+1]#插值處理result=np.transpose(result,[2,0,1])result[0]=inter(result[0],l,w)result[1]=inter(result[1],l,w)result[2]=inter(result[2],l,w)result=np.transpose(result,[1,2,0])#輸出Undistortion = np.uint8(result)cv2.imwrite(opt.res_path,Undistortion)

校正結果

?

總結

以上是生活随笔為你收集整理的鱼眼图像的校正(Python实现)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。