The Basics of Measure Objects
2.1 the process of 1D Edge extraction

Then, the mean gray value along each line of projection is calculated. The sequence of these mean values
is called the profile
簡單的說 是以 profile Line 為基准 對profile Line 垂直方向上的 灰度值取平均。這一系列的平均灰度值組成profile。
如果以profile Line 為基准,它的垂線不是 水平或者數值的時候 如上圖 (a)(b) ,就需要一個插值操作。目前halcon支持的有'nearest_neighbor', 'bilinear', 'bicubic' 。就如同我們對一副圖像進行縮放或者旋轉的時候為了盡可能的保證處理后的圖像保持原來的細節需要進行插值一樣。
我們用測量助手的時候 其中有一個輪廓線的呈現,就是平均灰度值組成的結果。
如下圖:

現在以gen_measure_rectangle2( : : Row, Column, Phi, Length1, Length2, Width, Height, Interpolation : MeasureHandle) 為例說明各參數作用。
ROW : 測量矩形的Y 中心
COL: 測量矩形的X中心
PHI: 測量矩形旋轉角度
Len1,Len2:測量矩形寬高的一半
Width,Height:圖像寬高
Interpolation:插值類型
MeasrueHandle:測量句柄
關於 測量ROI寬度的選擇,如果測量的邊緣和profile line 是垂直關系,則寬度盡肯能的寬 這樣可以減少噪聲.

如果測量的邊緣和profileline 不是垂直的關系 則寬度要盡可能的小,相應的噪聲增加。

綜上所述 在ID 測量的時候 最好 將 profile Line 與待測邊緣垂直 而且盡可能的寬 以減少噪聲。
如果不能保持垂直 那么 ROI的寬度要盡可能小。
2.2 create a measure object
gen_measure_rectangle2
gen_measure_arc
.
2.3 using the measure object
measure_pairs(Image : : MeasureHandle, Sigma, Threshold, Transition, Select : RowEdgeFirst, ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond, AmplitudeSecond, IntraDistance, InterDistance)




在用measure_pair 進行測量之前 有必要了解一下halcon的measure_pair 是怎么工作的。
上四副圖是halcon的測量助手的截圖。
圖1是設定的ROI區域
圖3 中是灰度均值組成的連續曲線 需要說明的是 圖中 最多邊和最右邊的兩條紅線是參看線 中間的4組藍紅線才是符合條件的邊緣線
圖4 是圖3的一階導數 需要說明的是 圖中 最多邊和最右邊的兩條紅線是參看線 中間的4組藍紅線才是符合條件的邊緣線
圖2 是各種參數的設置
【最小邊緣幅度】= 10 對應measure_pairs中的【threshold】參數 從圖4可以看到 圖中留下的紅藍線的絕對值都是大於等於10的
【平滑】=0.9 對應 measure_pairs中的【sigma】參數
勾選后為'all_strongest', 'positive_strongest', 'negative_strongest'
'positive':
only negative edges, i.e., light-to-dark 只返回負梯度值的邊緣,圖4中藍線所示
'negative' :相反。
'all' : 返回的是 正負都有
【位置】all 選擇所有 first 選擇第一組/條 last 選擇最后一組/條
boundary一個例子:測保險絲的寬度 Example: solution_guide/basics/fuse.hdev

