halcon之缺陷检测2
发布时间
阅读量:
阅读量
1,检查瓶子标签是否凸起,褶皱。
photometric_stereo
用于光度立体法三维表面重建的核心算子,通过多光源下的图像数据计算物体表面的高度场、梯度及反射率信息。以下是对该算子的详细解析:
1. 功能概述
photometric_stereo 基于 Woodham 算法,利用至少三张不同光照方向下的图像,通过光度立体技术重建物体表面的局部梯度信息,并综合为高度场(HeightField)或反射率图(Albedo)。其核心假设包括:
- 正交投影 :需使用远心镜头或长焦镜头以避免图像畸变。
- 朗伯反射 :物体表面需为漫反射材质,镜面反射区域会导致错误结果。
- 平行光源 :需使用远心光源或远距离点光源保证光线均匀性。
2. 核心参数
-
输入参数 :
Images:至少包含三张相同视角、不同光照方向的图像数组。Slants和Tilts:分别表示光源的倾斜角和方位角(以弧度为单位)。
-
输出参数 :
HeightField:高度场图像,表示表面相对高度。Gradient:梯度图像,包含表面法向量的局部梯度信息。Albedo:反射率图像,反映物体表面材质的光吸收特性。
-
关键选项 :
ResultType:控制输出类型(如高度场或梯度)。ReconstructionMethod:选择重建算法(默认基于最小二乘法)。
3. 典型应用场景
- 表面缺陷检测 :通过梯度或高度场差异识别微小表面缺陷。
- 打印质量检查 :排除光照角度对非平面字符检测的影响。
- 纹理分离 :分离反照率信息以消除阴影干扰。
4. 技术限制
- 非绝对高度重建 :仅能计算相对高度,无法替代激光三角测量或结构光等绝对三维重建方法3。
- 硬件要求严格 :需远心镜头、固定视角相机及可控光源系统。
- 材质限制 :镜面或高光表面区域会导致重建错误。
5. 采集设置要求
-
相机配置 :
- 使用远心镜头,且相机光轴与物体表面正交。
- 拍摄过程中相机与物体位置需完全固定。
-
光源要求 :
- 至少三种不同光照方向(通过调整
Slants和Tilts参数定义)。 - 光源需保持平行且强度均匀。
- 至少三种不同光照方向(通过调整
6. 与其他3D重建方法的对比
| 方法 | 优势 | 局限性 |
|---|---|---|
| 光度立体法 | 无需图像匹配,适合高精度表面细节重建 | 依赖严格光照条件,仅支持相对高度 |
| 激光三角测量 | 可重建绝对高度,抗干扰性强 | 设备成本高,不适合大面积检测 |
| 立体视觉 | 适合动态场景,支持绝对深度 | 依赖特征匹配,计算复杂度高 |
通过合理配置光源和相机参数,并结合反照率与梯度信息,photometric_stereo 在工业检测与质量控制中展现出高精度表面分析能力。
derivate_vector_field
用于处理矢量场的关键算子,通过高斯导数卷积提取矢量场的局部特征。以下是其核心功能、参数及应用场景的详细解析:
1. 功能概述
derivate_vector_field 对输入的矢量场(vector_field_relative 类型)执行高斯导数卷积,并计算基于梯度的特征参数(如曲率、散度等)。其核心功能包括:
- 高斯平滑 :通过指定
Sigma参数对矢量场进行高斯滤波,抑制噪声干扰。 - 特征提取 :根据
Component参数输出不同类型的特征图像(如平均曲率、旋度等),适用于表面几何特性分析。 - 适用性限制 :仅支持语义类型为
vector_field_relative的矢量场输入,其他类型(如绝对矢量场)需先转换。
2. 核心参数
-
输入参数 :
VectorField:输入矢量场,需通过real_to_vector_field或optical_flow_mg等算子生成26。Sigma:高斯核标准差,控制平滑程度,值越大平滑效果越显著。Component:指定输出特征类型,可选值包括:mean_curvature:平均曲率(常用于表面缺陷检测)。divergence/curl:散度或旋度(用于流体力学或变形分析)。
-
输出参数 :
Result:特征图像,数据类型为浮点数(real)。
3. 典型应用场景
- 缺陷检测 :通过计算表面梯度场的平均曲率(
mean_curvature),识别凹痕、划痕等局部几何异常。 - 变形分析 :在图像拼接或模拟随机局部变形时,结合
gen_random_vector_field生成随机矢量场,并通过本算子分析形变特征。 - 光流处理 :与
optical_flow_mg配合,提取光流场的散度或旋度信息,用于运动场可视化或动态场景分析。
4. 技术限制
- 输入类型限制 :仅接受
vector_field_relative类型矢量场,需确保输入数据格式正确。 - 噪声敏感性 :当原始矢量场噪声较大时,需增大
Sigma值以平滑噪声,但可能牺牲细节分辨率。 - 计算资源消耗 :处理高分辨率矢量场时需较高内存和计算性能。
*参考案例库:inspect_shampoo_label_photometric_stereo.hdev
*目的:
*使用光学立体技术检查标签是否褶皱、凸起
*要求:
*图像需要使用配置远心镜头的相机采集,避免深度畸变。
* Initialization
dev_close_window ()
dev_update_off ()
dev_open_window (0, 0, 640, 512, 'black', WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
Message := 'Inspect the label of a shampoo bottle'
Message[1] := 'using photometric stereo. In this case four'
Message[2] := 'different light orientations were used.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* * Show input images with different illumination
read_image (Images, 'photometric_stereo/shampoo_label_0' + [1:4])
for I := 1 to 4 by 1
Message := 'Acquire image ' + I + ' of 4'
select_obj (Images, ObjectSelected, I)
dev_display (ObjectSelected)
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
wait_seconds (0.5)
endfor
* *倾斜角
Tilts := [6.1,95.0,-176.1,-86.8]
*方位角
Slants := [41.4,42.6,41.7,40.9]
*gradient:倾斜率,albedo:反射率
ResultType := ['gradient','albedo']
*根据光影立体技术创建一个表面
photometric_stereo (Images, HeightField, Gradient, Albedo, Slants, Tilts, ResultType, 'poisson', [], [])
* * Display the albedo image
dev_display (Albedo)
disp_message (WindowHandle, 'Albedo image', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* *计算表面的高斯曲率
*使用梯度场作为运算符的输入
*缺陷通常很容易在曲率图像中检测到。
derivate_vector_field (Gradient, MeanCurvature, 1.0, 'mean_curvature')
* * Detect defects
* * Segment the tablet areas in the curvature image
threshold (MeanCurvature, Region, -10, -0.07)
opening_circle (Region, RegionOpening, 1)
connection (RegionOpening, ConnectedRegions)
select_shape (ConnectedRegions, Defects, 'area', 'and', 50, 99999)
shape_trans (Defects, Circle, 'outer_circle')
* Display the defects in curvature image
dev_set_draw ('margin')
dev_set_color ('red')
dev_set_line_width (2)
dev_display (MeanCurvature)
dev_display (Circle)
Message := 'The defect can easily be detected'
Message[1] := 'in the surface curvature image'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
stop ()
* Display the defects in the albedo image
dev_set_draw ('margin')
dev_set_color ('red')
dev_display (Albedo)
dev_display (Circle)
disp_message (WindowHandle, 'Defect in albedo image', 'window', 12, 12, 'black', 'true')
XML


2,Board线路焊接检查。
*参考案例库:board.hdev
*目的:
*检查电路板焊锡缺失的位置
*原理:
*合并计算多张在不同角度拍摄的电路板图像,查找出焊锡边缘(亮处)
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
dev_set_draw ('margin')
dev_set_line_width (2)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_update_window ('off')
*1,加载图片,并进行通道合并
read_image (Image, 'ic'+[0:3])
channels_to_image (Image, MultiChannelImage)
dev_display (MultiChannelImage)
stop ()
mean_n (MultiChannelImage, ImageMean)
dev_display (ImageMean)
stop()
*2,需要焊接的线路
threshold (Image, Region, 0, 40)
union1 (Region, dark)
fill_up (dark, darkFill)
complement (darkFill, back)
*3,焊接良好的线路
threshold (Image, Region, 100, 255)
union1 (Region, light)
intersection (darkFill, light, RegionIntersection)
expand_region (RegionIntersection, back, RegionExpanded, 'maximal', 'image')
fill_up (RegionExpanded, good)
*4,虚焊,缺焊的线路
difference (darkFill, good, rest)
*5,对bad区域进行适当扩展
expand_gray (rest, MultiChannelImage, good, bad, 6, 'image', 6)
fill_up (bad, RegionFillUp)
opening_circle (RegionFillUp, RegionClosing, 2.5)
connection (RegionClosing, ConnectedRegions)
select_shape (ConnectedRegions, bad, 'area', 'and', 150, 99999)
*6,显示结果
dev_display (Image)
dev_set_color ('green')
dev_display (good)
dev_set_color ('red')
dev_display (bad)
XML


3,Fish检查。
*参考案例库:count_fish_sticks.hdev
*目的:
*检查鱼生的数量是否为指定的数量,鱼生的宽度是否在规定的范围内
*描述:
*使用矩形测量获取宽度
*-------------------------1,参数设置
*设置生鱼片数量
fishNum:=15
*设置鱼生的最小宽度,最大宽度
minWidth:=20
maxWidth:=48
dev_close_window ()
*主窗口
dev_open_window (0, 0, 640, 512, 'black', WindowHandle)
dev_update_window ('off')
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (2)
*显示灰度趋势图
* dev_open_window (0, 640, 400, 200, 'black', GraphicsWindow)
*------------------------2,读取图片
for Index := 1 to 6 by 1
dev_set_window (WindowHandle)
read_image (Image, 'food/fish_stick_package_'+Index$'02')
dev_display (Image)
threshold (Image, Region, 100, 255)
closing_rectangle1 (Region, RegionClosing, 10, 10)
fill_up (RegionClosing, RegionFillUp)
difference (RegionFillUp, RegionClosing, RegionDifference)
smallest_rectangle2 (RegionDifference, Row, Column, Phi, Length1, Length2)
gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2)
*----------------------3,创建测量矩形
gen_measure_rectangle2 (Row, Column, Phi, Length1, 40, 640, 512, 'nearest_neighbor', MeasureHandle)
gen_rectangle2_contour_xld(Rectangle1, Row, Column, Phi, Length1, 60)
*测量轮廓的灰度值
measure_projection (Image, MeasureHandle, GrayValues)
*获取轮廓灰度值对应的函数
create_funct_1d_array (GrayValues, Function)
*计算函数的局部极小点和最大值。(分为多个阶段,每一阶段的最大最小值)。
local_min_max_funct_1d (Function, 'plateaus_center', 'true', Min, Max)
*获取横坐标对应的纵坐标(这里获得最小值对应的灰度值)
get_y_value_funct_1d (Function, Min, 'constant', Y)
close_measure (MeasureHandle)
*----------------------4,筛选计算每片鱼生的边界
*灰度小于50对应值得索引集合
*find(arr,val):返回数组arr中项为val的索引
indexs:=find(sgn(Y-50),-1)
*两片鱼生的分界位置
*subset(arr,indexs):返回数组arr中指定索引indexs对应的项
boundary:=subset(Min,indexs)
*界线
StickEdges:=[-0.5,boundary,2*Length1]
*--------------------- 5,计算鱼生的厚度
fishWidth:=[boundary,2*Length1]-[-0.5,boundary]
*----------------------6,计算每块鱼生的中心点已经边界的中心点
borderX:=StickEdges+Column-Length1*cos(Phi)
borderY:=Row+Length1*sin(Phi)-StickEdges/(2*Length1)*Length1*sin(Phi)
centerX:=borderX[0:|fishWidth|-1]+fishWidth/2*cos(Phi)
centerY:=borderY[0:|fishWidth|-1]+fishWidth/2*sin(Phi)
gen_cross_contour_xld (borderCross, borderY, borderX, 10, rad(45))
gen_cross_contour_xld (centerCross, centerY, centerX, 6, 0)
*----------------------7,打印结果
*处理噪声
noiseIndex:=find(sgn(fishWidth-10),-1)
noiseNum:=0
if(noiseIndex!=-1)
noiseNum:=|noiseIndex|
endif
smallIndexs:=-1
for i := 0 to |fishWidth|-1 by 1
if(fishWidth[i]>=10 and fishWidth[i]<minWidth)
smallIndexs:=[smallIndexs,i]
endif
endfor
bigIndexs:=find(sgn(fishWidth-maxWidth),1)
offsetRow:=0
if(|fishWidth|-noiseNum<fishNum or smallIndexs!=-1 or bigIndexs!=-1)
disp_message (WindowHandle, 'not ok', 'window', offsetRow, 20, 'red', 'false')
else
disp_message (WindowHandle, 'ok', 'window', offsetRow, 20, 'green', 'false')
endif
offsetRow:=offsetRow+25
str:=''
if(|fishWidth|-noiseNum<fishNum)
str:='数量不足'
endif
gen_empty_obj (bigRectangle)
if(smallIndexs!=-1 )
if(str!='')
str:=str+';'
endif
str:=str+'偏薄'
gen_rectangle2_contour_xld (smallRectangle, subset(centerY,smallIndexs), subset(centerX,smallIndexs), gen_tuple_const(|smallIndexs|,Phi),subset(fishWidth,smallIndexs),gen_tuple_const(|smallIndexs|,40) )
*偏小
dev_set_color ('red')
dev_display (smallRectangle)
endif
if(bigIndexs!=-1 )
if(str!='')
str:=str+';'
endif
str:=str+'偏厚'
*标记偏厚区域
gen_rectangle2_contour_xld (bigRectangle, subset(centerY,bigIndexs), subset(centerX,bigIndexs), gen_tuple_const(|bigIndexs|,Phi),subset(fishWidth,bigIndexs)/2,gen_tuple_const(|bigIndexs|,40) )
endif
tuple_strlen (str, Length)
*显示轮廓与十字线
dev_set_color ('orange')
set_line_style (WindowHandle, [5,2])
dev_display (Rectangle1)
set_line_style (WindowHandle, [])
*符合标准的区域
dev_set_color ('green')
dev_display (centerCross)
normalIndexs:=[0:|fishWidth|-1]
smallNum:=0
bigNum:=0
if(noiseIndex!=-1)
tuple_remove (normalIndexs, noiseIndex, normalIndexs)
noiseNum:=|noiseIndex|
endif
if(bigIndexs!=-1)
tuple_remove (normalIndexs, bigIndexs, normalIndexs)
bigNum:=|bigIndexs|
endif
if(smallIndexs!=-1)
tuple_remove (normalIndexs,smallIndexs, normalIndexs)
smallNum:=|smallIndexs|
endif
gen_rectangle2_contour_xld (normalRectangle, subset(centerY,normalIndexs), subset(centerX,normalIndexs), gen_tuple_const(|normalIndexs|,Phi),subset(fishWidth,normalIndexs)/2,gen_tuple_const(|normalIndexs|,40) )
dev_display (normalRectangle)
dev_set_color ('red')
dev_display (borderCross)
*偏大的区域
dev_display (bigRectangle)
if(Length!=0)
disp_message (WindowHandle,'异常原因:'+ str, 'window', offsetRow, 20,'white', 'false')
offsetRow:=offsetRow+25
endif
disp_message (WindowHandle, '标准数量:'+fishNum, 'window', offsetRow,20, 'white', 'false')
offsetRow:=offsetRow+25
disp_message (WindowHandle, '实际数量:'+(|fishWidth|-noiseNum), 'window', offsetRow, 20,'orange', 'false')
disp_message (WindowHandle, '合格数量:'+(|fishWidth|-noiseNum-smallNum-bigNum), 'window', offsetRow, 160,'green','false')
disp_message (WindowHandle, '偏薄数量:'+ smallNum, 'window', offsetRow, 300, 'red', 'false')
disp_message (WindowHandle, '偏厚数量:'+bigNum, 'window', offsetRow,430, 'red', 'false')
dev_set_colored (12)
stop ()
endfor
Matlab


4,Fish长度检查。
*参考案例库:check_fish_stick_dimension.hdev
*目的:
*检查鱼生的长度是否在规定的范围内
*----------------------------1,标准参数
*相机坐标与世界坐标的比例关系
cm_per_pix := 0.0373
*鱼生标准长度
TargetLength := 9.0
*上限容差
ToleranceHigh := 0.8
*下限容差
ToleranceLow := 0.2
*----------------------------2,读取图片
dev_close_window ()
read_image (Image, 'food/fish_sticks_raw_01')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_update_window ('off')
dev_set_line_width (2)
for Index := 1 to 10 by 1
read_image (Image, 'food/fish_sticks_raw_'+Index$'02')
dev_display (Image)
threshold (Image, Region, 70, 255)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 99999)
fill_up (SelectedRegions, RegionFillUp)
*获取图像边界,计算是否有超过边界的fish
boundary (Image, RegionBorder, 'inner')
*计算边界与fish的交集,如果交集的面积大于0则表示存在fish超过视野
intersection ( RegionFillUp,RegionBorder, RegionIntersection)
area_center (RegionIntersection, Area, Row, Column)
*完全在视野内的fish
validRegionIndex:=find(sgn(Area),0)
*与视野边界相交的fish
select_tuple_large (Area, 0, regionAtBoundaryIndices)
*计算处理完全在视野内的fish
select_obj (RegionFillUp, validRegion, validRegionIndex+1)
smallest_rectangle2 (validRegion, Row1, Column1, Phi, Length1, Length2)
*fish长度由相机坐标转化为世界坐标
fishLenght:=Length1*2*cm_per_pix
*各区域的索引
select_tuple_large (fishLenght, TargetLength-ToleranceLow, goodIndices)
select_tuple_large (fishLenght, TargetLength+ToleranceHigh, badIndices)
select_tuple_large (-fishLenght, -TargetLength+ToleranceLow, badIndices2)
tuple_remove (goodIndices, badIndices, goodIndices)
badIndices:=[badIndices,badIndices2]
*------------------3,显示结果
msg:='标准长度:'+TargetLength$'.1f'+'cm'
msg[1]:='误差范围:+'+ToleranceHigh$'.1f'+' / -'+ToleranceLow$'.1f'
disp_message (WindowHandle, msg, 'window', 20,20, 'black', 'true')
*标记完全处于视野内合格的区域
if(|goodIndices|!=0)
dev_set_color ('green')
gen_rectangle2_contour_xld (Rectangle,subset( Row1,goodIndices),subset( Column1,goodIndices) ,subset( Phi,goodIndices) , subset( Length1,goodIndices), subset( Length2,goodIndices))
dev_display (Rectangle)
* disp_message (WindowHandle, 'ok', 'window', subset( Row1,goodIndices),subset( Column1,goodIndices), 'green', 'false')
print_message (WindowHandle, subset( Row1,goodIndices), subset( Column1,goodIndices), 'OK', subset( fishLenght,goodIndices), 'green')
endif
*标记完全处于视野内但长度不合格的区域
if(|badIndices|!=0)
dev_set_color ('red')
gen_rectangle2_contour_xld (Rectangle,subset( Row1,badIndices),subset( Column1,badIndices) ,subset( Phi,badIndices) , subset( Length1,badIndices), subset( Length2,badIndices))
dev_display (Rectangle)
* disp_message (WindowHandle, 'ok', 'window', subset( Row1,badIndices),subset( Column1,badIndices), 'red', 'false')
print_message (WindowHandle, subset( Row1,badIndices), subset( Column1,badIndices), 'NG', subset( fishLenght,badIndices), 'red')
endif
*标记处于视野界线上的区域
if(|regionAtBoundaryIndices|!=0)
dev_set_color ('yellow')
select_obj ( RegionFillUp, regionAtBoundary, regionAtBoundaryIndices+1)
gen_contour_region_xld (regionAtBoundary, Contours, 'border')
dev_display (Contours)
endif
dev_set_colored (12)
stop()
endfor
XML

自定义的本地函数。
print_message(operator)
for i := 0 to |Rows|-1 by 1
dev_set_color (color)
disp_message (WindowHandle, result, 'window', Rows[i]-20, Columns[i]-10, color, 'false')
disp_message (WindowHandle, values[i]$'0.1f'+'cm', 'window', Rows[i]+10, Columns[i]-20, color, 'false')
endfor
return ()
XML
select_tuple_large (operator)
tuple_find (sgn(Tuple - Value), 1, Indices)
if (Indices[0] == -1)
Indices := []
endif
return ()
XML

5,塑料薄片异常点检查。
*参考案例库:detect_indent_fft.hdev
*目的:
*检查塑料制品表面的缺陷
dev_close_window ()
read_image (Image, 'plastics/plastics_01')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_set_line_width (2)
*创建高斯滤波器
gen_gauss_filter (ImageGauss2, 3, 3, 0, 'n', 'dc_center', Width, Height)
dev_update_window ('off')
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
for Index := 1 to 11 by 1
read_image (Image1, 'plastics/plastics_'+Index$'02')
dev_display (Image1)
rgb1_to_gray (Image1, GrayImage)
fft_generic (GrayImage, ImageFFT, 'to_freq', -1, 'none', 'dc_center', 'complex')
convol_fft (ImageFFT, ImageGauss2, ImageConvol)
*获取去噪后的空间域常使用real(仅包含幅值信息)作为输出类型。
fft_generic (ImageConvol, ImageFFT1, 'from_freq', 1, 'none', 'dc_center', 'real')
*计算输入图像的灰度值范围,即每个图像点在大小为(MaskHeight, Maskwidth)的矩形掩模内的
*最大和最小灰度值的差值(max - min)。得到的图像在ImageResult中返回。
gray_range_rect (ImageFFT1, ImageResult, 11, 11)
min_max_gray (ImageResult, ImageResult, 0, Min, Max, Range)
threshold (ImageResult, Region, max([ Max*0.8,5.8]), 255)
connection (Region, ConnectedRegions)
opening_circle (ConnectedRegions, RegionOpening, 2)
smallest_circle (RegionOpening, Row, Column, Radius)
select_shape (RegionOpening, SelectedRegions, 'area', 'and', 10, 99999)
count_obj (SelectedRegions, Number)
if(Number!=0 )
dev_set_color ('red')
gen_circle_contour_xld (ContCircle, Row, Column, Radius*3, 0, rad(360), 'positive', 1)
dev_display (ContCircle)
disp_message (WindowHandle, 'not ok', 'window',20, 20, 'red', 'true')
else
disp_message (WindowHandle, 'ok', 'window',20, 20, 'green', 'true')
endif
dev_set_colored (12)
stop ()
endfor
XML


6, 药丸检测。
*参考案例库:Check_blister.hdev
*对药丸进行检测
dev_close_window ()
read_image (Image, 'blister/blister_01')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_display (Image)
dev_set_draw ('margin')
dev_set_line_width (2)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
*---------------------1,获取标准图像与区域位置
decompose3 (Image, R, G, B)
threshold (B, Region, 100, 255)
connection (Region, ConnectedRegions)
*获取感兴趣区域
select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
shape_trans (SelectedRegions, RegionTrans, 'convex')
*获取仿射变换矩阵
orientation_region (RegionTrans, Phi)
area_center (RegionTrans, Area, staRow, staColumn)
vector_angle_to_rigid (staRow, staColumn, Phi, staRow, staColumn, 0, HomMat2D)
*图片仿射变化
affine_trans_image (B, staImageAffinTrans, HomMat2D, 'constant', 'false')
*区域仿射变化
affine_trans_region (RegionTrans, staRegion, HomMat2D, 'nearest_neighbor')
area_center (staRegion, Area1, refRow, refColumn)
orientation_region (staRegion, refPhi)
*--------------------2,设置感兴趣区域
gen_empty_obj (Chambers)
for i := 0 to 4 by 1
for j := 0 to 2 by 1
gen_rectangle1 (Rectangle, 62+i*70, 145+j*150, 122+i*70, 270+j*150)
concat_obj (Chambers, Rectangle, Chambers)
endfor
endfor
union1 (Chambers, RoiRegion)
*-------------------3,进行识别
read_image (Image1, 'blister/blister_'+[1:6]$'02')
count_obj (Image1, Number)
for Index := 1 to Number by 1
dev_set_colored (12)
select_obj (Image1, image, Index)
decompose3 (image, tempR, tempG, tempB)
threshold (tempB, tempRegion, 100, 255)
connection (tempRegion, ConnectedRegions1)
select_shape_std (ConnectedRegions1, SelectedRegions1, 'max_area', 0)
shape_trans (SelectedRegions1, tempRegion, 'convex')
orientation_region (tempRegion, tempPhi)
area_center (tempRegion, Area2, tempRow, tempColumn)
vector_angle_to_rigid (tempRow, tempColumn, tempPhi, refRow, refColumn, refPhi, HomMat2D1)
*仿射变换
affine_trans_image (tempB, ImageAffinTrans, HomMat2D1, 'constant', 'false')
affine_trans_image (image, ImageAffinTrans1, HomMat2D1, 'constant', 'false')
*裁剪感兴趣区域
reduce_domain (ImageAffinTrans,RoiRegion , ImageReduced)
var_threshold (ImageReduced, Region1, 15, 15, 0.2, 2, 'dark')
dev_clear_window ()
fill_up (Region1, RegionFillUp)
opening_circle (RegionFillUp, RegionOpening, 3.5)
connection (RegionOpening, ConnectedRegions2)
select_shape (ConnectedRegions2, SelectedRegions2, 'area', 'and', 426.61, 50000)
shape_trans (SelectedRegions2, RegionTrans1, 'convex')
union1 (RegionTrans1, BlisterRegionUnion)
*进行计算
gen_empty_obj (wrongBlister)
gen_empty_obj (missBlister)
gen_empty_obj (passBlister)
count_obj (Chambers, ChambersNumber)
for k := 1 to ChambersNumber by 1
select_obj (Chambers, Chamber, k)
intersection (Chamber, BlisterRegionUnion, BlisterRegion)
*计算交集的区域面积与灰度值
area_center (BlisterRegion, Area3, Row, Column)
if(Area3>0)
min_max_gray (BlisterRegion, ImageReduced, 0, Min, Max, Range)
if(Area3<3700 or Min<60)
*异常的药丸
concat_obj (wrongBlister, BlisterRegion, wrongBlister)
else
*ok的药丸
concat_obj (passBlister, Chamber, passBlister)
endif
else
*缺失
concat_obj (missBlister, Chamber,missBlister)
endif
endfor
*------------------结果显示
dev_display (ImageAffinTrans1)
count_obj (missBlister, missCount)
count_obj (passBlister, passCount)
count_obj (wrongBlister, wrongCount)
dev_set_color ('red')
dev_display (missBlister)
dev_set_color ('yellow')
dev_display (wrongBlister)
dev_set_color ('green')
dev_display (passBlister)
disp_message (WindowHandle, '标准数量:'+ChambersNumber, 'window', 20, 20, 'white', 'false')
disp_message (WindowHandle, '合格数量:'+passCount, 'window', 50, 20, 'green', 'false')
disp_message (WindowHandle, '异常数量:'+wrongCount, 'window', 80, 20, 'yellow', 'false')
disp_message (WindowHandle, '缺失数量:'+missCount, 'window', 110, 20, 'red', 'false')
stop ()
endfor
XML


全部评论 (0)
还没有任何评论哟~
