王 剛,朱明清,石 磊
(黑龍江省科學(xué)院智能制造研究所,黑龍江 哈爾濱 150090)
隨著科學(xué)技術(shù)的發(fā)展,激光測量方法廣泛應(yīng)用非接觸測量[1]、物體表面缺陷檢測[2],目標(biāo)跟蹤[3]等領(lǐng)域,應(yīng)用光學(xué)激光測量方法原理時,向目標(biāo)物體投射激光需要精確提取數(shù)字圖像中激光光斑信息,為獲取目標(biāo)物體的關(guān)鍵步驟,那么作為激光光斑中心定位[4-6]在光學(xué)測量系統(tǒng)中占有重要的地位,當(dāng)激光光斑點通過CCD或CMOS圖像傳感器采集時,受到環(huán)境中各種干擾及其采集后出現(xiàn)多點坐標(biāo),在實際使用背景時,如激光三角法[7]、激光準(zhǔn)直儀、共焦顯微測量法、激光參數(shù)測定等光學(xué)測量中,需要準(zhǔn)確提取激光光斑中心圖像坐標(biāo)。
本文就是針對于激光三角法中,向被測物體投射激光源后,通過COMS采集激光光斑圖像,通過FPGA硬件系統(tǒng)設(shè)計,提取出激光光斑中心坐標(biāo);為了驗證所選用的算法正確性,首先通過計算機(jī)軟件驗證,將得到的結(jié)果與FPGA 仿真結(jié)果對比,數(shù)據(jù)相同的情況,將應(yīng)用FPGA 硬件實現(xiàn)提取光斑坐標(biāo),實現(xiàn)激光光斑位置的算法移植到硬件中,利用FPGA的并行運算能力,使得測量速度得到提高,實時的應(yīng)用在實際生產(chǎn)中。
為了完成本文的研究內(nèi)容,即通過FPGA 實現(xiàn)激光光斑中心定位的研究設(shè)計;激光光斑中心是將激光照射到物體表面,通過圖像傳感器采集圖像信息,再通過算法處理實現(xiàn)其算法完成中心坐標(biāo)的提取,由于FPGA 是一種硬件描述語言實現(xiàn)的邏輯,要完成上述過程直接在FPGA中去算法驗證實現(xiàn)會變得更加復(fù)雜;對于FPGA無論在運行還是仿真過程中看到的就是一組數(shù)據(jù)或是一組時序波形,不能像二維圖片直觀的表達(dá)所要得到的信息,而且在越復(fù)雜的算法中越難直觀得到結(jié)果,出現(xiàn)問題也不利于問題的分析,綜上所述,文章中采用軟件通過opencv 實現(xiàn)激光中心定位的算法驗證,而在實現(xiàn)過程中采用的函數(shù)語言能夠方便轉(zhuǎn)化成verilog HDL語言的形式去實現(xiàn),最后能夠通過FPGA硬件描述語言實現(xiàn)。
系統(tǒng)設(shè)計方案圖如圖1,首先計算機(jī)通過采集系統(tǒng)采集到激光光斑的圖像,并保存到計算機(jī)中,其次來通過opencv 算法驗證,最后還得將圖像數(shù)據(jù)轉(zhuǎn)化成圖像灰度數(shù)據(jù)存儲于文本文件中,便于在modelsim中讀取灰度數(shù)據(jù);FPGA的仿真采用modelsim軟件完成,但是此軟件不能直接讀取圖像數(shù)據(jù),只能讀取二進(jìn)制或是十六進(jìn)制的數(shù)據(jù),為了完成此功能,可以采用c++語言將圖像轉(zhuǎn)化成灰度數(shù)據(jù),再通過軟件直接讀取數(shù)據(jù)。
圖1 系統(tǒng)設(shè)計方案圖
通過灰度圖像提取中心的方法有質(zhì)心法[8]、灰度重心法[9],區(qū)別在于一個是對二值圖像的運算,一個是對灰度圖像直接處理的方法。
1) 質(zhì)心法
用于對二值圖像[10]的中心提取處理方法,可理解為灰度重心法的特例;質(zhì)心法就是通過圖像閾值區(qū)分背景,是待測信息的一階矩來獲取質(zhì)心的方法,橫坐標(biāo)為二值化的圖像將值為‘1’的所有i的數(shù)值相加,再除以值為‘1’的總和數(shù),縱坐標(biāo)為二值化的圖像將值為‘1’的所有j 的數(shù)值相加,再除以值為‘1’的總和數(shù),其公式如下:
其中:g(i,j)為f(i,j)的二值圖像值,
M為圖像的行數(shù),
N為圖像的列數(shù)。
2) 灰度重心法
灰度重心法不需要對圖像二值化處理,它將光斑區(qū)域內(nèi)每一像素的灰度值當(dāng)作該點的“質(zhì)量”,橫坐標(biāo)為圖像坐標(biāo)中所有u值乘以對應(yīng)灰度值累加,再除所有灰度值的總和數(shù),縱坐標(biāo)為圖像坐標(biāo)中所有v值乘以對應(yīng)灰度值累加,再除所有灰度值的總和數(shù),其求光斑的公式為:
其中:f(u,v)為圖像的灰度值,
M為圖像的行數(shù),
N為圖像的列數(shù)。
在實際拍攝獲取激光光斑圖像時,由于是主動投射激光源的方式,背景信息與激光光斑信息具有明顯的差異,且有用信息都集中在最大灰度數(shù)據(jù)部分,通過對一般圖像處理數(shù)據(jù)的過程,首先將采集到的數(shù)據(jù)進(jìn)行濾波處理,在進(jìn)行算法運算;但是在FPGA中實現(xiàn)任何一種算法都是對硬件邏輯的負(fù)擔(dān),增加硬件描述語言的難度,同時占用大量的邏輯單元,影響整體的測量速度,減弱FPGA并行運行的能力,而通過質(zhì)心法與灰度重心法相比較,質(zhì)心法運算使得硬件運算簡單,占用寄存器的空間也相對較小,且硬件在讀取數(shù)據(jù)的過程中就可將圖像二值化,充分利用了FPGA流水線運行,達(dá)到更高質(zhì)量的使用。
根據(jù)上面分析,激光光斑都集中在灰度最大值部分,可以直接運用質(zhì)心法計算激光光斑中心坐標(biāo),如圖2所示,軟件系統(tǒng)的流程圖,首先程序進(jìn)入主函數(shù),接著讀取原始灰度圖像,通過P參數(shù)法求取灰度圖像的閾值,并輸出二值圖像;根據(jù)二值圖像帶入質(zhì)心法公式,求取橫、縱中心坐標(biāo);最后要將原始灰度圖像輸出txt文件,為modelsim仿真做準(zhǔn)備。
圖2 Visual軟件流程圖
對于open cv是專門用于處理圖像的函數(shù)庫,但是設(shè)計函數(shù)時要能夠方便于硬件描述語言的轉(zhuǎn)化,根據(jù)這個思想首先設(shè)計P參數(shù)法求取閾值,得到二值圖像的函數(shù),接著運用質(zhì)心法求橫縱中心坐標(biāo)的函數(shù),最后輸出灰度圖像的txt文件函數(shù)。
1) P 參數(shù)法獲得二值圖像函數(shù)為void gray2ot(Mat&inputImg,Mat&outputImg);運用P 參數(shù)法求P 值時,verilog HDL語言沒有對浮點數(shù)處理的方法,需要設(shè)計浮點數(shù)處理,再硬件對寄存器的位寬也有指定,為防止溢出,減少硬件空間占用,將所有像素點數(shù)縮小處理,總像素點數(shù)為1310720移動四位數(shù)據(jù)縮小處理,這樣使得P參數(shù)得到為整數(shù),避免小數(shù)的出現(xiàn),在運算中實在允許的誤差范圍內(nèi)。
2) 質(zhì)心法求取中心坐標(biāo)函數(shù)為void sumMat(Mat&inputImg,double x,double y);求取中心坐標(biāo)主要將公式中的參量轉(zhuǎn)化成程序來運算,得到要運算的值,在c 語言中主要就是為for循環(huán)遍歷圖像。
3) 將灰度圖像輸出txt 文件函數(shù)為int WriteData(string fileName,cv::Mat&matData);在設(shè)計此函數(shù)時輸出的圖像灰度數(shù)據(jù)為十六進(jìn)制數(shù)字,并且每個數(shù)據(jù)為一行,modelsim 讀取txt 文本數(shù)據(jù)時,只支持這樣的文件格式,如果按照數(shù)組形式輸出,數(shù)據(jù)是不能讀到相應(yīng)的寄存器中。
根據(jù)以上P參數(shù)法獲得二值圖像函數(shù)的設(shè)計,分別通過調(diào)整攝像頭的鏡頭,使得進(jìn)光不同,得到圖3的圖像與圖4的圖像,分別在程序中讀取圖3激光光斑背景為黑色背景與圖4激光光斑背景為灰度背景,得到閾值都是128,如圖5P 參數(shù)法閾值,兩幅灰度圖像得到二值圖像為圖6激光光斑二值圖。
圖3 激光光斑背景為黑色背景
圖4 激光光斑背景為灰度背景
圖5 P參數(shù)法閾值
圖6 激光光斑二值圖
將上一步得到的二值圖像通過質(zhì)心法求取中心坐標(biāo)函數(shù)運算得到圖7質(zhì)心法中心坐標(biāo),對應(yīng)橫坐標(biāo)公式中所有激光光斑點數(shù)坐標(biāo)i的和為177705,縱坐標(biāo)公式中所有激光光斑點數(shù)坐標(biāo)j 的和為1.4464*10^6,總的激光光斑點數(shù)為1326,最后得到的橫縱坐標(biāo)為(134,1090)。
圖7 質(zhì)心法中心坐標(biāo)
對于頂層模塊的設(shè)計思路是通過考慮實際CCD 或CMOS采集數(shù)據(jù)過程,實際圖像采集是利用時鐘、行和場信號共同完成數(shù)據(jù)的采集,在行、場信號有效周期內(nèi),每一個時鐘讀取一個像素的數(shù)據(jù),那么根據(jù)這樣的方法,只要在利用modelsim仿真時,仿真文件能夠根據(jù)時鐘讀取圖像中每一個像素數(shù)據(jù)即可,仿真文件需要從測試文件中讀取到數(shù)據(jù),實際測試文件中的數(shù)據(jù)是事先存到寄存器中的,可以采用讀取RAM的方式完成,給出地址信號,利用時鐘信號產(chǎn)生地址,每一個地址對應(yīng)一個數(shù)據(jù),保證數(shù)據(jù)的初始過程,利用時序電路設(shè)計時還需設(shè)計復(fù)位信號,最后根據(jù)激光光斑中心定位算法從模塊輸出圖像坐標(biāo)下的橫、縱坐標(biāo),設(shè)計的端口如下。
module CentralDistant(input clk,
input nrst,
input [7:0]data,
output [20:0]addr,
output [9:0]xdata,
output [10:0]ydata
);
……
endmodule
根據(jù)以上端口模塊的信號設(shè)計后,還需要考慮位寬,而在上面已經(jīng)定義出來,對于時鐘、復(fù)位信號是1位;數(shù)據(jù)是讀取0~255的灰度數(shù)據(jù),那么對應(yīng)的數(shù)據(jù)位寬是8位;讀取原始圖像的大小是1024*1280大小的圖像,進(jìn)而得出總的數(shù)據(jù)個數(shù)為1310720,對應(yīng)的二進(jìn)制數(shù)應(yīng)為21 位,故地址位數(shù)為21位;根據(jù)圖像的大小即可得到橫、縱坐標(biāo)的位寬分別為10位和11位。
根據(jù)上一節(jié)對待測模塊端口的設(shè)計,將對應(yīng)的輸入信號變成reg類型,輸出信號變成wire類型;同時定義時間尺度,時延單位為1ns,時延精度為1ps;同時調(diào)用待測模塊CentralDistant,測試模塊端口如下。
'timescale 1ns/100ps
module tester;
reg clk;
reg nrst;
wire [7:0]data;
wire [20:0]addr;
wire [9:0]xdata;
wire [10:0]ydata;
CentralDistant u(clk,nrst,addr,data,xdata,ydata);
endmodule
通過modulesim 仿真過程為軟件波形圖仿真,沒有實際的硬件,modulesim 中有系統(tǒng)函數(shù)指令$readmemh讀取文本文件數(shù)據(jù),那么通過Visual Studio 讀取激光光斑的圖像,利用函數(shù)轉(zhuǎn)換成十六進(jìn)制數(shù)文本文件。對于讀取的數(shù)據(jù)存儲到寄存中,寄存器的位寬為數(shù)據(jù)寬度,寄存器的數(shù)據(jù)深度為地址總數(shù),即可定義位21位,讀取過程在初始化過程中完成即可,保證測試程序執(zhí)行時,寄存器中已經(jīng)存在圖像灰度數(shù)據(jù),硬件描述部分代碼如下。
parameter wordsize=7;
parameter arraysize=1310719;
Reg[wordsize:0]admin_cq_entry_table[0:arraysize];
integer i;
initial begin
$readmemh("data.txt",admin_cq_entry_table);
for(i=1230042;i< 1230052;i=1+i)
$display("admin_cq_entry_table[%d]=%h",i,admin_cq_entry_table[i]);
end
測試模塊的作用就是產(chǎn)生對應(yīng)的輸入信號,及其提供需要的灰度數(shù)據(jù),上一步已經(jīng)將所需要的數(shù)據(jù)讀取到寄存admin_cq_entry_table 中,接下來控制對應(yīng)于端口設(shè)計的時鐘、復(fù)位信號,將數(shù)據(jù)按照地址給到數(shù)據(jù)端口即可,硬件描述語言部分代碼如下。
always repeat(1000)#2 clk=~clk;//
initial
begin
clk=0;
nrst=0;
#3 nrst=1;
#3 nrst=0;
#3 nrst=1;
end
assign data=admin_cq_entry_table[addr];
硬件描述語言并行運行的特點,圖像灰度數(shù)據(jù)是每個像素依次傳輸,根據(jù)傳輸過程中就可以進(jìn)行處理,但是硬件執(zhí)行也有先后順序,所以將Verilog HDL 語言描述分成五步,第一步為初始化寄存器,主要是以初始化作為灰度直方圖寄存器的數(shù)據(jù),與C 語言for 循環(huán)不同,硬件采用時序電路設(shè)計,做循環(huán)的本質(zhì)就是在執(zhí)行時鐘周期,利用多個時鐘周期完成對直方圖寄存器初始化;第二步做灰度直方圖中灰度統(tǒng)計,計算出各個灰度級上灰度個數(shù),為下一步P 參數(shù)法求閾值做好統(tǒng)計;第三步為P 參數(shù)法求閾值,通過從高位累計灰度直方圖寄存器的值,到達(dá)設(shè)定的P 值后,結(jié)束運算,得到閾值;第四步為圖像二值化,并計算大于閾值的數(shù)據(jù)個數(shù),及其橫、縱坐標(biāo)的值,為下一步計算做后數(shù)據(jù)準(zhǔn)備;第五步為計算橫、縱坐標(biāo)值,并復(fù)位相應(yīng)寄存器,并使硬件能夠返回第一步。
對于圖像灰度數(shù)據(jù)在程序代碼中,都按照二維數(shù)組的方式去進(jìn)行運算,而在測試文件中讀取的到的圖像數(shù)據(jù)為一個8位的1310720個寄存器,那么需要按照行場的方式轉(zhuǎn)換,將橫坐標(biāo)乘以列數(shù)1280,再加上縱坐標(biāo)即可得到對應(yīng)的數(shù)據(jù)地址;同時在硬件描述語言中,利用時序電路的特點,在有效的周期內(nèi),按照每個時鐘周期產(chǎn)生行場的變化,主要部分Verilog HDL語言如下。
assign addr=xcoordinate*11'd1280+ycoordinate;
if(xcoordinate>=10'd1023 || flag)
begin
xcoordinate<=10'd 0;
ycoordinate<=11'd 0;
end
else if(ycoordinate>=11'd1279)
begin
xcoordinate<=xcoordinate+1'b 1;
ycoordinate<=11'd 0;
end
else
ycoordinate<=ycoordinate+1'b 1;
圖8modelsim仿真圖所示,按照上面所述xdata、ydata為求取的橫縱坐標(biāo),其運算的結(jié)果為(134,1090),與軟件中運算取得整數(shù)結(jié)果相同;在仿真中,sumx 寄存器值為177705,sumy寄存器值為1446395,sum寄存器值為1326,而在軟件中計算得值依次為:177705,1.4464*10^6,1326,兩種方式驗證數(shù)據(jù)相同,其他運算的數(shù)據(jù)兩者也都完全一致,即設(shè)計的并行運算提取光斑中心坐標(biāo)的方法能夠在硬件上使用。
圖8 modelsim仿真圖
綜上所述,F(xiàn)PGA 中是能夠?qū)崿F(xiàn)激光光斑中心坐標(biāo)的提取,但是其中還是存在著浮點數(shù)的問題,接下來研究浮點數(shù)的方式可以通過兩種方法,一是擴(kuò)大寄存器的位寬,使其能夠達(dá)到最大數(shù)據(jù),在除法運算時要繼續(xù)擴(kuò)大位寬保證小數(shù)點后面的位數(shù);二是在FPGA 中做32 位浮點數(shù)的運算,完成整數(shù)與浮點數(shù)之間的轉(zhuǎn)化,在浮點數(shù)下計算;只要能夠保證運算精度的情況,在實際使用中,那種方式都可以,主要還要參考FPGA 的運算速度與使用面積,只要增加功能,必然影響FPGA 的性能,需要綜合去考慮。