Halcon检测PCB上每个包含3个不同圆(内,中,外)的圆孔的轮廓及半径信息,并自动存入csv文件

利用Halcon语言检测PCB上每个包含3个不同圆的圆孔的轮廓及半径信息,识别多张待测图片(若不是二值图片,需要在代码中加入二值化预处理),进行检测处理,并将每张图片的内圆、中圆、外圆的平均半径自动输出到csv文件中。

图中是利用xld的方法,用canny检测轮廓,提取边缘,根据特征选择边缘,保留有用的圆轮廓,进行拟合,计算半径,在CSV中循环写入半径数据。

**检测到内圆,中圆,外圆轮廓信息,放大选择区域进行检测
**每出现一个图像需要收到选择一个矩形ROI(不要这个操作,效果不变,但看得更直观清楚),
*识别完轮廓信息,点运行,等下一个图像出现
*不需要看图像识别效果或者不要手动点运行直接到最后结果可以去掉stop()
dev_close_window ()
dev_update_off ()

**路径改为本地路径
**将所有圆半径数据csv文件,观察各圆半径数据,分别确定下文的三类圆的最小最大范围(划分)
fileName0:='D:/work1/work01.csv'
file_exists (fileName0, FileExists)
if(FileExists)
    delete_file(fileName0)
endif
open_file (fileName0, 'append', FileHandle0)
*输入表头信息
string:=['图像路径','所有圆半径']
for t:=0 to |string|-1 by 1
    fwrite_string (FileHandle0, string[t]+',')
endfor
fwrite_string (FileHandle0, '\n')


**将半径信息存入csv文件,每张图的平均内,中,外圆半径数据
fileName:='D:/work1/work02.csv'
file_exists (fileName, FileExists)
if(FileExists)
    delete_file(fileName)
endif
open_file (fileName, 'append', FileHandle)
string:=['图像路径','内圆平均半径','中圆平均半径','外圆平均半径'] 
for t:=0 to |string|-1 by 1
    fwrite_string (FileHandle, string[t]+',')
endfor
*换行,下一行将存入图像信息和半径数据
fwrite_string (FileHandle, '\n')

**从本地文件路径中选择一个图像文件
* dev_open_file_dialog ('read_image', 'default', 'default', Selection)
* read_image (Image, Selection)

*循环读取文件夹中的文件目录,改成自己存有多张待测图片的文件夹
list_files ('D:/work1/Holesimages', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)

for Index := 0 to |ImageFiles| - 1 by 1
    read_image (Imageori, ImageFiles[Index])
    * Image Acquisition 01: Do something
    get_image_size (Imageori, Width, Height)
    dev_open_window (0, 0, Width/4, Height/4, 'black', WindowHandle)
    dev_display (Imageori)
*    set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    
    *选择目标区域的矩形区域ROI,鼠标选择
    draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
    *获取选择的矩形
    gen_rectangle1 (ModelRegion, Row1, Column1, Row2, Column2)
    *分割图像,去除不需要识别的区域,减少噪声
    reduce_domain (Imageori, ModelRegion, Image)
    *修改显示区域,只放大区域,不放大图像,图像中坐标尺寸信息未改变
    dev_set_part (Row1, Column1, Row2, Column2)

*     dev_display (Image)
*     emphasize (ModelRegionImage, Image, 7, 7, 1)
    dev_display (Image)

 **2.直接将整幅图像转化成xld,再一步步挑选自己想要的xld
    **提取亚像素精确边缘,根据自己的图像特征调节阈值,太大或太小都可能漏检或多检
    edges_sub_pix (Image, Edges, 'canny', 1.15, 5, 10)
    *将一个XLD轮廓分割为直线段、圆(圆弧)、椭圆弧
    segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 5, 4, 2)
    *使用圆特征选择圆轮廓
    select_shape_xld (ContoursSplit, Holes, 'circularity', 'and', 0.1, 1.0)
    **去除半径过小和过大的噪声,可以从所有半径(未平均处理)数据中得出大概的最小值26和最大值51
    select_shape_xld (Holes, Holes, 'ra', 'and', 20, 60)
    *合并空隙较小的轮廓
    union_adjacent_contours_xld(Holes, Holes, 10, 1, 'attr_keep')
    **同一个圆的多段圆弧轮廓会拟合为多个圆,以周长更长的圆弧拟合为准,去除短圆弧段,
    **保留比最小圆周长大的轮廓(2*20*3.14),不追求精确的话算一个大概范围就好
    select_shape_xld (Holes, Holes, 'contlength', 'and', 130, 999)
    *根据筛选好的轮廓拟合出圆,输出坐标半径信息
    fit_circle_contour_xld(Holes, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
    *创建拟合圆
    gen_circle(CircleHoles, Row, Column, Radius)
    *显示拟合圆(仅显示轮廓)
    dev_set_line_width(2)
    dev_set_draw('margin')
    dev_display (CircleHoles)
    count_obj (CircleHoles, Number)

 tuple_sort (Radius, sRadius)
    
   *把所有圆的半径数据(57个)存表
    fwrite_string (FileHandle0, ImageFiles[Index]+',')
    for i:=0 to |sRadius|-1 by 1
         fwrite_string (FileHandle0, sRadius[i]+',')
    endfor
    fwrite_string (FileHandle0, '\n')
   
    Radiusmin:=[]
    Radiusmed:=[]
    Radiusmax:=[]
    Radiusfal:=[]
    *分类所有识别到的圆轮廓,内圆,中圆,外圆
    for n:=0 to Number-1 by 1
        if (sRadius[n]>=27 and sRadius[n]<=29)
            for m:=0 to Number-1 by 1
                Radiusmin[m]:=sRadius[n]
            endfor
        elseif (sRadius[n]>=41 and sRadius[n]<=43)
            for d:=0 to Number-1 by 1
                Radiusmed[d]:=sRadius[n]
            endfor
        elseif (sRadius[n]>=48 and sRadius[n]<=50)
            for x:=0 to Number-1 by 1
                Radiusmax[x]:=sRadius[n]
            endfor
        else
            for f:=0 to Number-1 by 1
                Radiusfal[f]:=sRadius[n]
            endfor
        endif      
    endfor
    
    *求所有内圆平均半径,中圆平均半径
    tuple_mean (Radiusmin, AvgRmin)
    tuple_mean (Radiusmed, AvgRmed)
    tuple_mean (Radiusmax, AvgRmax)
    disp_message (WindowHandle, 'AvgRmin:'+AvgRmin, 'window', 0, -1, 'black', 'true')
    disp_message (WindowHandle, 'AvgRmed:'+AvgRmed, 'window', 20, -1, 'black', 'true')
    disp_message (WindowHandle, 'AvgRmax:'+AvgRmax, 'window', 40, -1, 'black', 'true')
    disp_message (WindowHandle, 'Number:'+Number, 'window', 60, -1, 'black', 'true')
    *可以看每张图像识别效果,需要点F5才能继续下一步
    stop()
    
    Param:=[AvgRmin,AvgRmed,AvgRmax]
    **在csv文件填入各类圆的平均半径数据
    fwrite_string (FileHandle, ImageFiles[Index]+',')
    for j:=0 to |Param|-1 by 1
         fwrite_string (FileHandle, Param[j]+',')
    endfor
    fwrite_string (FileHandle, '\n')

endfor

*填写完成,关闭csv文件
close_file(FileHandle)
dev_close_window ()

原创不易,这个创作也试验了很多次才完成的,转载请标明出处,谢谢!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值