**********************************************
* 思路:1.gen_measure_rectangle2 創建測量區域
2.measure_pairs 配對
3.顯示結果
****************************************************
read_image(Fuse,'fuse')
get_image_size(Fuse,Width,Height)
Row := 297
Column := 545
Lenght1 :=80
Lenght2 :=10
get_image_size(Fuse,Width,Height)
Row := 297
Column := 545
Lenght1 :=80
Lenght2 :=10
* 旋轉90度
Angle :=rad(90)
*Length1 為矩形寬 Length2為矩形高
Angle :=rad(90)
*Length1 為矩形寬 Length2為矩形高
gen_measure_rectangle2(Row,Column,Angle,Lenght1,Lenght2,Width,Height,\
'bilinear',MeasureHandle)
'bilinear',MeasureHandle)
* 對圖像的測量區域配對
* 如上實驗圖為兩對直線
*配對后的中心坐標存放在RowEdgeFirst,\
* ColumnEdgeFirst,\
* ColumnEdgeFirst,\
* RowEdgeSecond,\
* ColumEdgeSecond 數組中
* ColumEdgeSecond 數組中
*每對線- 兩條線的距離在 IntraDistance 數組中
measure_pairs(Fuse,MeasureHandle,1,1,'negative','all',RowEdgeFirst,\
ColumnEdgeFirst,AmpliudeFirst,RowEdgeSecond,\
ColumEdgeSecond,AmpliudeSecond,IntraDistance,\
InterDistance)
ColumnEdgeFirst,AmpliudeFirst,RowEdgeSecond,\
ColumEdgeSecond,AmpliudeSecond,IntraDistance,\
InterDistance)
*得到線 如實驗圖所示
*measure_pairs 得到的只是點現在 計算出線
*gen_contour_polygon_xld(Edge,[0,1,2,2,2],[0,0,0,1,2]) 可以得到這樣的圖形
*gen_contour_polygon_xld(Edge,[0,1,2,2,2],[0,0,0,1,2]) 可以得到這樣的圖形
* |
* |
* |————
* 左下 以坐上角(0,0)為原點
for i :=0 to | RowEdgeFirst |-1 by 1
gen_contour_polygon_xld (EdgeFirst, \
[-sin(Angle+rad(90))*Lenght2+RowEdgeFirst[i],\
-sin(Angle-rad(90))*Lenght2+RowEdgeFirst[i]],\
[cos(Angle+rad(90))*Lenght2+ColumnEdgeFirst[i], \
cos(Angle-rad(90))*Lenght2+ColumnEdgeFirst[i]])
gen_contour_polygon_xld (EdgeSecond, \
[-sin(Angle+rad(90))*Lenght2+RowEdgeSecond[i],\
-sin(Angle-rad(90))*Lenght2+RowEdgeSecond[i]],\
[cos(Angle+rad(90))*Lenght2+ColumEdgeSecond[i], \
cos(Angle-rad(90))*Lenght2+ColumEdgeSecond[i]])
dev_set_color ('cyan')
dev_display (EdgeFirst)
dev_set_color ('magenta')
dev_display (EdgeSecond)
dev_set_color ('blue')
endfor
一個例子: 檢測鑄造零件 Example: hdevelop/Applications/Measuring-2D/measure_arc.hdev

******************************
*measure_pos
*思路:先生成一個圓弧,即弧線上的點作為測量區域
* 用measure_pos測量弧線的點得出 孔間距離
************************************
read_image(Zeiss1,'zeiss1')
get_image_size(Zeiss1,Width,Height)
dev_close_window()
dev_open_window(0,0,Width/2,Height/2,'black',WindowHandle)
dev_display(Zeiss1)
Row := 275
Column :=335
Radius :=107
AngleStart :=-rad(55)
AngleExtent :=rad(170)
*獲取橢圓指定角度的點坐標
get_points_ellipse(AngleStart+AngleExtent,Row,Column,0,Radius,Radius,\
RowPoint,ColPoint )
dev_set_draw('fill')
dev_set_color('green')
dev_set_line_width(1)
read_image(Zeiss1,'zeiss1')
get_image_size(Zeiss1,Width,Height)
dev_close_window()
dev_open_window(0,0,Width/2,Height/2,'black',WindowHandle)
dev_display(Zeiss1)
Row := 275
Column :=335
Radius :=107
AngleStart :=-rad(55)
AngleExtent :=rad(170)
*獲取橢圓指定角度的點坐標
get_points_ellipse(AngleStart+AngleExtent,Row,Column,0,Radius,Radius,\
RowPoint,ColPoint )
dev_set_draw('fill')
dev_set_color('green')
dev_set_line_width(1)
*顯示圓
disp_arc (WindowHandle, Row, Column, AngleExtent,RowPoint, ColPoint)
*生成測量圓弧
gen_measure_arc(Row,Column,Radius,AngleStart,AngleExtent,10,\
Width,Height,'nearest_neighbor',MeasureHandle)
*測量
measure_pos(Zeiss1,MeasureHandle,1,10,'all','all',RowEdge,\
ColumnEdge,Amplitude,Distance)
*計算距離
distance_pp(RowEdge[1],ColumnEdge[1],RowEdge[2],ColumnEdge[2],IntermeDist)
dev_set_color('red')
dev_set_line_width(3)
disp_line(WindowHandle,RowEdge[1],ColumnEdge[1],RowEdge[2],ColumnEdge[2])
disp_message(WindowHandle,'Distance: ' + IntermeDist , 'image',\
250,8,'yellow','false')
close_measure(MeasureHandle)
disp_arc (WindowHandle, Row, Column, AngleExtent,RowPoint, ColPoint)
*生成測量圓弧
gen_measure_arc(Row,Column,Radius,AngleStart,AngleExtent,10,\
Width,Height,'nearest_neighbor',MeasureHandle)
*測量
measure_pos(Zeiss1,MeasureHandle,1,10,'all','all',RowEdge,\
ColumnEdge,Amplitude,Distance)
*計算距離
distance_pp(RowEdge[1],ColumnEdge[1],RowEdge[2],ColumnEdge[2],IntermeDist)
dev_set_color('red')
dev_set_line_width(3)
disp_line(WindowHandle,RowEdge[1],ColumnEdge[1],RowEdge[2],ColumnEdge[2])
disp_message(WindowHandle,'Distance: ' + IntermeDist , 'image',\
250,8,'yellow','false')
close_measure(MeasureHandle)
例子:Fuzzy Measuring Example: hdevelop/Applications/Measuring-2D/fuzzy_measure_pin.hdev
沒看懂
例子:Measuring Leads of a Moving IC 測量電路板的針腳邊緣
例子:Measuring Leads of a Moving IC 測量電路板的針腳邊緣

