通過R語言處理高斯光束
圖片加載與顯示
R語言中也有不少圖像處理包,著名的magick就提供了R語言的接口。但是magick包更像是一個代碼版的PS,可以實現諸多高級功能,但過於完整的代碼封裝使得一些基礎操作反而難以施展。所以我們使用imager包。
本實驗在RStudio中運行。
首先,安裝並導入包。
然後,通過load.image讀取圖片賦值給變量,在R語言中推薦使用<-
進行賦值,賦值之後可以在右側Environment
選項卡中查看數據區,可以看到我們賦值的img
是一個Large cimg
類型。
通過dim
函數可以查看數據的維度,可以看到該數據類型有4個維度,前兩個分別代表圖片的長、寬;第三個代表幀數;第四個代表顏色通道,其值爲3,表示這是一個rgb圖片。
讀取圖片之後通過plot
命令可以方便地查看圖片數據。
> install.packages(imager)
> library(imager)
> img <- load.image("1.bmp")
> dim(img)
[1] 640 480 1 3
> plot(img)
在使用plot之後,可以在右側的Plots
選項卡中查看剛剛畫出的數據,如下圖所示。
圖像截取
爲了便於處理,一般需要將圖片轉換爲矩陣格式,而對於rgb圖像而言,還需要將通道統一,即先通過grayscale
轉成灰度圖像,然後通過as.matrix
轉成矩陣。
通過image
函數可以查看矩陣的數據,其輸入參數爲x軸座標取值、y軸座標取值。
> gray <- grayscale(img)
> imgMat = as.matrix(gray)
> dim(imgMat)
[1] 640 480
> m = dim(imgMat)[1]
> n = dim(imgMat)[2]
> x <- 1:m
> y <- 1:n
> image(x,y,imgMat)
我們可以看到矩陣中大量的數據是無效的背景,需要對矩陣進行截取。在得到矩陣的image圖像之後,可以通過locator
命令交互式選取座標位置,從而可以精確地截取矩陣。其方法爲,輸入命令之後,將鼠標放在圖像上,當鼠標光標變爲十字時點擊,R會記錄下鼠標點擊的位置。
然後通過[:,:]
的索引方法,對矩陣進行截取。
> unlist(locator(2))
x1 x2 y1 y2
356.8567 422.5432 186.0054 246.7325
> roi = imgMat[356:422,186:246]
> image(roi) #當不輸入座標時,其橫縱座標默認歸一化
顯示強度
僞彩圖雖然也能反應出光斑的強度信息,但總體來說不夠直觀,而是依賴於人的主觀感覺。在R語言中,graphics包提供了3d圖像繪製函數persp
,其輸入參數分別爲x、y、z,所以我們需要將矩陣拆分成三個向量,分別代表x軸、y軸以及圖片的像素點強度。
> x <- 1:dim(roi)[1]
> y <- 1:dim(roi)[2]
> persp(x,y,z)
> persp(x,y,roi,theta=30,phi=50,axes=TRUE,shade=0.2,col="#00AAFF")
其中,theta,phi這兩個參數的作用是調整視角,shade爲陰影,col爲顏色,其輸入的值爲16進制的rgb。
高斯擬合
由於矩陣是二維數據,所以我們首先通過每列選取最大值的方式得到一個數組。R語言中不直接提供計算矩陣每一行最大值的函數,但是提供了apply
,可以指定矩陣的行操作或者列操作。其輸入變量位待處理矩陣,行列標識以及處理函數。行列標識中,1代表行處理,2代表列處理。
> arr = apply(roi,1,max) #對每一行執行max操作,max即選取最大值
> plot(arr) #畫圖
最後,就是最重要的數據擬合。在R語言中,通過nlm
函數進行非線性擬合,其輸入參數分別爲擬合函數表達式以及擬合參數的初始值。其中,擬合函數表達式中的變量需要預先定義好。
對於高斯函數,其表達式爲
其中,y即我們之前求取最大值得到的arr,x則爲與arr等長的自然數列。a的值表示該函數的最大值;b表示其中心值,c表示當y值降到分之一處時x距離中心的位置。初始值可根據此選取。
> x <- 1:length(arr) #建立x
> a0 <- max(arr) #a的初始值
> b0 <- length(arr)/2 #b的初始值,根據圖像可知,b的初始值在數據的中心位置
> c0 <- length(arr)/4 #c的初始值
> fit <- nlm(arr~~a*exp(-((x-b)/c)^2),start=list(a=a0,b=b0,c=c0))
> fit
Nonlinear regression model
model: arr ~ a * exp(-((x - b)/c)^2)
data: parent.frame()
a b c
0.2285 35.7438 19.7131 #此即爲擬合參數
residual sum-of-squares: 0.005557
Number of iterations to convergence: 5
Achieved convergence tolerance: 5.998e-06
通過predict
函數可以提取fit中的模型,並根據輸入的x得出擬合之後的y值。我們可以據此畫出原始數據與擬合函數的圖像。
> y = predict(fit,list(x=x))
> plot(x,arr)
> lines(x,y,col='red')