结合模板匹配与测量的剃须刀缺陷检测

模板匹配与测量

原图

模板图

在这里插入图片描述

检测图

在这里插入图片描述

代码

* ------------------------------------------------------------------------------------------------
*此示例程序使用基于形状的匹配来对齐度量的roi
*工具,然后检查单个刀片。

*该程序有两种运行模式:(1)全仿射变换
*2)采用平移测度
*修改下一行以在模式之间切换。

*该参数控制是否使用translate_measure
USING_TRANSLATE_MEASURE := 1
* ------------------------------------------------------------------------------------------------

dev_update_window ('off')
read_image (ModelImage, 'razors1')
get_image_pointer1 (ModelImage, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_display (ModelImage)
*显示设置
dev_set_color ('cyan')
dev_set_draw ('margin')
dev_set_line_width (2)
stop ()
* -------------------  start of the application  ----------------
* 模板对象确定
Row1 := 46
Column1 := 57
Row2 := 79
Column2 := 94
gen_rectangle1 (ROIPart1, Row1, Column1, Row2, Column2)
gen_rectangle1 (ROIPart2, Row1 + 364, Column1 + 13, Row2 + 364, Column2 + 13)
union2 (ROIPart1, ROIPart2, ModelROI)
area_center (ModelROI, Area, CenterROIRow, CenterROIColumn)
dev_display (ModelImage)
dev_display (ModelROI)
stop ()
* 建模
reduce_domain (ModelImage, ModelROI, ImageROI)
create_shape_model (ImageROI, 4, 0, 0, 'auto', 'none', 'use_polarity', 30, 10, ModelID)
inspect_shape_model (ImageROI, ShapeModelImage, ShapeModelRegion, 1, 30)
*通过get_shape_model_contours可知建立的模型中心在(0,0)处
get_shape_model_contours (ShapeModel, ModelID, 1)

dev_clear_window ()
dev_set_color ('blue')
dev_display (ShapeModelRegion)
stop ()
* 测量ROI区域确定
Rect1Row := 244
Rect1Col := 73
DistColRect1Rect2 := 17
Rect2Row := Rect1Row
Rect2Col := Rect1Col + DistColRect1Rect2
RectPhi := rad(90)
RectLength1 := 122
RectLength2 := 2
gen_rectangle2 (MeasureROI1, Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2)
gen_rectangle2 (MeasureROI2, Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2)
dev_display (ModelImage)
dev_set_color ('yellow')
dev_display (MeasureROI1)
dev_display (MeasureROI2)
***************************************************
**方法一:建模默认原点仿射变换时,平移模型区域中心到原点
*通过变量OriginalClipRegion保留原始参数属性,'clip_region'是否裁剪
* get_system ('clip_region', OriginalClipRegion)
* set_system ('clip_region', 'false')
*把建模的区域的中心移到0,0点,此时角度为0。以便后面的仿射变换
* move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn)
* move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn)
* set_system ('clip_region', OriginalClipRegion)

