OpenCV学习笔记(三十六)——Kalman滤波做运动目标跟踪 OpenCV学习笔记(三十七)——实用函数、系统函数、宏core OpenCV学习笔记(三十八)——显示当前FPS OpenC
OpenCV學(xué)習(xí)筆記(三十六)——Kalman濾波做運(yùn)動(dòng)目標(biāo)跟蹤??
kalman濾波大家都很熟悉,其基本思想就是先不考慮輸入信號(hào)和觀測(cè)噪聲的影響,得到狀態(tài)變量和輸出信號(hào)的估計(jì)值,再用輸出信號(hào)的估計(jì)誤差加權(quán)后校正狀態(tài)變量的估計(jì)值,使?fàn)顟B(tài)變量估計(jì)誤差的均方差最小。具體它的原理和實(shí)現(xiàn),我想也不用我在這里費(fèi)口舌,但這個(gè)理論基礎(chǔ)必須的有,必須得知道想用kalman濾波做跟蹤,必須得先建立運(yùn)動(dòng)模型和觀察模型,不是想用就能用的。如果不能建立運(yùn)動(dòng)模型,也就意味著你所要面對(duì)的問(wèn)題不能用kalman濾波解決。
我結(jié)合一下OpenCV自帶的kalman.cpp這個(gè)例程來(lái)介紹一下如何在OpenCV中使用kalman濾波吧,OpenCV已經(jīng)把Kalman濾波封裝到一個(gè)類KalmanFilter中了。使用起來(lái)非常方便,但那繁多的各種矩陣還是容易讓人摸不著頭腦。這里要知道的一點(diǎn)是,想要用kalman濾波,要知道前一時(shí)刻的狀態(tài)估計(jì)值x,當(dāng)前的觀測(cè)值y,還得建立狀態(tài)方程和量測(cè)方程。有了這些就可以運(yùn)用kalman濾波了。
OpenCV自帶了例程里面是對(duì)一個(gè)1維點(diǎn)的運(yùn)動(dòng)跟蹤,雖然這個(gè)點(diǎn)是在2維平面中運(yùn)動(dòng),但由于它是在一個(gè)圓弧上運(yùn)動(dòng),只有一個(gè)自由度,角度,所以還是1維的。還是一個(gè)勻速運(yùn)動(dòng),建立勻速運(yùn)動(dòng)模型,設(shè)定狀態(tài)變量x = [ x1, x2 ] = [ 角度,角速度 ],則運(yùn)動(dòng)模型為
x1(k+1) = x1(k)+x2(k)*T
x2(k+1)= x2(k)
則狀態(tài)轉(zhuǎn)移方程為
x* = Ax + w
這里設(shè)計(jì)的噪聲是高斯隨機(jī)噪聲,則量測(cè)方程為:
z = Cx + v
看了代碼,對(duì)應(yīng)上以上各項(xiàng):
狀態(tài)估計(jì)值x --> state
當(dāng)前觀測(cè)值z(mì) -->?measurement
KalmanFilter類內(nèi)成員變量transitionMatrix就是狀態(tài)轉(zhuǎn)移方程中的矩陣A
KalmanFilter類內(nèi)成員變量measurementMatrix就是量測(cè)方程中矩陣C
我想就不用我再翻譯了吧。相信有了以上的注釋,大家都能找到它們的對(duì)應(yīng)項(xiàng)。
使用的時(shí)候,除了初始化我剛剛初始化過(guò)的transitionMatrix和measurementMatrix外,還需要初始化processNoiseCov,measurementNoiseCov和errorCovPost。
把它們初始化好之后,接下來(lái)的動(dòng)作就很簡(jiǎn)單了,分兩步走,第一步調(diào)用成員函數(shù)predict得到當(dāng)前狀態(tài)變量的估計(jì)值,第二步調(diào)用成員函數(shù)correct用觀測(cè)值校正狀態(tài)變量。再更新狀態(tài)變量做下一次估計(jì)。聽著好簡(jiǎn)單啊,代碼就不上傳坑爹了,在opencv2.3.1\samples\cpp\kalman.cpp中其義自見(jiàn)。
OpenCV學(xué)習(xí)筆記(三十七)——實(shí)用函數(shù)、系統(tǒng)函數(shù)、宏core
如果你想在OpenCV的基礎(chǔ)上自己開發(fā)一些算法,我覺(jué)得core這部分內(nèi)容不得不精啊,能熟練使用OpenCV的數(shù)據(jù)結(jié)構(gòu)是開發(fā)的基礎(chǔ),又是重中之重。最近就又拌在這上頭了,所以再重溫一下。這次分析一下Utility and System Functions and Macros這部分,就是實(shí)用函數(shù)、系統(tǒng)函數(shù)和宏。
OpenCV在這部分里包含一些類似標(biāo)準(zhǔn)c++、c里面的一些東西。
系統(tǒng)函數(shù)有很多。有些是內(nèi)存方面的操作,類似new delete之類的操作,很多都是為了防止內(nèi)存溢出的函數(shù)有alignPtr、alignSize、allocate、deallocate、fastMalloc、fastFree。格式輸出的函數(shù)啦format(是不是太熟悉了)。還有一些和系統(tǒng)相關(guān)的東西checkHardwareSupport、getNumThreads、getThreadNum、getTickCount、getTickFrequency、getCPUTickCount、setNumThreads。還有一些比較有意思的東西,比如功能類似#ifdef #endf這樣的開關(guān),也有函數(shù)setUseOptimized實(shí)現(xiàn) ,相關(guān)的還有useOptimized函數(shù)。還有一個(gè)不懂的函數(shù)saturate_cast(求指點(diǎn))等待各位補(bǔ)充。
實(shí)用函數(shù)很接近<math.h>里的一些函數(shù),很有意思,可以方便大家開發(fā),有計(jì)算向量角度的函數(shù)fastAtan2、計(jì)算立方根的函數(shù)cubeRoot、向上取整函數(shù)cvCeil、向下取整函數(shù)cvFloor、四舍五入函數(shù)cvRound。注意cvCeil、cvFloor、cvRound和大家常用的ceil、floor、round函數(shù)略有不同,標(biāo)準(zhǔn)庫(kù)函數(shù)返回值并不是int型的變量,必要時(shí)需強(qiáng)制轉(zhuǎn)換,而OpenCV里面的取整函數(shù)返回值為int型。還有一些類似matlab里面的函數(shù),比如cvIsInf判斷自變量是否無(wú)窮大,cvIsNaN判斷自變量是否Not a Number。
宏也很多,這些宏在標(biāo)準(zhǔn)c++、c里也有出現(xiàn),CV_Assert是個(gè)斷言,不知道和assert()有什么區(qū)別。error也是一種異常,還有Exception類這個(gè)異常類。
有了這些東西,開發(fā)起來(lái)有沒(méi)有更順手一些呢~~隨著使用的深入,我會(huì)再補(bǔ)充一些上訴東西的使用心得
OpenCV學(xué)習(xí)筆記(三十八)——顯示當(dāng)前FPS?
最近做一個(gè)東西,需要實(shí)時(shí)顯示,于是想在屏幕顯示FPS。FPS是Frame Per Second的縮寫,中文意思是每秒幀數(shù),即幀速。FPS是測(cè)量用于保存、顯示動(dòng)態(tài)視頻的信息數(shù)量。通俗來(lái)講就是指動(dòng)畫或視頻的畫面數(shù)。
這就需要我在系統(tǒng)函數(shù)一講里提到的getTickCount、getTickFrequency這兩個(gè)函數(shù)了。前一個(gè)函數(shù)返回tick次數(shù),后一個(gè)函數(shù)返回每秒tick次數(shù),它們的比就是時(shí)間咯。
如果想得到一段程序的運(yùn)行時(shí)間,可以套用下面的例子:
[cpp] view plain copy
以上這段程序在測(cè)試算法的時(shí)間消耗在哪里是很好的測(cè)試程序。我這里只需要稍微改寫一下這個(gè)例子,得到每幀之間的時(shí)間,再用我之前在繪圖函數(shù)那節(jié)講過(guò)的putText把FPS顯示到屏幕上咯。
不過(guò)有個(gè)問(wèn)題還是讓我感覺(jué)不舒服,就是用它做的定時(shí)不是很準(zhǔn),感覺(jué)時(shí)間比實(shí)際的快一些。測(cè)試較少,也不敢亂講,歡迎大家測(cè)試并發(fā)表意見(jiàn)
簡(jiǎn)單的很,源程序下載地址:http://download.csdn.net/detail/yang_xian521/3957523
OpenCV學(xué)習(xí)筆記(三十九)——再談OpenCV的數(shù)據(jù)結(jié)構(gòu),Mat是如此強(qiáng)大?
還是一個(gè)實(shí)時(shí)性要求的程序最近把我弄得有些上火。為了提高代碼運(yùn)行的速度,我也是又新啃東西學(xué)了。由于我代碼里使用了vector,網(wǎng)上搜來(lái)搜去有人說(shuō)vector慢,又有人說(shuō)STL里的sort排序速度是我等常人不能企及的,有人說(shuō)要少resize,這個(gè)重新分配內(nèi)存非常耗時(shí),又有人說(shuō)要用swap來(lái)徹底刪除不要的內(nèi)存空間。帶著這么多疑問(wèn),我實(shí)在不知道我程序慢的原因。于是乎閱讀了《Effective STL》,這書挺深的,粗淺讀讀,先把自己急著弄清楚的以上各問(wèn)題弄懂。再看程序,做了些優(yōu)化,速度還是提高不多,頭開始大了
我的解決辦法是用我上一講提到的getTickCount、getTickFrequency函數(shù)分析我代碼的運(yùn)行時(shí)間,遇到的問(wèn)題是下面這句非常耗時(shí)
[cpp] view plain copy10000*10只是我要開辟的空間,不知道怎么用reserve函數(shù)開辟, 這句運(yùn)行了大概100ms。今天再看這段代碼,發(fā)現(xiàn)我太傻了,何必要用vector<vector<int>>呢,完全可以用OpenCV自帶的Mat來(lái)解決啊,于是把上面這句改寫如下 [cpp] view plain copy
結(jié)果只需要0.2ms!!!同志們,STL在Mat面前都顯得如此無(wú)力啊,有木有啊!我決定花費(fèi)幾天的時(shí)間再好好讀讀reference的core的部分,來(lái)吃透OpenCV的數(shù)據(jù)結(jié)構(gòu)。而且感覺(jué)Mat跟STL的兼容性很好,也有push_back,pop_back這樣的操作,所以啊,同志們,千萬(wàn)別把Mat只當(dāng)做是顯示圖片用的,它是很強(qiáng)大的數(shù)據(jù)結(jié)構(gòu),用了它,可以事半功倍,誰(shuí)用誰(shuí)知道!~~
OpenCV學(xué)習(xí)筆記(四十)——再談OpenCV數(shù)據(jù)結(jié)構(gòu)Mat詳解
我記得開始接觸OpenCV就是因?yàn)橐粋€(gè)算法里面需要2維動(dòng)態(tài)數(shù)組,那時(shí)候看core這部分也算是走馬觀花吧,隨著使用的增多,對(duì)Mat這個(gè)結(jié)構(gòu)越來(lái)越喜愛(ài),也覺(jué)得有必要溫故而知新,于是這次再看看Mat。
Mat最大的優(yōu)勢(shì)跟STL很相似,都是對(duì)內(nèi)存進(jìn)行動(dòng)態(tài)的管理,不需要之前用戶手動(dòng)的管理內(nèi)存,對(duì)于一些大型的開發(fā),有時(shí)候投入的lpImage內(nèi)存管理的時(shí)間甚至比關(guān)注算法實(shí)現(xiàn)的時(shí)間還要多,這顯然是不合適的。除了有些嵌入式場(chǎng)合必須使用c語(yǔ)言,我任何時(shí)候都強(qiáng)烈像大家推薦Mat。
Mat這個(gè)類有兩部分?jǐn)?shù)據(jù)。一個(gè)是matrix header,這部分的大小是固定的,包含矩陣的大小,存儲(chǔ)的方式,矩陣存儲(chǔ)的地址等等。另一個(gè)部分是一個(gè)指向矩陣包含像素值的指針。
[cpp] view plain copy需要注意的是,copy這樣的操作只是copy了矩陣的matrix header和那個(gè)指針,而不是矩陣的本身,也就意味著兩個(gè)矩陣的數(shù)據(jù)指針指向的是同一個(gè)地址,需要開發(fā)者格外注意。比如上面這段程序,A、B、C指向的是同一塊數(shù)據(jù),他們的header不同,但對(duì)于A的操作同樣也影響著B、C的結(jié)果。剛剛提高了內(nèi)存自動(dòng)釋放的問(wèn)題,那么當(dāng)我不再使用A的時(shí)候就把內(nèi)存釋放了,那時(shí)候再操作B和C豈不是很危險(xiǎn)。不用擔(dān)心,OpenCV的大神為我們已經(jīng)考慮了這個(gè)問(wèn)題,是在最后一個(gè)Mat不再使用的時(shí)候才會(huì)釋放內(nèi)存,咱們就放心用就行了。
如果想建立互不影響的Mat,是真正的復(fù)制操作,需要使用函數(shù)clone()或者copyTo()。
說(shuō)到數(shù)據(jù)的存儲(chǔ),這一直就是一個(gè)值得關(guān)注的問(wèn)題,Mat_<uchar>對(duì)應(yīng)的是CV_8U,Mat_<uchar>對(duì)應(yīng)的是CV_8U,Mat_<char>對(duì)應(yīng)的是CV_8S,Mat_<int>對(duì)應(yīng)的是CV_32S,Mat_<float>對(duì)應(yīng)的是CV_32F,Mat_<double>對(duì)應(yīng)的是CV_64F,對(duì)應(yīng)的數(shù)據(jù)深度如下:
? CV_8U - 8-bit unsigned integers ( 0..255 )
? CV_8S - 8-bit signed integers ( -128..127 )
? CV_16U - 16-bit unsigned integers ( 0..65535 )
? CV_16S - 16-bit signed integers ( -32768..32767 )
? CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
? CV_32F - 32-bit ?oating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
? CV_64F - 64-bit ?oating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
這里還需要注意一個(gè)問(wèn)題,很多OpenCV的函數(shù)支持的數(shù)據(jù)深度只有8位和32位的,所以要少使用CV_64F,但是vs的編譯器又會(huì)把float數(shù)據(jù)自動(dòng)變成double型,有些不太爽。
還有個(gè)需要注意的問(wèn)題,就是流操作符<<對(duì)于Mat的操作,僅限于Mat是2維的情況。
還有必要說(shuō)一下Mat的存儲(chǔ)是逐行的存儲(chǔ)的。
再說(shuō)說(shuō)Mat的創(chuàng)建,方式有兩種,羅列一下:1.調(diào)用create(行,列,類型)2.Mat(行,列,類型(值))。例如:
[cpp] view plain copy要是想創(chuàng)建更高維的矩陣,要寫成下面的方式 [cpp] view plain copy
對(duì)于矩陣的行操作或者列操作,方式如下:(注意對(duì)列操作時(shí)要新建一個(gè)Mat,我想應(yīng)該跟列地址不連續(xù)有關(guān)) [cpp] view plain copy
下面的東西就比較狂暴了,對(duì)于外來(lái)的數(shù)據(jù),比如你從別的地方接受了一幅圖片,但可以不是Mat結(jié)構(gòu)的,而只有一個(gè)數(shù)據(jù)的指針,看看接下來(lái)的代碼是如何應(yīng)付的,重點(diǎn)哦,親 [cpp] view plain copy
親,有木有很簡(jiǎn)單!!!
還有一種快速初始化數(shù)據(jù)的辦法,如下:
[cpp] view plain copy也可以把原來(lái)的IplImage格式的圖片直接用Mat(IplImage)的方式轉(zhuǎn)成Mat結(jié)構(gòu),也可以像Matlab一樣調(diào)用zeros()、ones()、eye()這樣的函數(shù)進(jìn)行初始化。
如果你需要提前釋放數(shù)據(jù)的指針和內(nèi)存,可以調(diào)用release()。
對(duì)于數(shù)據(jù)的獲取,當(dāng)然還是調(diào)用at<float>(3, 3)這樣的格式為最佳。其他的方法我甚少嘗試,就不敢介紹了。
最后要提的一點(diǎn)是關(guān)于Mat的表達(dá)式,這個(gè)也非常多,加減乘除,轉(zhuǎn)置求逆,我怎么記得我以前介紹過(guò)呢。那就不多說(shuō)啦~
from: http://blog.csdn.net/yang_xian521/article/category/910716
總結(jié)
以上是生活随笔為你收集整理的OpenCV学习笔记(三十六)——Kalman滤波做运动目标跟踪 OpenCV学习笔记(三十七)——实用函数、系统函数、宏core OpenCV学习笔记(三十八)——显示当前FPS OpenC的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OpenCV学习笔记(三十一)——让de
- 下一篇: OpenCV学习笔记(四十一)——再看基