检测键盘按键的网格的交叉点

对应示例程序:
measure_grid.hdev

目标:检测键盘按键的网格的交叉点
思路为:
      1.读取图像
      2.利用均值滤波 阈值分割 形态学处理 常用的Blob分析方法等,提取出网格区域
      3.计算网格区域的骨架,并筛选出目标轮廓
      4.根据轮廓拟合出所有的网格线,并根据角度将他们分成水平和垂直两个数组。再计算每条水平线和垂直线的交点,作为最终的结果。在例程中,还根据先验知识,对交点做了判断,如果交点到直线的距离小于某个值,才是正确的交点。目的是去掉拟合不正确导致的错误交点。
      5.最后例程中提供了另一种思路,即根据提取出的骨架,直接取骨架线间的交点,作为最终的检测结果。

图像:
在这里插入图片描述
在这里插入图片描述

代码:

dev_update_off ()
* 
* step: acquire image
* 
read_image (Image, 'keypad')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_display (Image)
* 
* step: initialize visualization
* 
dev_set_colored (3)
dev_set_draw ('fill')
* 
* step:extract the region of the grid
*提取网格区域   阈值分割 形态学处理 常用的Blob分析方法

mean_image (Image, ImageMean, 7, 7)        //均值滤波
dyn_threshold (Image, ImageMean, RegionDynThresh, 4, 'dark')  //局部阈值分割

connection (RegionDynThresh, ConnectedRegions)   //连通域分割
//筛选
select_shape (ConnectedRegions, SelectedRegions, ['max_diameter','contlength'], 'and', [200,800], [99999,99999])
closing_circle (SelectedRegions, RegionClosing, 1.5)  //闭操作
dev_display (Image)
dev_display (RegionClosing)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* step:extract the contours of the grid
* 提取出网格轮廓
skeleton (RegionClosing, Skeleton)  //取区域的骨架
gen_contours_skeleton_xld (Skeleton, ContoursSkeleton, 1, 'filter')  //将骨架转换为XLD轮廓
segment_contours_xld (ContoursSkeleton, ContoursSplitSkeleton, 'lines', 5, 2, 1) //将XLD轮廓分成线段
select_contours_xld (ContoursSplitSkeleton, SelectedContours, 'contour_length', 30, 1000, -0.5, 0.5) //筛选
union_collinear_contours_xld (SelectedContours, UnionCollinearContours, 100, 10, 20, rad(10), 'attr_keep')  //合并相近的XLD轮廓
dev_display (Image)
dev_display (UnionCollinearContours)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* step:fit lines to the contours
* 拟合网格线
count_obj (UnionCollinearContours, NumberContours)
gen_empty_obj (LinesHorizontal)   //水平线的数组
gen_empty_obj (LinesVertical)     //垂直线的数组
for i := 1 to NumberContours by 1
    select_obj (UnionCollinearContours, ObjectSelected, i)  //对每条线进行处理
    //拟合直线
    fit_line_contour_xld (ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
    //画线段
    gen_contour_polygon_xld (Contour, [RowBegin,RowEnd], [ColBegin,ColEnd])
    Phi := atan2(-Nr,Nc)
    if (abs(Phi) < rad(5)) //如果角度小于5度 就划分到垂直数组
        concat_obj (LinesVertical, Contour, LinesVertical)
    endif
    if (rad(85) < abs(Phi) and abs(Phi) < rad(95))  //如果角度大于85度,小于95个 就划分到水平数组
        concat_obj (LinesHorizontal, Contour, LinesHorizontal)
    endif
endfor

*结果显示
dev_display (Image)
dev_set_color ('red')
dev_display (LinesVertical)
dev_set_color ('yellow')
dev_display (LinesHorizontal)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* step:extract junction points of the grid
* 取网格线之间的交点  要计算水平线和垂直线的全部交点  用双层循环
RowJunction := []
ColJunction := []
RowRealJunction := []
ColRealJunction := []
count_obj (LinesHorizontal, NumberLH)  //统计水平线的数量
count_obj (LinesVertical, NumberLV)    //统计垂直线的数量
for i := 1 to NumberLH by 1
    select_obj (LinesHorizontal, HorizontalLine, i)
    get_contour_xld (HorizontalLine, RowHorizontal, ColHorizontal)  //取水平线的坐标
    for j := 1 to NumberLV by 1
        select_obj (LinesVertical, VerticalLine, j)
        get_contour_xld (VerticalLine, RowVertical, ColVertical)  //取垂直线的坐标
        //计算水平线和垂直线的交点
        intersection_lines (RowHorizontal[0], ColHorizontal[0], RowHorizontal[1], ColHorizontal[1], RowVertical[0], ColVertical[0], RowVertical[1], ColVertical[1], Row, Column, IsOverlapping)
        //计算交点到直线的距离
        distance_ps (Row, Column, RowHorizontal[0], ColHorizontal[0], RowHorizontal[1], ColHorizontal[1], DistanceH, DistanceHMax)
        distance_ps (Row, Column, RowVertical[0], ColVertical[0], RowVertical[1], ColVertical[1], DistanceV, DistanceVMax)
        RowJunction := [RowJunction,Row]   //把交点放进一个统一的数组中,用于后面的显示
        ColJunction := [ColJunction,Column]
        if ((DistanceH <= 30) and (DistanceV <= 30))  //只有距离小于30的点才是合理的 ,用于去掉错误结果
            RowRealJunction := [RowRealJunction,Row]
            ColRealJunction := [ColRealJunction,Column]
        endif
    endfor
endfor
dev_set_color ('white')
gen_cross_contour_xld (Cross, RowJunction, ColJunction, 12, 0.785398) //画十字交点
dev_display (Cross)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_display (Image)
dev_set_color ('gray')
dev_display (LinesHorizontal)
dev_display (LinesVertical)
dev_set_color ('white')
gen_cross_contour_xld (Cross, RowRealJunction, ColRealJunction, 12, 0.785398)
dev_display (Cross)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* or via region processing, starting with the
* skeleton obtained above
* 或者通过区域处理,从上面获得的骨架开始
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_display (Image)
junctions_skeleton (Skeleton, EndPoints, JuncPoints) //在骨架中查找连接点和端点
//骨架间的连接点就是所求的交叉点
get_region_points (JuncPoints, RowJunctionRegionProcessing, ColumnJunctionRegionProcessing)
//画十字交点
gen_cross_contour_xld (CrossCenter, RowJunctionRegionProcessing, ColumnJunctionRegionProcessing, 12, 0.785398)
dev_set_color ('gray')
dev_display (Skeleton)
dev_set_color ('white')
dev_display (CrossCenter)
disp_message (WindowHandle, 'Result of corresponding', 'window', 40, 10, 'white', 'false')
disp_message (WindowHandle, 'region processing', 'window', 90, 10, 'white', 'false')

用到的几个算子:
      skeleton --取区域的骨架
       union_collinear_contours_xld --合并相近的XLD轮廓
       junctions_skeleton --在骨架中查找连接点和端点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值