* DistRect1CenterRow := Rect1Row - CenterROIRow
* DistRect1CenterCol := Rect1Col - CenterROIColumn
* DistRect2CenterRow := Rect2Row - CenterROIRow
* DistRect2CenterCol := Rect2Col - CenterROIColumn
****************************************************
if (USING_TRANSLATE_MEASURE != 0)
   
    *测量对象生成一次,后续可以使用translate_measure继续使用
    gen_measure_rectangle2 (Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
    gen_measure_rectangle2 (Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
endif
stop ()
* find_shape_model模板匹配
read_image (SearchImage, 'razors2')
dev_display (SearchImage)
find_shape_model (SearchImage, ModelID, 0, 0, 0.8, 0, 0.5, 'least_squares', 0, 0.7, RowCheck, ColumnCheck, AngleCheck, Score)
if (|Score| > 0)
    for i := 0 to |Score| - 1 by 1
        * 方法一:建模默认原点仿射变换
        *vector_angle_to_rigid (0, 0, 0, RowCheck[i], ColumnCheck[i], AngleCheck[i], MovementOfObject)
         * affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, MovementOfObject)
         *方法二:建模区域不回原点,使用监视模型  
        vector_angle_to_rigid (CenterROIRow, CenterROIColumn, 0, RowCheck[i], ColumnCheck[i], AngleCheck[i], MovementOfObject)       
        affine_trans_region (ShapeModelRegion, ModelAtNewPosition, MovementOfObject, 'nearest_neighbor')
        dev_display (ModelAtNewPosition)
        
        * 方法二:建模区域不回原点 
        affine_trans_region (MeasureROI1, MeasureROI1AtNewPosition, MovementOfObject, 'constant')
        affine_trans_region (MeasureROI2, MeasureROI2AtNewPosition, MovementOfObject, 'constant')
        *方法一:建模默认原点仿射变换
       * affine_trans_region (MeasureROI1Ref, MeasureROI1AtNewPosition, MovementOfObject, 'constant')
       * affine_trans_region (MeasureROI2Ref, MeasureROI2AtNewPosition, MovementOfObject, 'constant')
        
        dev_display (MeasureROI1AtNewPosition)
        dev_display (MeasureROI2AtNewPosition)
        *方法一:建模默认原点仿射变换
*         affine_trans_pixel (MovementOfObject, DistRect1CenterRow, DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck)
*         affine_trans_pixel (MovementOfObject, DistRect2CenterRow, DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck)
        * 方法二:建模区域不回原点 
        affine_trans_pixel (MovementOfObject, Rect1Row, Rect1Col, Rect1RowCheck, Rect1ColCheck)
        affine_trans_pixel (MovementOfObject, Rect2Row, Rect2Col, Rect2RowCheck, Rect2ColCheck)
        
        
        if (USING_TRANSLATE_MEASURE != 0)
            * -> translate the already created measure objects
            *前面已经生成了测量对象,直接转换测量
            translate_measure (MeasureHandle1, Rect1RowCheck, Rect1ColCheck)
            translate_measure (MeasureHandle2, Rect2RowCheck, Rect2ColCheck)
            measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
            measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
        else
            * -> create new measure objects and destroy them after the measurement
            *每次测量生成测量对象
            RectPhiCheck := RectPhi + AngleCheck[i]
            gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
            gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
            * step 5: perform the measurement
            measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
            measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
            close_measure (MeasureHandle1)
            close_measure (MeasureHandle2)
        endif
        * step 6: check for too short or missing teeth
        NumberTeeth1 := |Width1|
        NumberTeeth2 := |Width2|
        dev_set_color ('red')
        *判断测量的边缘对数量是否不到37
        if (NumberTeeth1 < 37)
            for j := 0 to NumberTeeth1 - 2 by 1
                *如果边缘对宽度大于4,那么框选该部分并设置该部分区域在新窗口显示
                if (Distance1[j] > 4.0)
                    RowFault := round(0.5 * (RowEdge11[j + 1] + RowEdge21[j]))
                    ColFault := round(0.5 * (ColEdge11[j + 1] + ColEdge21[j]))
                    disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
                    dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
                    dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
                    dev_display (SearchImage)
                    disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
                    stop ()
                    dev_close_window ()
                    dev_set_part (0, 0, Height - 1, Width - 1)
                endif
            endfor
        endif
        if (NumberTeeth2 < 37)
            for j := 0 to NumberTeeth2 - 2 by 1
                if (Distance2[j] > 4.0)
                    RowFault := round(0.5 * (RowEdge12[j + 1] + RowEdge22[j]))
                    ColFault := round(0.5 * (ColEdge12[j + 1] + ColEdge22[j]))
                    disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
                    dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
                    dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
                    dev_display (SearchImage)
                    disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
                    stop ()
                    dev_close_window ()
                    dev_set_part (0, 0, Height - 1, Width - 1)
                endif
            endfor
        endif
        dev_set_color ('yellow')
        stop ()
    endfor
endif
* -------------------  end of the application  -----------------
* clean up
if (USING_TRANSLATE_MEASURE != 0)
    close_measure (MeasureHandle1)
    close_measure (MeasureHandle2)
endif
dev_update_window ('on')
clear_shape_model (ModelID)
dump_window (WindowHandle, 'png', '识别检测结果')

结果

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
电路城管理员语: 工程师屌丝必备的生活用品之一就是剃须刀,天天用,知道它的内部是如何工作的吗?看来看看瑞萨定制的奔腾剃须刀电路参考设计。 瑞萨官网参考设计: 工程师在购买剃须刀的时候虽然很多时候是奔着品牌去的,但是也要看看性能如何。 且看这款剃须刀和你们手中的性能有没有差别: 1小时快速恒流充电,充满后涓流 充电保护控制,防止过充电,损坏电池 避免过放电,Vb<2V,停止放电 适配器输出3.3V-3.6V、静态功耗<=1mA 检测充电电流,调节达到恒流,检测放电电流 俗话说外行看热闹,内行看门道,以上这些参数工程师们肯定不会陌生的吧。 那接下了看看此款剃须刀使用了哪款MCU吧? 78F9212—估计很多工程师对这个MUC不是很熟悉。78F9212隶属于NEC公司产品系列,该公司在2009年与瑞萨合并 它是78KOS微控制器中的8位单片机微控制器,具有单电压自编程FLASH存储和许多外围设备的特点。在此方案中用到了78F9212的内部10位 4通道的AD转换、GPIO口等。 剃须刀电路简易系统框图: 该方案中有非常重要的学习资料,分析了硬件电路中可以能出现的问题,比如:静态电流过大该如何处理、瞬变电压怎么抑制、放电回路存在静态电流大如何处理、电源反向保护在哪里等等,都在附件的应用手册中可以找到解决方法。 剃须刀作为男生的日常用品,这里给出了瑞萨官方的设计方案,有详细的代码可供参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值