**************************************************************
* *對於角度,不可以這樣:比如 AngleStart :=350 AngleExtent :=20,這樣到360就會停止,而應該是這樣AngleStart:=-10
*
Optimization
, *這個用於優化生成模型的 點 尤其是對於比較大的圖像, If Optimization = 'none', all model points are stored ,其他未知
*
Metric
, *If Metric = 'use_polarity', the object in the image and the model must have the same contrast. If, for example, the model is a bright * *object on a dark background, the object is found only if it is also brighter than the background.
*
*
* inspect_shape_model(Image : * 輸入 -- 建模的圖片
* ModelImages, * 輸出 --金子塔圖片 如果NumLevels = 4 那就是四張哦
* ModelRegions : *輸出 --二值后的模型
* NumLevels, * 輸入 -- 金字塔等級
* Contrast : ) * 二值化閾值
* find_shape_model(Image : : ModelID, AngleStart, AngleExtent,
* MinScore, * 最小相似度 如 0.7 則要 70%相似
* NumMatches, *
* MaxOverlap, *如果模型是一個 對稱的模型 ,那么在找模型的時候 可能會有重疊的區域 哦說不清楚額[0.0,1.0]
* SubPixel,
* NumLevels, * 金字塔數 可選值: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
* Greediness : * of the search heuristic (0: safe but slow; 1: fast but matches may be missed
*
* 思路:以芯片的字母區域做基准, 用模型匹配來校准 測量區域
*
**********************************************************
dev_update_pc('off')
dev_update_window('off')
dev_update_var('off')
open_framegrabber ('File', 1, 1, 0, 0, 0, 0, 'default', -1, \
'default', 'default', 'default', 'board/board.seq', 'default',\
-1, -1, FGHandle)
grab_image(Image,FGHandle)
get_image_size(Image,Width,Height)
dev_close_window()
dev_open_window(0,0,Width,Height,'black',WindowHandle)
dev_set_window(WindowHandle)
dev_display(Image)
Row1 :=188
Column1 :=182
Row2 :=298
Column2 :=412
gen_rectangle1(Rectangle,Row1,Column1,Row2,Column2)
area_center(Rectangle,Area,Row,Column)
dev_display(Rectangle)
Rect1Row :=-102
Rect1Col :=5
Rect2Row :=107
Rect2Col :=5
RectPhi :=0
RectLength1 :=170
RectLength2 :=5
gen_rectangle2 (Rectangle1, Row+Rect1Row, Column+Rect1Col, RectPhi, RectLength1, RectLength2)
gen_rectangle2 (Rectangle2, Row+Rect2Row, Column+Rect2Col, RectPhi, RectLength1, RectLength2)
dev_display(Rectangle1)
dev_display(Rectangle2)
*創建模型
reduce_domain(Image,Rectangle,ImageReduced)
create_shape_model (ImageReduced,'auto', 0, rad(360), rad(1), 'none', 'use_polarity', 30, 'auto', ModelID)
*獲取模型輪廓 shapeModel 在下面有用到哦
*shapeMode 是基准 ,這里shapemodel 的中心點 是原點(0,0) 也就是圖像的左上角
get_shape_model_contours(ShapeModel,ModelID,1)
*這段代碼沒用 囧 ~~ 例子里寫這段干嘛 不嫌長啊
*
*創建變換矩陣
*hom_mat2d_identity(HomMat2DIndentity)
*平移矩陣
*hom_mat2d_translate(HomMat2DIndentity,Row,Column,HomMat2DTranslate)
*shapeModel平移 ,這樣就到了原來的位置
*因為沒有旋轉,所以不需要旋轉變換了
*affine_trans_contour_xld(ShapeModel,ShapeMOdelTrans,HomMat2DTranslate)
disp_message(WindowHandle,['Press left button to start','and stop the demo'],\
'image',12,12,'black','true')
get_mbutton(WindowHandle,Row3,Column3,Button1)
Button :=0
while(Button #1)
dev_set_window(WindowHandle)
dev_set_part(0,0,Height-1,Width-1)
grab_image(ImageCheck,FGHandle)
dev_display(ImageCheck)
*得到匹配模型的位置和旋轉角度
find_shape_model (ImageCheck, ModelID, rad(0), rad(360), 0.7, 1, 0.5, 'least_squares', 4, 0.7,\
RowCheck, ColumnCheck, AngleCheck, Score)
if(|Score| > 0)
dev_set_color('green')
*這里對shapeModel(基准shapemodel 是在圖像原點的) 做平移和旋轉操作.
hom_mat2d_identity(HomMat2DIndentity)
hom_mat2d_translate(HomMat2DIndentity,RowCheck,ColumnCheck,HomMat2DTranslate)
hom_mat2d_rotate(HomMat2DTranslate,AngleCheck,RowCheck,ColumnCheck,HomMat2DRotate)
affine_trans_contour_xld(ShapeModel,ShapeModelTrans,HomMat2DRotate)
dev_display(ShapeModelTrans)
*這里是對測量區域做校准,圖像變換后,測量區域也是要跟着變的餓
*根據新的變換矩陣,以 測量區域 Rect1Row等 求出變換后的 新Rect1RowCheck
*這樣就可以創建新的 測量區域了
affine_trans_pixel(HomMat2DRotate,Rect1Row,Rect1Col,Rect1RowCheck,Rect1ColCheck)
affine_trans_pixel(HomMat2DRotate,Rect2Row,Rect2Col,Rect2RowCheck,Rect2ColCheck)
gen_rectangle2(Rectangle1Check,Rect1RowCheck,Rect1ColCheck,AngleCheck,RectLength1,RectLength2)
gen_rectangle2(Rectangle2Check,Rect2RowCheck,Rect2ColCheck,AngleCheck,RectLength1,RectLength2)
dev_set_color('blue')
dev_set_draw('margin')
dev_set_line_width(3)
dev_display(Rectangle1Check)
dev_display(Rectangle2Check)
gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, AngleCheck, RectLength1, RectLength2,\
Width, Height, 'nearest_neighbor', MeasureHandle1)
gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, AngleCheck, RectLength1, RectLength2,\
Width, Height, 'nearest_neighbor', MeasureHandle2)
measure_pairs (ImageCheck, MeasureHandle1, 2, 90, 'positive', 'all', RowEdgeFirst1, \
ColumnEdgeFirst1, AmplitudeFirst1, RowEdgeSecond1, ColumnEdgeSecond1, AmplitudeSecond1, IntraDistance1, InterDistance1)
measure_pairs (ImageCheck, MeasureHandle2, 2, 90, 'positive', 'all', RowEdgeFirst2, \
ColumnEdgeFirst2, AmplitudeFirst2, RowEdgeSecond2, ColumnEdgeSecond2, AmplitudeSecond2, IntraDistance2, InterDistance2)
close_measure(MeasureHandle1)
close_measure(MeasureHandle2)
dev_set_color('red')
dev_set_draw('fill')
disp_line (WindowHandle, RowEdgeFirst1-RectLength2*cos(AngleCheck), ColumnEdgeFirst1-RectLength2*sin(AngleCheck), RowEdgeFirst1+RectLength2*cos(AngleCheck), ColumnEdgeFirst1+RectLength2*sin(AngleCheck))
disp_line (WindowHandle, RowEdgeSecond1-RectLength2*cos(AngleCheck), ColumnEdgeSecond1-RectLength2*sin(AngleCheck), RowEdgeSecond1+RectLength2*cos(AngleCheck), ColumnEdgeSecond1+RectLength2*sin(AngleCheck))
disp_line (WindowHandle, RowEdgeFirst2-RectLength2*cos(AngleCheck), ColumnEdgeFirst2-RectLength2*sin(AngleCheck), RowEdgeFirst2+RectLength2*cos(AngleCheck), ColumnEdgeFirst2+RectLength2*sin(AngleCheck))
disp_line (WindowHandle, RowEdgeSecond2-RectLength2*cos(AngleCheck), ColumnEdgeSecond2-RectLength2*sin(AngleCheck), RowEdgeSecond2+RectLength2*cos(AngleCheck), ColumnEdgeSecond2+RectLength2*sin(AngleCheck))
wait_seconds(2)
endif
* get_mposition (WindowHandle, R, C, Button)
endwhile
dev_update_pc('off')
dev_update_window('off')
dev_update_var('off')
open_framegrabber ('File', 1, 1, 0, 0, 0, 0, 'default', -1, \
'default', 'default', 'default', 'board/board.seq', 'default',\
-1, -1, FGHandle)
grab_image(Image,FGHandle)
get_image_size(Image,Width,Height)
dev_close_window()
dev_open_window(0,0,Width,Height,'black',WindowHandle)
dev_set_window(WindowHandle)
dev_display(Image)
Row1 :=188
Column1 :=182
Row2 :=298
Column2 :=412
gen_rectangle1(Rectangle,Row1,Column1,Row2,Column2)
area_center(Rectangle,Area,Row,Column)
dev_display(Rectangle)
Rect1Row :=-102
Rect1Col :=5
Rect2Row :=107
Rect2Col :=5
RectPhi :=0
RectLength1 :=170
RectLength2 :=5
gen_rectangle2 (Rectangle1, Row+Rect1Row, Column+Rect1Col, RectPhi, RectLength1, RectLength2)
gen_rectangle2 (Rectangle2, Row+Rect2Row, Column+Rect2Col, RectPhi, RectLength1, RectLength2)
dev_display(Rectangle1)
dev_display(Rectangle2)
*創建模型
reduce_domain(Image,Rectangle,ImageReduced)
create_shape_model (ImageReduced,'auto', 0, rad(360), rad(1), 'none', 'use_polarity', 30, 'auto', ModelID)
*獲取模型輪廓 shapeModel 在下面有用到哦
*shapeMode 是基准 ,這里shapemodel 的中心點 是原點(0,0) 也就是圖像的左上角
get_shape_model_contours(ShapeModel,ModelID,1)
*這段代碼沒用 囧 ~~ 例子里寫這段干嘛 不嫌長啊
*
*創建變換矩陣
*hom_mat2d_identity(HomMat2DIndentity)
*平移矩陣
*hom_mat2d_translate(HomMat2DIndentity,Row,Column,HomMat2DTranslate)
*shapeModel平移 ,這樣就到了原來的位置
*因為沒有旋轉,所以不需要旋轉變換了
*affine_trans_contour_xld(ShapeModel,ShapeMOdelTrans,HomMat2DTranslate)
disp_message(WindowHandle,['Press left button to start','and stop the demo'],\
'image',12,12,'black','true')
get_mbutton(WindowHandle,Row3,Column3,Button1)
Button :=0
while(Button #1)
dev_set_window(WindowHandle)
dev_set_part(0,0,Height-1,Width-1)
grab_image(ImageCheck,FGHandle)
dev_display(ImageCheck)
*得到匹配模型的位置和旋轉角度
find_shape_model (ImageCheck, ModelID, rad(0), rad(360), 0.7, 1, 0.5, 'least_squares', 4, 0.7,\
RowCheck, ColumnCheck, AngleCheck, Score)
if(|Score| > 0)
dev_set_color('green')
*這里對shapeModel(基准shapemodel 是在圖像原點的) 做平移和旋轉操作.
hom_mat2d_identity(HomMat2DIndentity)
hom_mat2d_translate(HomMat2DIndentity,RowCheck,ColumnCheck,HomMat2DTranslate)
hom_mat2d_rotate(HomMat2DTranslate,AngleCheck,RowCheck,ColumnCheck,HomMat2DRotate)
affine_trans_contour_xld(ShapeModel,ShapeModelTrans,HomMat2DRotate)
dev_display(ShapeModelTrans)
*這里是對測量區域做校准,圖像變換后,測量區域也是要跟着變的餓
*根據新的變換矩陣,以 測量區域 Rect1Row等 求出變換后的 新Rect1RowCheck
*這樣就可以創建新的 測量區域了
affine_trans_pixel(HomMat2DRotate,Rect1Row,Rect1Col,Rect1RowCheck,Rect1ColCheck)
affine_trans_pixel(HomMat2DRotate,Rect2Row,Rect2Col,Rect2RowCheck,Rect2ColCheck)
gen_rectangle2(Rectangle1Check,Rect1RowCheck,Rect1ColCheck,AngleCheck,RectLength1,RectLength2)
gen_rectangle2(Rectangle2Check,Rect2RowCheck,Rect2ColCheck,AngleCheck,RectLength1,RectLength2)
dev_set_color('blue')
dev_set_draw('margin')
dev_set_line_width(3)
dev_display(Rectangle1Check)
dev_display(Rectangle2Check)
gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, AngleCheck, RectLength1, RectLength2,\
Width, Height, 'nearest_neighbor', MeasureHandle1)
gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, AngleCheck, RectLength1, RectLength2,\
Width, Height, 'nearest_neighbor', MeasureHandle2)
measure_pairs (ImageCheck, MeasureHandle1, 2, 90, 'positive', 'all', RowEdgeFirst1, \
ColumnEdgeFirst1, AmplitudeFirst1, RowEdgeSecond1, ColumnEdgeSecond1, AmplitudeSecond1, IntraDistance1, InterDistance1)
measure_pairs (ImageCheck, MeasureHandle2, 2, 90, 'positive', 'all', RowEdgeFirst2, \
ColumnEdgeFirst2, AmplitudeFirst2, RowEdgeSecond2, ColumnEdgeSecond2, AmplitudeSecond2, IntraDistance2, InterDistance2)
close_measure(MeasureHandle1)
close_measure(MeasureHandle2)
dev_set_color('red')
dev_set_draw('fill')
disp_line (WindowHandle, RowEdgeFirst1-RectLength2*cos(AngleCheck), ColumnEdgeFirst1-RectLength2*sin(AngleCheck), RowEdgeFirst1+RectLength2*cos(AngleCheck), ColumnEdgeFirst1+RectLength2*sin(AngleCheck))
disp_line (WindowHandle, RowEdgeSecond1-RectLength2*cos(AngleCheck), ColumnEdgeSecond1-RectLength2*sin(AngleCheck), RowEdgeSecond1+RectLength2*cos(AngleCheck), ColumnEdgeSecond1+RectLength2*sin(AngleCheck))
disp_line (WindowHandle, RowEdgeFirst2-RectLength2*cos(AngleCheck), ColumnEdgeFirst2-RectLength2*sin(AngleCheck), RowEdgeFirst2+RectLength2*cos(AngleCheck), ColumnEdgeFirst2+RectLength2*sin(AngleCheck))
disp_line (WindowHandle, RowEdgeSecond2-RectLength2*cos(AngleCheck), ColumnEdgeSecond2-RectLength2*sin(AngleCheck), RowEdgeSecond2+RectLength2*cos(AngleCheck), ColumnEdgeSecond2+RectLength2*sin(AngleCheck))
wait_seconds(2)
endif
* get_mposition (WindowHandle, R, C, Button)
endwhile
例子:Inspect IC Example: hdevelop/Applications/Measuring-2D/measure_pin.hdev
圖0

