基于Virtex-II平臺的目標(biāo)捕捉系統(tǒng)的的設(shè)計和實現(xiàn),附完整代碼
掃描二維碼
隨時隨地手機看文章
摘要
此項目旨在對一個目標(biāo)捕獲系統(tǒng)的圖像處理算法進(jìn)行嚴(yán)格的硬件驗證.我們將用分別用硬件設(shè)計和多核軟件設(shè)計來分別實現(xiàn)這個算法,并比較這兩種實現(xiàn)方式.在創(chuàng)建多核軟件設(shè)計的過程中我們還將對OpenFire軟核進(jìn)行改進(jìn)以搭建起這個多核網(wǎng)絡(luò).
這個目標(biāo)捕獲系統(tǒng)的圖像處理算法的硬件實現(xiàn)方式和多核軟件實現(xiàn)方式將在一個基于FPGA試驗板上進(jìn)行比較.以此證明通過合理配置和編程多核軟件實現(xiàn)同樣很容易達(dá)到和硬件實現(xiàn)一樣的低功耗性能,并只有非常低的面積消耗.
引言
隨著現(xiàn)代高速處理器的迅猛發(fā)展,圖像處理技術(shù)也日益成熟。其中,移動目標(biāo)的視頻檢測與跟蹤是圖像處理、分析應(yīng)用的一個重要領(lǐng)域,是當(dāng)前相關(guān)領(lǐng)域的研究前沿。移動目標(biāo)視頻檢測與跟蹤技術(shù),在機器人視覺、交通監(jiān)測、可視預(yù)警、機器導(dǎo)航等民用領(lǐng)域有著廣泛的應(yīng)用.基于FPGA為核心器件構(gòu)成的視頻識別和跟蹤裝置,實現(xiàn)圖像跟蹤各項功能。此項目提出的跟蹤算法與設(shè)計的跟蹤裝置可在一定程度上解決視頻跟蹤精度低、處理速度慢的問題,同時本視頻跟蹤裝置也可作為進(jìn)一步研究圖像處理與跟蹤控制的平臺。該系統(tǒng)體積小,靈活性高,易于升級,可應(yīng)用于無人值守的智能監(jiān)控系統(tǒng),如銀行,金庫,倉庫等重地。當(dāng)發(fā)現(xiàn)異常情況出現(xiàn)時,該系統(tǒng)能夠自動報警或采取其它相應(yīng)的措施,從而更有效、可靠地實現(xiàn)了安全防范,同時也在很大程度上減少了監(jiān)視人員的工作量和疲勞度,大大提高了工作效率。
此項目旨在對一個目標(biāo)捕獲系統(tǒng)的圖像處理算法進(jìn)行嚴(yán)格的硬件驗證.我們將用分別用硬件設(shè)計和多核軟件設(shè)計來分別實現(xiàn)這個算法,并比較這兩種實現(xiàn)方式.在創(chuàng)建多核軟件設(shè)計的過程中我們還將對OpenFire軟核進(jìn)行改進(jìn)以搭建起這個多核網(wǎng)絡(luò).
這個目標(biāo)捕獲系統(tǒng)的圖像處理算法的硬件實現(xiàn)方式和多核軟件實現(xiàn)方式將在一個基于FPGA試驗板上進(jìn)行比較.以此證明通過合理配置和編程多核軟件實現(xiàn)同樣很容易達(dá)到和硬件實現(xiàn)一樣的低功耗性能,并只有非常低的面積消耗.
目標(biāo)捕獲系統(tǒng)流程及系統(tǒng)架構(gòu)
圖一 目標(biāo)捕獲系統(tǒng)流程圖
圖二 本項目系統(tǒng)架構(gòu)圖
FPGA的實現(xiàn)
1 算法簡介
(1)背景差分法算法背景差分[6]是利用當(dāng)前圖像與背景圖像差分來檢測出運動區(qū)域的一種技術(shù),一般能提供最完全的特征數(shù)據(jù),但對于動態(tài)場景的變化,如光照等事件的干擾特別敏感??紤]到攝像機移動緩慢,背景圖像變化比較遲緩,而運動對象相對于背景變化較快,這樣相對于變化較慢的背景圖像來說,可把運動對象看作是一個對背景圖像的隨機擾動。針對本裝置的設(shè)計要求,我們應(yīng)用Kalman濾波器[4]在零均值白噪聲的退化公式即漸消記憶遞歸最小二乘法,來更新和重建背景圖像,得到時域漸消遞歸最小二乘法的遞歸式
(2) 顏色濾波去陰影算法
如果圖像中具有運動陰影和分割碎塊,分割所得的圖像往往與實際目標(biāo)不符,產(chǎn)生欠分割或過分割的現(xiàn)象。由于陰影象素的灰度值在一個局部領(lǐng)域中變化不是很大,所以顏色濾波主要是構(gòu)造一個包含陰影的模板,再用這個模板與差分結(jié)果做邏輯與的操作,從而檢出陰影。本算法比較簡單,執(zhí)行速度快,處理中不需要區(qū)分陰影和半陰影,而且可以將移動陰影和背景中的陰影都檢出來,只是模板中的參數(shù)要根據(jù)現(xiàn)實情況和經(jīng)驗來定。由于靜止物體的陰影也是不動的,所以靜止目標(biāo)可以歸入背景中
(3)形心跟蹤算法
形心跟蹤是將整個跟蹤波門內(nèi)的圖像二值化,用求目標(biāo)形心的辦法獲得目標(biāo)位置參量。由于形心值是相對于目標(biāo)面積歸一化的值,因此形心值不受目標(biāo)面積、形狀以及灰度分布細(xì)節(jié)的限制。同時,形心跟蹤的計算頗為簡便。但是,形心跟蹤器受目標(biāo)的劇烈運動或目標(biāo)被遮擋的影響較為嚴(yán)重,瞄準(zhǔn)點漂移是遠(yuǎn)距離跟蹤系統(tǒng)的主要誤差之一。這也是我們采用目標(biāo)軌跡擬合算法來外推運動目標(biāo)位置,并與相關(guān)跟蹤法并行工作的原因。由于形心算法比較普及,本跟蹤裝置直接采用了改進(jìn)的形心跟蹤算法,用目標(biāo)峰值自適應(yīng)檢測算法使系統(tǒng)的計算可靠性和實時性達(dá)到最佳結(jié)合值。
2 算法的實現(xiàn)
1 差分機模型
圖三 差分機模型
從圖中可以看出 差分機分4步對比計算每個像素和顏色的差別,輸入這個模型的是紅綠藍(lán)的像素值 和 紅綠藍(lán)的顏色值以及閾值.當(dāng)閾值為16bits 寬的時候 那么每個輸入像素的值就是8bits寬.
二進(jìn)制的數(shù)據(jù)流作為此差分機的輸出用于構(gòu)建差分圖形.
四openfire 軟核架構(gòu)系統(tǒng)采用四個OpenFire core 作為自己的軟核 .Openfire是一個開源的軟核, 這種開放源碼的處理器和Xilinx的Microblaze 兼容,甚至可以使用大多數(shù)Xilinx?。牛模颂峁┑墓ぞ?。Openfire在cache和FSL總線等方面和Microblaze有著相同的配置 , 但是openfire允許改變數(shù)據(jù)通過的字節(jié)寬度,這正是我們目標(biāo)捕捉圖像處理算法所需要的.
圖四 四 OpenFire 軟核 架構(gòu)
圖五 改進(jìn)后的openfire處理器頂層圖
圖六 Openfire OPB 狀態(tài)機
圖七 Open fire OPB memory 系統(tǒng)圖
圖八 Open fire IOPB memory 系統(tǒng)圖
圖九 改進(jìn)OenFire FSL 數(shù)據(jù) I/O
部分代碼
1 FSL loopback test code
// This code is used by an OpenFire with all eight of its FSL ports connected
// in loopback to ensure that all ports are functional.
#include "fsl.h"
bool test_fsls(void);
int main(void) {
test_fsls();
while(1);
}
bool test_fsls(void) {
int data = 0;
putfsl(data+1,0);
getfsl(data,0);
putfsl(data+1,1);
getfsl(data,1);
putfsl(data+1,2);
getfsl(data,2);
putfsl(data+1,3);
getfsl(data,3);
putfsl(data+1,4);
getfsl(data,4);
putfsl(data+1,5);
getfsl(data,5);
putfsl(data+1,6);
getfsl(data,6);
putfsl(data+1,7);
getfsl(data,7);
return(data == 8);
}
2 IOPB / DOPB test code
#include "microblaze_0/include/xparameters.h"
#include "microblaze_0/include/xuartlite_l.h"
#include "microblaze_0/include/fsl.h"
extern void xil_printf(const char*, ...);
void outbyte(char c)
{
XUartLite_SendByte(STDOUT_BASEADDRESS, c);
}
char inbyte(void)
{
return XUartLite_RecvByte(STDIN_BASEADDRESS);
}
volatile unsigned int * timer = (unsigned int *)0x40060008;
volatile unsigned int * ddr = (unsigned int *)0x30000000;
unsigned int (*moved_summer)(const unsigned int * values, const int numvals);
unsigned int summer(const unsigned int * values, const int numvals)
{
int ctr;
unsigned int sum = 0;
for(ctr=0;ctr<numvals;ctr++)
sum += values[ctr];
return sum;
}
int main(void)
{
unsigned int starttime;
unsigned int endtime;
unsigned int timetaken;
int test_ctr;
int num_tests = 16;
int num_shifts = 4; // num_shifts = log2(num_tests)
int array_sz = 16;
int array_ctr;
int num_instructions = 100;
int instr_ctr;
unsigned int retval;
for(array_ctr = 0; array_ctr < array_sz; array_ctr++)
ddr[array_ctr] = array_ctr;
xil_printf("-- Starting Test (BRAM) --rn");
retval = 0;
timetaken = 0;
for(test_ctr=0;test_ctr<num_tests;test_ctr++)
{
starttime = timer[0];
retval = summer(ddr,array_sz);
endtime = timer[0];
timetaken += endtime - starttime;
}
xil_printf("-- Test Finished --rn");
xil_printf("RtVal: %drn", retval);
xil_printf("Taken: %drn", timetaken);
xil_printf("#Runs: %drn", num_tests);
for(test_ctr=0;test_ctr<num_shifts;test_ctr++) timetaken >>= 1;
xil_printf("Avg: %drn", timetaken);
((unsigned int *)moved_summer) = ddr + 0x1000;
for(instr_ctr=0; instr_ctr<num_instructions; instr_ctr++)
((unsigned int *)moved_summer)[instr_ctr] = ((unsigned int *)summer)[instr_ctr];
xil_printf("-- Starting Test (DDR) --rn");
retval = 0;
timetaken = 0;
for(test_ctr=0;test_ctr<num_tests;test_ctr++)
{
starttime = timer[0];
retval = moved_summer(ddr,array_sz);
endtime = timer[0];
timetaken += endtime - starttime;
}
xil_printf("-- Test Finished --rn");
xil_printf("RtVal: %drn", retval);
xil_printf("Taken: %drn", timetaken);
xil_printf("#Runs: %drn", num_tests);
for(test_ctr=0;test_ctr<num_shifts;test_ctr++) timetaken >>= 1;
xil_printf("Avg: %drn", timetaken);
while(1);
return(0);
}
3 OpenFire#1 C Code
unsigned mostly_colors;
unsigned thresh_desired;
unsigned char * rdes = &(((unsigned char *)&mostly_colors)[0]);
unsigned char * r = &(((unsigned char *)&mostly_colors)[1]);
unsigned char * g = &(((unsigned char *)&mostly_colors)[2]);
unsigned char * b = &(((unsigned char *)&mostly_colors)[3]);
unsigned short * thresh = &(((unsigned short *)&thresh_desired)[0]);
unsigned char * gdes = &(((unsigned char *)&thresh_desired)[2]);
unsigned char * bdes = &(((unsigned char *)&thresh_desired)[3]);
unsigned yx_data, sum;
while(1)
{
getfsl(mostly_colors,0);
getfsl(thresh_desired,1);
getfsl(yx_data,2);
sum = ((*r) - (*rdes)) * ((*r) - (*rdes)) +
((*g) - (*gdes)) * ((*g) - (*gdes)) +
((*b) - (*bdes)) * ((*b) - (*bdes));
if(sum < (*thresh))
{
putfsl(yx_data,0);
putfsl(yx_data,1);
}
else
{
putfsl(0,0);
putfsl(0,1);
}
}
需要的開發(fā)平臺
硬件平臺
軟件平臺
PC機
Linux
QT
Virtex-II Pro開發(fā)板
Matlab
ISE
ModelSim
EDK