第三節(jié) 測量3.3.1 簡單的啰嗦幾十句所謂的測量,主要是測量出物理尺寸,就是我們現(xiàn)實中所說的尺寸。畢竟算出像素尺寸實在是不是太難。Halcon里面的物理尺寸測量分1d,2d,3d測量,作為入門書籍我們這兒只講1d的,就是長度測量。比如咱們的標(biāo)定板長度的測量。有沒有很想學(xué)?哈哈…… 3.3.2 言歸正傳圖 3-3-2-1 如上圖(3-3-2-1),單擊助手里面的第四個選項'Measure'。會彈出下圖(3-3-3-2),在輸入欄有兩個參數(shù)需要我們來填,第一個是第一紅框里面的,待測量圖片的來源,可以選擇你已經(jīng)拍好的照片,就是圖像文件,單擊那一行后面小框框可以選擇圖片路徑,下一行是通過圖像采集助手,就是相機采集圖片來測量,如果你還沒有打開圖像采集助手,一選中就會自動彈出圖像采集助手來幫你選擇相機,本章第一節(jié)剛好你學(xué)了連接相機,怎么利用圖像采集助手實在是難不倒你。如果你選中后面的'實時采集',就可以實時采集每一張圖片來進(jìn)行測量了。一切配置好后,下面一個框內(nèi)是要相機的內(nèi)參外參了,上一節(jié)剛好學(xué)的標(biāo)定。希望你有保存。'.cal'和'.dat'剛好就對應(yīng)了兩個參數(shù)保存文件的格式。還是點擊最后面的小框添加。 圖 3-2-2-2 一切配置好后,就可以進(jìn)入第二頁選項卡如下圖:此時你halcon的圖像窗口應(yīng)該是在實時顯示的圖片。把標(biāo)定板放進(jìn)視野中,如下圖(3-3-2-3)。 圖 3-3-2-3 圖 3-3-2-4 然后選擇上圖(3-3-2-4)中最上你們的小方框,這是畫直線的功能,到halcon圖像窗口中畫一條測量的線,保證這條線穿過要測量的物體的兩個邊緣,如下圖(3-3-2-5): 圖 3-3-2-5 通常情況下,還是要調(diào)整下上圖(3-3-2-4)中紅框框內(nèi)的三種參數(shù):最小邊緣幅度,意思是說halcon自己沿著線路找邊緣,當(dāng)某個地方灰度值差大于這個幅度的時候就認(rèn)為它為邊緣。平滑,是指對圖片進(jìn)行平滑,如果你的圖片噪聲多,干擾多,則需要平滑。ROI寬,其實halcon測量是在一個矩形ROI里面測量,你畫的直線相當(dāng)于這個矩形的長邊中心軸線,這根線的長度就是這個矩形的長了,那這個矩形的寬就取決于你在這兒設(shè)置的ROI的寬了,而且halcon會在直線的邊緣上顯示你的ROI的寬,讓你看到它找出來的邊緣,所以我通常喜歡把ROI寬設(shè)置大一點,如下圖(3-3-2-6): 圖 3-3-2-6 看圖中的垂直的綠線,它顯示的就是矩形ROI的寬了,你也可以通過這個看看邊緣是否找到,找到的是否準(zhǔn)確。第四行的是插值方法,(具體的插值方法簡介,詳見本節(jié)TIPS 1)我建議選第二種吧。 接下來是邊緣選擇里面的變換和位置,如下圖(3-3-2-7): 圖 3-3-2-7 變換里面有positive和negative,positive是指灰度值由暗到亮的邊緣,negative是指灰度值由亮到暗的邊緣,你自己去挨個選擇下,然后看看效果就知道了。All就是都選的意思咯。下面的位置里面還有first和last,這個實在不用我去啰嗦什么是first的位置什么是last的位置了吧。善意提醒下,你畫的那條線是有方向的,由起始位置指向結(jié)束位置。咱們這就兩個都選all吧。再往下的那些就是些輔助功能了,有興趣的自己看下也能一目了然,不用講解的。選項卡第三欄是模糊,對圖像進(jìn)行各種模糊的,咱們初級的用不上。直接跳過到結(jié)果欄: 圖 3-3-2-7 是的,結(jié)果已經(jīng)出來啦!如上圖(3-3-2-7),單位在右上角是mm。因為有兩個邊緣,所以有兩行數(shù)據(jù),每一行分別是每個邊緣點的坐標(biāo)和幅度,這個幅度是指,沿著你畫的測量直線的方向,每個邊緣點左右兩邊的灰度差。本例中第1個點是由黑色背景到白色標(biāo)定板,所以灰度值上升了39.7639,第2個點是由白色標(biāo)定板重新進(jìn)入黑色背景,所以幅度變化就是負(fù)值了。那為什么兩個幅值的絕對值不一樣呢?因為我打光不均勻唄~笨!下面一個就是你最關(guān)注的的距離了,表示距離下一個邊緣點的距離,因為只有兩個點,所以第二個點的距離參數(shù)就沒有了。那么這個70.526mm就是兩個點之間的物理距離了,也就是這塊標(biāo)定板中間白色部分的寬度。測的準(zhǔn)不準(zhǔn)呢?你自己看吧!如下圖(3-3-2-8)。(友情提示:如果你的數(shù)據(jù)一直在跳動,就說明你一開始點擊了實時采集,所以它就在一直對新采集的圖片進(jìn)行測量,我的就是這樣。) 圖 3-3-2-8 到這兒,這個測量咱們算是結(jié)束啦。感興趣的話可以繼續(xù)拿一些其它東西來測測,看看準(zhǔn)不準(zhǔn)。但是如果要寫代碼怎么寫呢?讓我們在選項卡代碼生成里面點擊'插入代碼'吧。代碼如下圖(3-3-2-9)。 圖 3-3-2-9 別被這一頁紙的陌生代碼嚇到了,其實關(guān)鍵代碼沒幾步,很多都是賦值和重復(fù),讓我來一點點的分析給你聽。首先是打開相機,接下來是相機的內(nèi)參外參賦值,這些你都有的,也都會的。然后設(shè)置了邊緣最小幅度,就是之前在助手里面第二頁選項卡邊緣下設(shè)置的第一個參數(shù)。然后是ROI的寬的一半,看我上面截圖里面是60,這兒它設(shè)置成30了,當(dāng)然自有妙用,五分鐘后你就知道了。接下來是算子: set_system ('int_zooming', 'true'):這個算子是設(shè)置系統(tǒng)的意思,怎么個設(shè)置法?第一個參數(shù)就是你要設(shè)置的系統(tǒng)參數(shù)名,第二個就是系統(tǒng)參數(shù)值,相當(dāng)于一個是name,一個是value。本例中這個參數(shù)的意思就是說,你如果選擇了true,那么對圖像縮放的時候所有的數(shù)值都用整數(shù)來算,減少運算量嘛。 接下來四行代碼就是畫那根線的起始終止點的坐標(biāo)了。不要被它的命名嚇唬到了,其實就是兩個點的縱橫坐標(biāo),再接下來的七行又是什么呢,就是測量用的那個矩形了。還記得我說的其實halcon里面的測量是在一個矩形內(nèi)嗎?那你還記得如果生成一個帶角度的矩形需要哪些參數(shù)嗎?就是gen_rectangele2()后面的參數(shù)啦。需要矩形的中心點坐標(biāo)(兩個參數(shù)),矩形的角度(一個參數(shù)),矩形的長寬的一半(兩個參數(shù))。一共五個參數(shù)。分別對應(yīng)接下來七行里面的17,18,21,22,23行。19,20行是用來求角度phi的。因為這個矩形的角度你又沒設(shè)置,只好自己算了,拿你畫的那條線的起始點的縱坐標(biāo)做差,橫坐標(biāo)再做差,然后atan()就可以了,就是21行的算子啦。這樣分析是不是好懂很多。。有了這些參數(shù)就要畫測量的矩形了! gen_measure_rectangle2(TmpCtrl_Row,TmpCtrl_Column,TmpCtrl_Phi,TmpCtrl_Len1, TmpCtrl_Len2, 2588, 1940, 'bilinear', MsrHandle_Measure_01_0):這才是本例第一個靈魂算子,就是生成一個測量用的2型矩形。第一第二個參數(shù)就是矩形中心點的坐標(biāo)啦,第三個參數(shù)就是矩形的角度,第四第五個參數(shù)就是這個矩形長短邊的二分之一長度啦。第六第七個參數(shù)就是整張圖片的寬高,第八個參數(shù)是插值方法,本例我選的是雙線性插值法;第九個參數(shù)就是生成這個矩形所存的句柄。 生成這個測量的矩形后,就是要開始測量了嘛!可是我們好像還沒有圖片。。。所以接下來肯定是抓取圖片啦,如下圖(3-3-2-10): 圖 3-3-2-10 因為我在助手第一頁選擇了實時獲取,所以這兒給加了一個死循環(huán)while(true)。不要在意這些細(xì)節(jié)。接著看里面的循環(huán)體: grab_image (Image, AcqHandle):抓取圖片,屬于同步獲取。第一個參數(shù)是抓到的圖片,第二個參數(shù)是抓圖片的相機的句柄。這個算子很簡單了,沒什么好講的。下面一個是重點: measure_pos(Image,MsrHandle_Measure_01_0,1,AmplitudeThreshold,'all','all',Row_Measure_01_0,Column_Measure_01_0,Amplitude_Measure_01_0,Distance_Measure_01_0):提取垂直于矩形的邊緣并測量。這個算子參數(shù)本來就多,halcon還給每個參數(shù)起這么長的名字。實在是醉了,也不怕嚇到我的讀者……,話說回來,以后我們會遇到參數(shù)更多的算子的。下面我來說說每個參數(shù)的意思吧,第一個參數(shù)就是要測量的圖像啦;第二個參數(shù)是測量矩形的句柄;就是上一個算子畫出來的那個矩形啦;第三個參數(shù)是高斯平滑系數(shù),這個在助手里面也有設(shè)置;第四個參數(shù)是最小邊緣幅度,開頭賦值的那個,在這兒用到了;第五個參數(shù)是轉(zhuǎn)換,對應(yīng)的是第二個選項卡下面邊緣里面的那個轉(zhuǎn)換,我們選all的還記得嗎?所以第六個參數(shù)就是剩下的那個位置參數(shù)啦!也是all;第七第八第九第十個參數(shù)就是分別對應(yīng)結(jié)果選項卡里面輸出的內(nèi)容,分別為邊緣點的縱、橫坐標(biāo),幅度變化值,以及距離。但是!這些都是相機的像素坐標(biāo),以及像素距離,因為我們的相機的內(nèi)參和外參還沒有告訴算子呢。所以我們還需要接下來一步: image_points_to_world_plane(CameraParameters,CameraPose,Row_Measure_01_0,Column_Measure_01_0,0.001,Column_World_Measure_01_0,Row_World_Measure_01_0):啥意思來著?上一節(jié)說過!當(dāng)時可能有點不知道怎么用,現(xiàn)在是不是有恍然大悟的趕腳?也算是學(xué)以致用了。其中scale參數(shù)0.001就是mm的意思了唄。這個算子在這兒的作用就是把上面測得的邊緣點縱橫坐標(biāo)轉(zhuǎn)換成空間物理坐標(biāo)。這些轉(zhuǎn)了,再利用歐幾里得距離公式,就可以求出來實際距離了,實在是不難: 思路是很簡單,但是halcon把它整的有點小復(fù)雜,顯擺了一個算子,加了一個if判斷邏輯。判斷求出來的物理邊緣點的縱坐標(biāo)的個數(shù),肯定是2個啦,因為兩個邊緣點嘛。然后: tuple_select_range(Row_World_Measure_01_0,0,TmpCtrl_Length-2,TmpCtrl_RowFrom):這個算子的意思是從一個數(shù)組里面篩選元素,1個或多個都行。第一個參數(shù)是數(shù)組,第二個參數(shù),第三個參數(shù)是篩選的元素是從數(shù)組的序號幾到幾,第四個參數(shù)是輸出。本例中,就是提取世界坐標(biāo)下縱坐標(biāo)數(shù)組(Row_World_Measure_01_0)里面從第0個到第0(TmpCtrl_Length - 2=0)個元素,那就是第0個了唄。這樣的算子重復(fù)了四次,還有三次分別是世界坐標(biāo)系下橫坐標(biāo)數(shù)組里面從第0個到第0個元素,世界坐標(biāo)系下縱坐標(biāo)數(shù)組里面從第1個到第1(TmpCtrl_Length - 1=1)個元素,世界坐標(biāo)系下橫坐標(biāo)參數(shù)里面從第1個到第1個元素。說白了就是提取出世界坐標(biāo)系下兩個坐標(biāo)點的橫縱坐標(biāo)。然后歐幾里得: distance_pp(TmpCtrl_RowFrom,TmpCtrl_ColumnFrom,TmpCtrl_RowTo,TmpCtrl_ColumnTo, Distance_World_Measure_01_0):求點與點之間的距離。pp的意思就是point-point。前面四個參數(shù)就是兩個點的橫縱坐標(biāo),第五個參數(shù)是輸出,即距離。這是一個數(shù)學(xué)公式。(更多distance相關(guān)的算子詳見本節(jié) TIPS 2) 這個輸出就是結(jié)果啦,最后就是: close_measure (MsrHandle_Measure_01_0):關(guān)掉測量對象。畢竟做事有始有終嘛! 至此,一次完整的測量,從使用助手開始,到代碼的學(xué)習(xí)都算是全套完成了?,F(xiàn)在如果有一個生產(chǎn)標(biāo)定板的生產(chǎn)線,需要你在產(chǎn)線最后加一套視覺系統(tǒng),檢測標(biāo)定板的長寬和各個圓圓心之間的距離是否符合要求。你會怎么做?從相機、鏡頭、光源的選型開始,平臺怎么搭建,怎么打光。一切就緒后,軟件部分怎么寫?相機的連接,標(biāo)定,測量等等全套。最后再轉(zhuǎn)成C#代碼生成exe執(zhí)行文件。雖然這個項目暫時不能給你,但是你可以從頭到尾想一下。如果全套你都能做,那么我寫這本書的目的也算是達(dá)到很大一部分了。助手總共有5個,還有兩個一個是模板匹配,一個是OCR的識別。這兩個我就不講了。模板匹配的例程我會在后面有講解,明白了例程,知道了什么是模板匹配,你再回頭弄這個助手,簡直不要太容易。所以就算我寫,那時候你也懶得看了。 還是回到本節(jié),大家一起復(fù)習(xí)下本節(jié)的算子: 1)set_system ('int_zooming', 'true'): 2)gen_measure_rectangle2(TmpCtrl_Row,TmpCtrl_Column, TmpCtrl_Phi, TmpCtrl_Len1, TmpCtrl_Len2, 2588, 1940, 'bilinear', MsrHandle_Measure_01_0): 3)grab_image (Image, AcqHandle): 4)measure_pos(Image,MsrHandle_Measure_01_0,1,AmplitudeThreshold,'all','all',Row_Measure_01_0,Column_Measure_01_0,Amplitude_Measure_01_0,Distance_Measure_01_0): 5)image_points_to_world_plane(CameraParameters,CameraPose,Row_Measure_01_0,Column_Measure_01_0,0.001,Column_World_Measure_01_0,Row_World_Measure_01_0): 6)tuple_select_range(Row_World_Measure_01_0,0,TmpCtrl_Length-2,TmpCtrl_RowFrom): 7)distance_pp(TmpCtrl_RowFrom,TmpCtrl_ColumnFrom,TmpCtrl_RowTo,TmpCtrl_ColumnTo, Distance_World_Measure_01_0): 8)close_measure (MsrHandle_Measure_01_0): 本節(jié)TIPS: 1) ,如圖,點開這個下拉窗口,會發(fā)現(xiàn)插值方法有三種:nearest_neighbor,bilinear和bicubic。先解釋下什么叫插值,就是說圖片在各種仿射變換或者其它的變換中,會遇到某些像素的像素值缺失的情況,這個時候得補充上,比如你把一個50*50的圖像擴大成60*60的圖像,那么每一行每一列就都會多出來十個像素,一共多出來3600-2500=1100個像素,這么多像素要給它賦值呀,這個賦值的方法就叫做插值或者內(nèi)插,插值常用的就是上面的三種方法。第一種(nearest_neighbor)是最近鄰域插值法:差不多意思就是找到需要賦值的像素點最鄰近的點,把它的像素賦值給這個新像素。這種方法速度最快,但是缺陷最明顯:某些直邊緣會嚴(yán)重失真。第二種(bilinear)是雙線性插值法:它是用新像素四個最鄰近的點來估計這個新像素點的灰度值,公式如下: Gray(x,y)=ax+by+cxy+d a,b,c,d四個參數(shù)剛好可以用鄰近四個點帶進(jìn)去聯(lián)立一個4維方程組,然后求出來。這種方法會比第一種方法好很多,沒有太明顯的bug,但是運算量也上去了。效果第二好,速度第二快吧。第三種(bicubic)是雙三次插值法:根據(jù)16個最鄰近的點的灰度值來估算該像素點的灰度值。厲害了吧!公式也很變態(tài): 對的,所以你平時是不用管它是怎么算的,只要記住它用了16個點來估算,效果三種方法里面最好的,但是運算量最大,耗時最長。 2)在halcon里面F1,左上角搜索欄輸入distance,如下圖: 圖 3-3-2-11 半頁紙的distance。這些都是求距離的算子,復(fù)雜的看不懂的暫時也不用弄懂,但是這種學(xué)習(xí)方法我們要學(xué)會,你看到一個重要的單詞,覺得還會有其它的相關(guān)算子的時候,就可以到這里搜索出來看看。比如tuple,gen,get,contour,read,write等等。我們再回到這個distance。Distance后面掛的c是contour(輪廓),l是line(直線),r是region(區(qū)域),p是point(點),s是(line segment)線段。那很多算子就很好理解了,比如distance_rr_min就是兩個region之間的最小距離。那distance_rr什么意思呢?哈哈,自己點進(jìn)去看吧! |
|
來自: taotao_2016 > 《幾何》