Halcon光度立体技术

Posted QtHalcon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Halcon光度立体技术相关的知识,希望对你有一定的参考价值。

 在工业领域,表面检测是一个非常广泛的应用领域。在halcon中使用增强的光度立体视觉方法,三维表面检测被加强。利用阴影可方便快速的检测物体表面的缺口或凹痕。 使用光度立体视觉方法可在复杂图像中轻松找到表面缺陷 。

1 光度立体

    典型应用:

    光度立体的典型应用是检测表面中代表缺陷的微小不一致,或者从使用的图像中排除光的方向的影响,例如,用于非平面字符的打印检查。请注意,光度立体不适合绝对高度的重建,即它不能替代典型的3D重建算法,如焦点深度或光片。

    局限性:

    hanlcon的光度立体它基于Woodham的算法,因此一方面假设相机执行正交投影。也就是说,必须使用远心镜头或具有长焦距的镜头。另一方面,它假设每个光源都提供平行且均匀的光束。也就是说,必须使用强度均匀的远心照明光源,或者作为替代的远距离点光源。此外,物体必须具有朗伯反射率特性,即它必须以漫射方式反射入射光。具有镜面反射特性(即镜面或光面)的对象或对象区域无法正确处理,从而导致错误的结果。

    采集:

    带有远心镜头的相机必须正交放置,即垂直于应重建的场景。在采集图像期间,相机相对于场景的方向不得改变。相反,对于至少三个灰度值图像,照明相对于相机的方向必须改变。

    照明方向:

    对于每个图像,照明方向必须指定为参数内的角度Slants和Tilts,它描述了照明相对于场景的方向。

    Slants是相机的光轴与照明方向之间的角度,如下:

    Tilts是在对象平面或任何平行于它的平面内测量的,例如,图像平面。特别是,它描述了从图像中心指向右侧的方向与投射到平面中的光的方向之间的角度。也就是说,在查看图像(或相应的场景)时,倾斜角度为0表示光线来自右侧,倾斜角度为90表示光线来自顶部,倾斜角度为180表示光线来自左侧,依此类推。如下:

    光度立体至少需要三个具有不同照明方向的图像,太多照明方向会导致处理时间增加,最好是4~6个方向,Slants角度在30°~60°之间,Tilts角度均匀分布在物体周围,实际应用中可以如下架设光源:

    用到的算子:


//使用光度立体法重建表面
void PhotometricStereo(const HObject& Images, //输入图像
  HObject* HeightField,               //重建的高度字段
  HObject* Gradient,                  //曲面的梯度场
  HObject* Albedo,                    //表面的反照率
  const HTuple& Slants,               //相机与照明方向之间的角度
  const HTuple& Tilts,                //对象平面内照明方向的角度
  const HTuple& ResultType,           //请求结果的类型
  const HTuple& ReconstructionMethod, //重建方法
  const HTuple& GenParamName,         //一般参数名称
  const HTuple& GenParamValue)        //一般参数设置
//梯度场转平均曲率场
void DerivateVectorField(
  const HObject& VectorField,  //梯度场图像
  HObject* Result,             //返回平均曲率场图像
  const HTuple& Sigma,         //高斯系数
  const HTuple& Component)     //组件计算

2 识别字符

    有的银行卡背面的数字,如果采用常规的Blob分析或者频域等方法,是很难达到目的的,但是采用光度立体就能比较容易的将前景和背景分离。

    测试代码:


dev_update_off ()
ImageFiles := []
ImageFiles[0] := './1.png'
ImageFiles[1] := './2.png'
ImageFiles[2] := './3.png'
ImageFiles[3] := './4.png'
gen_empty_obj (Images)
for Index := 0 to |ImageFiles| - 1 by 1
       read_image (Image, ImageFiles[Index])      
       concat_obj (Images, Image, Images)  
       wait_seconds (0.3)
       *dev_display (Image)
endfor
Slants:=[45,45,45,45]
Tilts:=[0,90,180,270]
* 光度立体法
photometric_stereo (Images, HeightField, Gradient, Albedo, Slants, Tilts, 'all', 'poisson', [], [])
* 梯度场转平均曲率场
derivate_vector_field (Gradient, Result, 1, 'mean_curvature')
* 镜像
mirror_image (Result, Image, 'row')
mirror_image (Image, ImageMirror, 'column')
* 将灰度值分布在0到255之间
scale_image_max (ImageMirror, ImageScaleMax)
* 尝试在频域中继续处理
fft_generic (ImageScaleMax, ImageFFT, 'to_freq', -1, 'sqrt', 'dc_center', 'complex')
* 得到背景
get_image_size (ImageFFT, Width, Height)
gen_gauss_filter (ImageGauss, 10, 10, 0, 'none', 'dc_center', Width, Height)
gen_lowpass (ImageLowpass, 0.05, 'none', 'dc_center', Width, Height)
convol_fft (ImageFFT, ImageGauss, ImageConvol)
fft_generic (ImageConvol, ImageBackground, 'from_freq', 1, 'sqrt', 'dc_center', 'byte')
* 差分,去掉背景
sub_image (ImageScaleMax, ImageBackground, ImageSub, 1, 128)
median_image (ImageSub, ImageMedian, 'circle', 3, 'mirrored')