圖1 :sigma = 1.0

圖2 sigma=1.5

圖3 sigma =3.0

*************************************************************
*
*①測量針腳個數,寬度,間距
*②測量針腳長度
*measure_pairs 與 measure_pos 的不同
*在此例子中 meausre_pairs 用於檢測針腳寬度 measure_pos 用於檢測陣腳高度
* measure_pairs 適用於處理用邊緣包圍的物體,如針腳寬度,中間有白色區域將每個針腳隔開,而且可以根據Transition參數將得到不同的測量結果,
* 如陣腳兩側的邊緣點(這些點是圖0左紅線的中心點) 結果返回在RowEdgeFirst, ColumnEdgeFirst,RowEdgeSecond, ColumnEdgeSecond 數* 組中
* 而遇到圖0右 中測量針腳高度的時候 就可以用measure_pos
*
Transition
, *List of values: 'all', 'positive', 'negative', 'all_strongest', 'positive_strongest', 'negative_strongest'
* *參數含義見說明文檔
* ,AmplitudeSecond,
* IntraDistance, *在此例子中是針腳寬度的數組
* InterDistance) *在此例子中是 針腳間的間距
*
*
* measure_pos(Image : : MeasureHandle, Sigma, Threshold, Transition, Select : RowEdge, ColumnEdge, Amplitude,
* Distance) * 在此例子中是圖0右邊四條紅線的間距,即有三個間距。
****************************************************************
dev_close_window()
read_image(Image,'ic_pin')
get_image_size(Image,Width,Height)
dev_open_window(0,0,Width/2,Height/2,'black',WindowHandle)
dev_display(Image)
Row :=47
Column :=485
Phi :=0
Length1 :=420
Length2 :=10
dev_set_color('green')
dev_set_draw('margin')
dev_set_line_width(3)
gen_rectangle2(Rectangle,Row,Column,Phi,Length1,Length2)
gen_measure_rectangle2(Row,Column,Phi,Length1,Length2,Width,Height,\
'nearest_neighbor',MeaserHandle)
* If Transition = 'negative', the edge points with a light-to-dark transition
*in the direction of the major axis of the rectangle are returned in RowEdgeFirst
*and ColumnEdgeFirst. In this case, the corresponding edges with a drak-to-light
*transition are returned in RowEdgeSecond and ColumnEdgeSecond
dev_close_window()
read_image(Image,'ic_pin')
get_image_size(Image,Width,Height)
dev_open_window(0,0,Width/2,Height/2,'black',WindowHandle)
dev_display(Image)
Row :=47
Column :=485
Phi :=0
Length1 :=420
Length2 :=10
dev_set_color('green')
dev_set_draw('margin')
dev_set_line_width(3)
gen_rectangle2(Rectangle,Row,Column,Phi,Length1,Length2)
gen_measure_rectangle2(Row,Column,Phi,Length1,Length2,Width,Height,\
'nearest_neighbor',MeaserHandle)
* If Transition = 'negative', the edge points with a light-to-dark transition
*in the direction of the major axis of the rectangle are returned in RowEdgeFirst
*and ColumnEdgeFirst. In this case, the corresponding edges with a drak-to-light
*transition are returned in RowEdgeSecond and ColumnEdgeSecond
*sigma 參數效果如上圖1,2所示
measure_pairs (Image, MeaserHandle, 1.5, 30, 'negative', 'all', RowEdgeFirst,\
ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond,\
AmplitudeSecond, PinWidth, PinDistance)
disp_line (WindowHandle, RowEdgeFirst, ColumnEdgeFirst, RowEdgeSecond,\
ColumnEdgeSecond)
avgPinWidth :=sum(PinWidth)/|PinWidth|
avgPinDistance :=sum(PinDistance)/|PinDistance|
numPins :=|PinWidth|
dev_set_color('yellow')
disp_message(WindowHandle,'Number of pins :'+numPins,'image',200,100,'yellow','false')
disp_message(WindowHandle,'Average Pin Width:' +avgPinWidth,'image',260,100,'yellow','false')
*來個特寫
stop()
Row1 := 0
Column1 := 600
Row2 := 100
Column2 := 700
dev_set_color ('blue')
disp_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
dev_set_part(Row1,Column1,Row2,Column2)
dev_display(Image)
dev_set_color('green')
dev_display(Rectangle)
dev_set_color('red')
disp_line (WindowHandle, RowEdgeFirst, ColumnEdgeFirst, RowEdgeSecond,\
ColumnEdgeSecond)
close_measure(MeaserHandle)
stop()
dev_set_part(0,0,Height-1,Width-1)
dev_display(Image)
dev_set_line_width(3)
Row := 508
Column := 200
Phi := -rad(90)
Length1 := 482
Length2 := 35
gen_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2)
gen_measure_rectangle2 (Row, Column, Phi, Length1, Length2, Width, Height, 'nearest_neighbor', MeasureHandle)
measure_pos (Image, MeasureHandle, 1.5, 30, 'all', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
disp_line(WindowHandle,RowEdge,ColumnEdge-Length2,RowEdge,ColumnEdge+Length2)
PinHeight1 :=RowEdge[1] - RowEdge[0]
PinHeight2 :=RowEdge[3] - RowEdge[2]
disp_message(WindowHandle,'Pin Height:'+PinHeight1,'image',\
RowEdge[1],ColumnEdge[1]+100,'yellow','false')
disp_message(WindowHandle,'Pin Height:'+PinHeight2,'image',\
RowEdge[3]-50,ColumnEdge[3]+100,'yellow','false')
close_measure(MeasureHandle)
Suppress Clutter ro Noise 抑制噪聲
measure_pairs (Image, MeaserHandle, 1.5, 30, 'negative', 'all', RowEdgeFirst,\
ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond,\
AmplitudeSecond, PinWidth, PinDistance)
disp_line (WindowHandle, RowEdgeFirst, ColumnEdgeFirst, RowEdgeSecond,\
ColumnEdgeSecond)
avgPinWidth :=sum(PinWidth)/|PinWidth|
avgPinDistance :=sum(PinDistance)/|PinDistance|
numPins :=|PinWidth|
dev_set_color('yellow')
disp_message(WindowHandle,'Number of pins :'+numPins,'image',200,100,'yellow','false')
disp_message(WindowHandle,'Average Pin Width:' +avgPinWidth,'image',260,100,'yellow','false')
*來個特寫
stop()
Row1 := 0
Column1 := 600
Row2 := 100
Column2 := 700
dev_set_color ('blue')
disp_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
dev_set_part(Row1,Column1,Row2,Column2)
dev_display(Image)
dev_set_color('green')
dev_display(Rectangle)
dev_set_color('red')
disp_line (WindowHandle, RowEdgeFirst, ColumnEdgeFirst, RowEdgeSecond,\
ColumnEdgeSecond)
close_measure(MeaserHandle)
stop()
dev_set_part(0,0,Height-1,Width-1)
dev_display(Image)
dev_set_line_width(3)
Row := 508
Column := 200
Phi := -rad(90)
Length1 := 482
Length2 := 35
gen_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2)
gen_measure_rectangle2 (Row, Column, Phi, Length1, Length2, Width, Height, 'nearest_neighbor', MeasureHandle)
measure_pos (Image, MeasureHandle, 1.5, 30, 'all', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
disp_line(WindowHandle,RowEdge,ColumnEdge-Length2,RowEdge,ColumnEdge+Length2)
PinHeight1 :=RowEdge[1] - RowEdge[0]
PinHeight2 :=RowEdge[3] - RowEdge[2]
disp_message(WindowHandle,'Pin Height:'+PinHeight1,'image',\
RowEdge[1],ColumnEdge[1]+100,'yellow','false')
disp_message(WindowHandle,'Pin Height:'+PinHeight2,'image',\
RowEdge[3]-50,ColumnEdge[3]+100,'yellow','false')
close_measure(MeasureHandle)
Suppress Clutter ro Noise 抑制噪聲
multiple approaches to achieve this. The best one is to increase the threshold for the edge extraction to
eliminate faint edges. In addition, the value for the smoothing parameter can be increased to smooth
irrelevant edges away.
When grouping edges to pairs, noise edges can lead to an incorrect grouping if they are in the vicinity of
the “real” edge and have the same polarity. In such a case you can suppress the noise edges by selecting
only the strongest edges of a sequence of consecutive rising and falling edges.
通過增大閾值 或者 smoothing parameter 減少不相關的噪聲。
當我們配對的時候噪聲邊緣將影響結果的正確性, 我們可以通關選擇 the strongest edges of a sequence of consecutive rising and falling edges
Reuse Measure Object 在利用 measure object
Because the creation of a measure object needs some time, we recommend to reuse them if possible.
If no alignment is needed, the measure object can, for example, be created offline and reused for each
image. If the alignment involves only a translation, translate_measure can be used to correct the
position.
If no alignment is needed, the measure object can, for example, be created offline and reused for each
image. If the alignment involves only a translation, translate_measure can be used to correct the
position.

如圖所示有兩個 measure object
通過translate_measure (MeasureHandle, RowBottom, Column) 可以只生成一個 measure rectangle 另一個用該函數重新利用
Use an Absolute Gray Value Threshold
As an alternative to edge extraction, the measurements can be performed based on an absolute gray value
threshold by using the operator measure_thresh. Here, all positions where the gray value crosses the
given threshold are selected.
threshold by using the operator measure_thresh. Here, all positions where the gray value crosses the
given threshold are selected.
Fuzzy Measuring
In case there are extra edges that do not belong to the measurement, HALCON offers an extended
version of measuring: fuzzy measuring. This tool allows to define so-called fuzzy rules, which describe
the features of good edges. Possible features are, e.g., the position, the distance, the gray values, or the
amplitude of edges. These functions are created with create_funct_1d_pairs and passed to the tool
with set_fuzzy_measure. Based on these rules, the tool will select the most appropriate edges.
The advantage of this approach is the flexibility to deal with extra edges even if a very low min-
imum threshold or smoothing is used. An example for this approach is the example program
fuzzy_measure_pin.hdev on page 53.
Please refer to the Solution Guide III-A, chapter 4 on page 33, for more information.
In case there are extra edges that do not belong to the measurement, HALCON offers an extended
version of measuring: fuzzy measuring. This tool allows to define so-called fuzzy rules, which describe
the features of good edges. Possible features are, e.g., the position, the distance, the gray values, or the
amplitude of edges. These functions are created with create_funct_1d_pairs and passed to the tool
with set_fuzzy_measure. Based on these rules, the tool will select the most appropriate edges.
The advantage of this approach is the flexibility to deal with extra edges even if a very low min-
imum threshold or smoothing is used. An example for this approach is the example program
fuzzy_measure_pin.hdev on page 53.
Please refer to the Solution Guide III-A, chapter 4 on page 33, for more information.
Evaluation of Gray Values
To have full control over the evaluation of the gray values along the measurement line or arc, you can use
measure_projection. The operator returns the projected gray values as an array of numbers, which
can then be further processed with HALCON operators for tuple or function processing (see the chapters
“Tuple” and “Tools . Function” in the Reference Manual). Please refer to the Solution Guide III-A,
section 3.4 on page 22, for more information.
To have full control over the evaluation of the gray values along the measurement line or arc, you can use
measure_projection. The operator returns the projected gray values as an array of numbers, which
can then be further processed with HALCON operators for tuple or function processing (see the chapters
“Tuple” and “Tools . Function” in the Reference Manual). Please refer to the Solution Guide III-A,
section 3.4 on page 22, for more information.