光流法 Optical Flow
最近調研目標跟蹤,看到一個光流法,測試了一下它的效果,挺好玩的,這里對找到的資料簡單整理總結一下。
對于光流法的介紹,可以參看如下博客http://blog.csdn.net/zouxy09/article/details/8683859?:
光流(optic flow)是什么呢?名字很專業,感覺很陌生,但本質上,我們是最熟悉不過的了。因為這種視覺現象我們每天都在經歷。從本質上說,光流就是你在這個運動著的世界里感覺到的明顯的視覺運動(呵呵,相對論,沒有絕對的靜止,也沒有絕對的運動)。例如,當你坐在火車上,然后往窗外看。你可以看到樹、地面、建筑等等,他們都在往后退。這個運動就是光流。而且,我們都會發現,他們的運動速度居然不一樣?這就給我們提供了一個挺有意思的信息:通過不同目標的運動速度判斷它們與我們的距離。一些比較遠的目標,例如云、山,它們移動很慢,感覺就像靜止一樣。但一些離得比較近的物體,例如建筑和樹,就比較快的往后退,然后離我們的距離越近,它們往后退的速度越快。一些非常近的物體,例如路面的標記啊,草地啊等等,快到好像在我們耳旁發出嗖嗖的聲音。
光流除了提供遠近外,還可以提供角度信息。與咱們的眼睛正對著的方向成90度方向運動的物體速度要比其他角度的快,當小到0度的時候,也就是物體朝著我們的方向直接撞過來,我們就是感受不到它的運動(光流)了,看起來好像是靜止的。當它離我們越近,就越來越大(當然了,我們平時看到感覺還是有速度的,因為物體較大,它的邊緣還是和我們人眼具有大于0的角度的)。
呵呵,說了那么多,好像還沒進入比較官方的,研究性的定義。那就貼上一個吧。
光流的概念是Gibson在1950年首先提出來的。它是空間運動物體在觀察成像平面上的像素運動的瞬時速度,是利用圖像序列中像素在時間域上的變化以及相鄰幀之間的相關性來找到上一幀跟當前幀之間存在的對應關系,從而計算出相鄰幀之間物體的運動信息的一種方法。一般而言,光流是由于場景中前景目標本身的移動、相機的運動,或者兩者的共同運動所產生的。
當人的眼睛觀察運動物體時,物體的景象在人眼的視網膜上形成一系列連續變化的圖像,這一系列連續變化的信息不斷“流過”視網膜(即圖像平面),好像一種光的“流”,故稱之為光流(optical flow)。光流表達了圖像的變化,由于它包含了目標運動的信息,因此可被觀察者用來確定目標的運動情況。
研究光流場的目的就是為了從圖片序列中近似得到不能直接得到的運動場。運動場,其實就是物體在三維真實世界中的運動;光流場,是運動場在二維圖像平面上(人的眼睛或者攝像頭)的投影。
那通俗的講就是通過一個圖片序列,把每張圖像中每個像素的運動速度和運動方向找出來就是光流場。那怎么找呢?咱們直觀理解肯定是:第t幀的時候A點的位置是(x1, y1),那么我們在第t+1幀的時候再找到A點,假如它的位置是(x2,y2),那么我們就可以確定A點的運動了:(ux, vy) = (x2, y2) - (x1,y1)。
那怎么知道第t+1幀的時候A點的位置呢? 這就存在很多的光流計算方法了。
1981年,Horn和Schunck創造性地將二維速度場與灰度相聯系,引入光流約束方程,得到光流計算的基本算法。人們基于不同的理論基礎提出各種光流計算方法,算法性能各有不同。Barron等人對多種光流計算技術進行了總結,按照理論基礎與數學方法的區別把它們分成四種:基于梯度的方法、基于匹配的方法、基于能量的方法、基于相位的方法。近年來神經動力學方法也頗受學者重視。
IJCV2011有一篇文章,《A Database and Evaluation Methodology for Optical Flow》里面對主流的光流算法做了簡要的介紹和對不同算法進行了評估。網址是:http://vision.middlebury.edu/flow/
感覺這個文章在光流算法的解說上非常好,條例很清晰。想了解光流的,推薦看這篇文章。另外,需要提到的一個問題是,光流場是圖片中每個像素都有一個x方向和y方向的位移,所以在上面那些光流計算結束后得到的光流flow是個和原來圖像大小相等的雙通道圖像。那怎么可視化呢?這篇文章用的是Munsell顏色系統來顯示。
博文后面還介紹了孟塞爾顏色系統,及光流法在OpenCV中的使用示例
這篇博文寫得很好,很清楚,不過就是相關理論介紹的少了點,有關理論可以參考 http://www.cnblogs.com/gnuhpc/archive/2012/12/04/2802124.html ? :
圖像約束方程可以寫為I(x,y,z,t) = I(x+δx,y+δy,z+δz,t+δt),I(x,y,z,t)為在(x,y,z)位置的體素。我們假設移動足夠的小,那么對圖像約束方程使用泰勒公式,我們可以得到:
H.O.T. 指更高階,在移動足夠小的情況下可以忽略。從這個方程中我們可以得到:
或者
最終得到
Vx,Vy,Vz分別是I(x,y,z,t)的光流向量中x,y,z的組成。三個偏微分則是圖像在(x,y,z,t)這一點上相應方向的差分。
所以
Ix*Vx + Iy*Vy + Iz*Vz = ?It
即
基于此公式,可以推導出 Lucas–Kanade光流算法 ,詳細見博文。
?
在Matlab中也有相關函數可以實現光流法,在機器視覺工具箱中它被封裝成了一個類,使用方便。這里簡單測試一下,看代碼:
% 光流法測試--兩張圖片
clc
clear
close all
% 指定圖片
refimg = 'car0.png'; % 參考圖片
inputimg = 'car1.png'; % 供對比圖片
refimg = 'frame10.png'; % 參考圖片
inputimg = 'frame11.png'; % 供對比圖片
% 讀取圖片
Iref = imread(refimg);
Iinput = imread(inputimg);
if size(Iref, 3) == 3
Irefg = rgb2gray(Iref);
Iinputg = rgb2gray(Iinput);
else
Irefg = Iref;
Iinputg = Iinput;
end
% 創建光流對象及類型轉化對象
opticalFlow = vision.OpticalFlow('ReferenceFrameDelay', 1);
converter = vision.ImageDataTypeConverter;
% 修改光流對象的配置
opticalFlow.OutputValue = 'Horizontal and vertical components in complex form'; % 返回復數形式光流圖
opticalFlow.ReferenceFrameSource = 'Input port'; % 對比兩張圖片,而不是視頻流
if 1 % 使用的算法
opticalFlow.Method = 'Lucas-Kanade';
opticalFlow.NoiseReductionThreshold = 0.001; % 默認是0.0039
else
opticalFlow.Method = 'Horn-Schunck';
opticalFlow.Smoothness = 0.5; % 默認是1
end
% 調用光流對象計算兩張圖片的光流
Iinputg_c = step(converter, Iinputg);
Irefg_c = step(converter, Irefg);
of = step(opticalFlow, Iinputg_c, Irefg_c);
ofH = real(of);
ofV = imag(of);
% 將光流轉化為彩色圖顯示
ofI = computeColor(ofH, ofV);
% 顯示結果
figure
subplot(221)
imshow(Iref)
subplot(222)
imshow(Iinput)
subplot(223)
imshow(ofH, [])
subplot(224)
imshow(ofV, [])
figure
imshow(ofI)
程序中的測試圖片可以從http://vision.middlebury.edu/flow/? ,這個網站提供了供光流法測試的很多測試圖片,方便研究這方面算法的人對比效果,另外函數computeColor是將光流法結果轉化為彩色圖顯示,代碼也在這個網站中。運行程序結果如下
光流法常用在視頻對象跟蹤中,matlab中提供了例子,這里我稍作整理,換用了不同的顯示方式:
% 光流法測試--視頻
clc
clear
close all
% 讀取文件對象
videoReader = vision.VideoFileReader('viptraffic.avi','ImageColorSpace','Intensity','VideoOutputDataType','uint8');
% 類型轉化對象
converter = vision.ImageDataTypeConverter;
% 光流對象
opticalFlow = vision.OpticalFlow('ReferenceFrameDelay', 1);
opticalFlow.OutputValue = 'Horizontal and vertical components in complex form';
if 0 % 使用的算法
opticalFlow.Method = 'Lucas-Kanade';
opticalFlow.NoiseReductionThreshold = 0.001; % 默認是0.0039
else
opticalFlow.Method = 'Horn-Schunck';
opticalFlow.Smoothness = 0.5; % 默認是1
end
% 顯示對象
frame = step(videoReader);
figure
subplot(121)
himg = imshow(frame);
subplot(122)
hof = imshow(frame);
% 開始播放
while ~isDone(videoReader)
% 得到一幀
frame = step(videoReader);
% 格式轉化
im = step(converter, frame);
% 計算光流
of = step(opticalFlow, im);
% 光流圖轉化
ofI = computeColor(real(of), imag(of));
% 顯示
set(himg, 'cdata', frame)
set(hof, 'cdata', ofI)
drawnow
end
release(videoReader);
運行程序結果如下
? ? ? Matlab幫助中有對光流法理論的介紹,簡潔明了,有時間翻譯一下。 from:?http://chunqiu.blog.ustc.edu.cn/?p=661 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的光流法 Optical Flow的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GitHub上一些有用的Reposito
- 下一篇: Matlab制作个人主页