***字符识别
gen_rectangle1 (ROI_0, 629.385, 382.235, 852.788, 1515)
reduce_domain (ImageMedian, ROI_0, ImageReduced)
threshold (ImageReduced, Regions, 132, 205)

closing_circle (Regions, RegionClosing, 1.5)
connection (RegionClosing, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, ['area','width'], 'and', [850.44,14.96], [2000.01,53.38])
sort_region (SelectedRegions, SortedRegions, 'character', 'true', 'row')

reduce_domain (ImageReduced, SelectedRegions, ImageReduced1)

paint_region (ImageReduced, ImageReduced, WihteBackground, 255, 'fill')
paint_region (SortedRegions, WihteBackground, ImageResult, 0, 'fill')

read_ocr_class_mlp ('Industrial_0-9_NoRej.omc', OCRHandle)
do_ocr_multi_class_mlp (SortedRegions, ImageResult, OCRHandle, Class, Confidence)

dev_display (ImageResult)
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 26, 'mono', 'true', 'false')
disp_message (WindowHandle, '由光度立体法求得:', 'image', 12, 12, 'black', 'true')
disp_message (WindowHandle, '卡号:'+sum(Class), 'image', 162, 12, 'black', 'true')
dev_update_on ()

结果如下:

3 缺陷检测

    有的表面缺陷检测可以用光度立体法去解决

    测试代码:


*用于检查药物泡罩背面。
*输入4张从药泡背面拍摄的图像
dev_close_window ()
dev_update_off ()
*创建窗口
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*设置字体
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')

* 读取不同角度拍摄的图像
read_image (Images, 'photometric_stereo/blister_back_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参数是俯视图看光源的角度
Tilts := [6.1,95.0,-176.1,-86.8]
*Slants参数是主视图看光源的角度
Slants := [41.4,42.6,41.7,40.9]
*请求结果的类型。“梯度”,“反照率”
ResultType := ['gradient','albedo']

*核心算子
photometric_stereo (Images, HeightField, Gradient, Albedo, Slants, Tilts, ResultType, 'poisson', [], [])
* 
*显示反照率图像
dev_display (Albedo)
disp_message (WindowHandle, 'Albedo image', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
*显示这张图片之后,有很多种方式去检测这张图片

* 计算曲面的高斯曲率
*使用梯度场作为操作符的输入
* derivate_vector_field。
*缺陷通常很容易在曲率图像中检测出来。
derivate_vector_field (Gradient, GaussCurvature, 1, 'gauss_curvature')
*使用区域分割的图像。
regiongrowing (GaussCurvature, Regions, 1, 1, 0.001, 250)
*选择宽度和高度都在150-200之间的图像
select_shape (Regions, TabletRegions, ['width','height'], 'and', [150,150], [200,200])
*形成一个凸形区域
shape_trans (TabletRegions, TabletRegions, 'convex')
*区域进行联合
union1 (TabletRegions, TabletRegions)
*以3.5的圆形进行腐蚀区域(减小region)
erosion_circle (TabletRegions, TabletRegions, 3.5)
*减少图像区域
reduce_domain (GaussCurvature, TabletRegions, ImageReduced)
*计算图像的绝对值(模数)。
abs_image (ImageReduced, ImageAbs)
*阈值分割
threshold (ImageAbs, Region, 0.03, 255)
*圆的闭运算
closing_circle (Region, RegionClosing, 10.5)
*将检测区域进行分离
connection (RegionClosing, ConnectedRegions)
*选择其中像素大小在10-99999之间的区域,就是error区域
select_shape (ConnectedRegions, Defects, 'area', 'and', 10, 99999)
*找到该区域的中心
area_center (Defects, Area, Row, Column)
*以中心为圆的中心,画一个半径
gen_circle (Circle, Row, Column, gen_tuple_const(|Row|,20.5))

dev_set_draw ('margin')
dev_set_color ('red')
dev_set_line_width (2)
dev_display (GaussCurvature)
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')

    结果如下:

以上是关于Halcon光度立体技术的主要内容,如果未能解决你的问题,请参考以下文章

photometric_stereo halcon光度立体法三维表面重建

详细的光度立体法以及实现

直接法光度误差导数推导

光度学原理

光圈快门感光度

手机拍照参数的调整