http://www.cnblogs.com/xiaomaLV2/archive/2011/11/29/2267509.html
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
* 旋轉90度
Angle :=rad(90)
*Length1 為矩形寬 Length2為矩形高
gen_measure_rectangle2(Row,Column,Angle,Lenght1,Lenght2,Width,Height,\
'bilinear',MeasureHandle)
* 對圖像的測量區域配對
* 如上實驗圖為兩對直線
*配對後的中心坐標存放在RowEdgeFirst,\
* ColumnEdgeFirst,\
* RowEdgeSecond,\
* ColumEdgeSecond 數組中
*每對線- 兩條線的距離在 IntraDistance 數組中
measure_pairs(Fuse,MeasureHandle,1,1,'negative','all',RowEdgeFirst,\
ColumnEdgeFirst,AmpliudeFirst,RowEdgeSecond,\
ColumEdgeSecond,AmpliudeSecond,IntraDistance,\
InterDistance)
*得到線 如實驗圖所示
*measure_pairs 得到的只是點現在 計算出線
*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)
*顯示圓
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 測量電路板的針腳邊緣
**************************************************************
* create_shape_model(
Template
: :
*
NumLevels
, * 金字塔 默認設置 'auto' 可以使用inspect_shape_model來試著確定NumLevels
*
AngleStart
, *起始角度
*
AngleExtent
, *角度幅度 順時針
* *對於角度,不可以這樣:比如 AngleStart :=350 AngleExtent :=20,這樣到360就會停止,而應該是這樣AngleStart:=-10
*
AngleStep
, *一次旋轉多少度
*
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.
*
Contrast
, *二值化閾值 可以通過inspect_shape_model 試著確定
*
MinContrast
: * 和 Contrast 組成一個 閾值范圍
*
ModelID
)
*
*
* 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
* Row, Column, Angle, Score)
*
* 思路:以芯片的字母區域做基准, 用模型匹配來校准 測量區域
*
**********************************************************
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
*measure_pairs(
Image
: :
MeasureHandle
,
*
Sigma
, *高斯平滑參數-- [0.4 , 100] 具體參數效果如上圖1,2所示
*
Threshold
, *閾值
*
Transition
, *List of values: 'all', 'positive', 'negative', 'all_strongest', 'positive_strongest', 'negative_strongest'
* *參數含義見說明文檔
*
Select
:
RowEdgeFirst
,
ColumnEdgeFirst
,
AmplitudeFirst
,
RowEdgeSecond
,
ColumnEdgeSecond
,
* ,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
*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 抑制噪聲
In many applications there is clutter or noise that must be suppressed. The measure operators offer
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.
如圖所示有兩個 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.
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.
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.