【愚公系列】2023年04月 Halcon机器视觉-基于Halcon车牌识别


前言

1.Halcon是什么

Halcon是一种计算机视觉软件工具,用于图像处理、分析和机器视觉应用。它由德国MVTec公司开发,是一种功能强大的视觉软件工具,可用于解决各种计算机视觉问题,包括目标检测、图像识别、三维视觉等。Halcon支持多种编程语言,包括C++、C#、Python等,用户可以使用自己熟悉的编程语言进行开发和应用。

2.车牌识别

车牌识别系统是一种使用计算机视觉和图像处理技术来识别汽车车牌的系统。它可以快速准确地识别车牌号码,并将其记录到数据库中。这种系统通常用于交通管理、停车场管理和公共安全等领域。

3.车牌识别系统

车牌识别系统(Vehicle License Plate Recognition,VLPR) 是指能够检测到受监控路面的车辆并自动提取车辆牌照信息(含汉字字符、英文字母阿拉伯数字及号牌颜色)进行处理的技术。车牌识别是现代智能交通系统中的重要组成部分之一,应用十分广泛。它以数字图像处理、模式识别、计算机视觉等技术为基础,对摄像机所拍摄的车辆图像或者视频序列进行分析,得到每一辆汽车唯一的车牌号码,从而完成识别过程。通过一些后续处理手段可以实现停车场收费管理,交通流量控制指标测量,车辆定位,汽车防盗,高速公路超速自动化监管、闯红灯电子警察、公路收费站等等功能。对于维护交通安全和城市治安,防止交通堵塞,实现交通自动化管理有着现实的意义。

汽车牌照号码是车辆的唯一“身份”标识,牌照自动识别技术可以在汽车不作任何改动的情况下实现汽车“身份”的自动登记及验证,这项技术已经应用于公路收费、停车管理、称重系统、交通诱导、交通执法、公路稽查、车辆调度、车辆检测等各种场合。

一、基于Halcon车牌识别

1.车牌识别的流程

车牌识别步骤:

  1. 灰度化:

实际就是对原始车牌图片进行预处理,把彩色图片转化为黑白图片,然后对不符合指定阙值范围的灰度值进行过滤。

  1. 车牌定位:

这是技术难点之一,根据行业经验,定位车牌位置对于车牌的准确识别而言实际上就成功了60%。很多车牌识别的产品都对车牌的定位预留了很多配置参数,例如截取原始图片的位置参数、车牌的长宽比例、大小等等,这些都是为了提高车牌定位的准确率。

  1. 字符分割:

车牌定位后是字符分割,使用的识别过程是:对定位的车牌位置进行降噪处理=>边界模糊=>从右向左找出前6个封闭的图形=>剩余的封闭图形综合为一个图形进行汉字的识别。

  1. 字符识别:

就是根据字符模板进行模板匹配,因此需预先建立相应的字符模板。基于图像进行字符识别也可配置很多参数来大大提高字符的识别率。例如限定车牌头的字符,车牌各位字符的识别优先级等等。

二、车牌识别前预处理

dev_close_window ()
***** ----------------0.读取图片
dev_close_window ()
read_image (Image, '../素材/chepai18.jpg')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)
***** ----------------1.处理图片-定位车牌
***** 灰度处理
rgb1_to_gray (Image, GrayImage)
***** 二值化
threshold (GrayImage, Region, 80, 100)
***** 组装不同颜色
connection (Region, ConnectedRegions)
***** 特征处理
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 8870.97, 10000)
***** ----------------2.处理图片- 转正图片
***** 获取区域
shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
***** 获取中心点
area_center (RegionTrans, Area, Row, Column)
***** 获取幅度
orientation_region (RegionTrans, Phi)
***** 生成反式变幻矩阵
vector_angle_to_rigid (Row, Column, Phi, Row, Column, rad(0), HomMat2D)
***** 生成斜切矩阵
hom_mat2d_slant (HomMat2D, rad(15), 'x', Column, Row, HomMat2DSlant)
affine_trans_region (RegionTrans, RegionAffineTrans, HomMat2DSlant, 'nearest_neighbor')
***** 生成反式变幻图片
affine_trans_image (Image, ImageAffineTrans, HomMat2DSlant, 'constant', 'false')
***** 抠图
reduce_domain (ImageAffineTrans, RegionAffineTrans, ImageReduced)

在这里插入图片描述

三、开始车牌识别

******************** 开始车牌识别***********************************
*************** ----------------3.开始识别之车牌图片预处理
rgb1_to_gray (ImageReduced, GrayImage1)
threshold (GrayImage1, Region1, 128, 255)
***** 腐蚀
erosion_rectangle1 (Region1, RegionErosion, 3, 3)
***** 开运算-去除外边毛刺
opening_rectangle1 (RegionErosion, RegionOpening, 1, 3)
connection (RegionOpening, ConnectedRegions1)
select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 200, 500)
***** 排序
sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'column')
***************----------------4.识别字符
***** 灰度颜色反转
invert_image (GrayImage1, ImageInvert)
***** 定义分类识别器
read_ocr_class_mlp ('Industrial_0-9A-Z_NoRej.omc', OCRHandle)
***** 开始识别
do_ocr_multi_class_mlp (SortedRegions, ImageInvert, OCRHandle, Class, Confidence)
***** 设置字体、设置颜色
set_display_font (WindowHandle, 30, 'mono', 'true', 'false')
dev_clear_window ()
dev_display (Image)
dev_set_color ('red')
***** 循环打印
for Index := 0 to |Class|-1 by 1
    set_tposition (WindowHandle,30, 120+20*Index)
    write_string (WindowHandle, Class[Index])
endfor

在这里插入图片描述

四、识别车牌上面的中文

自定义车牌识别训练库步骤:

【1】、字符分割

【2】、创建trf训练文件,即将字符图像和字符关联起来write_ocr_trainf

【3】、读取trf训练文件,得到所有类别及其对应的个数,read_ocr_trainf_names

【4】、创建分类器create_ocr_class_mlp

【5】、训练分类器trainf_ocr_class_mlp

【6】、保存omc文件,即训练好的分类器write_ocr_class_mlp(可以不保存直接进行识别,如果下次还要用的话最好保存下来,下次直接读取该训练好的模型进行识别就好)

【7】、读取omc文件read_ocr_class_mlp

1.处理需要识别的字符

*************************** 车牌中的中文识别 *******************************
rgb1_to_gray (ImageReduced, GrayImage1)
threshold (GrayImage1, Regions, 176, 242)
closing_circle (Regions, RegionClosing, 3.5)
opening_circle (Regions, RegionOpening, 1.7)
connection (RegionOpening, ConnectedRegions1)
select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 20, 600)
sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'column')
*************** 组装苏字区域
select_obj (SortedRegions, ObjectSelected1, 1)
select_obj (SortedRegions, ObjectSelected2, 2)
select_obj (SortedRegions, ObjectSelected3, 3)
union2 (ObjectSelected1, ObjectSelected2, RegionUnion)
union2 (RegionUnion, ObjectSelected3, RegionUnion1)
select_obj (SortedRegions, ObjectSelected4, 4)
select_obj (SortedRegions, ObjectSelected5, 5)
select_obj (SortedRegions, ObjectSelected6, 6)
select_obj (SortedRegions, ObjectSelected7, 7)
select_obj (SortedRegions, ObjectSelected8, 8)
select_obj (SortedRegions, ObjectSelected9, 9)
***************** 把所有区域组成一个对象
gen_empty_obj (NumberObject)
concat_obj (NumberObject, RegionUnion1, NumberObject)
concat_obj (NumberObject, ObjectSelected4, NumberObject)
concat_obj (NumberObject, ObjectSelected5, NumberObject)
concat_obj (NumberObject, ObjectSelected6, NumberObject)
concat_obj (NumberObject, ObjectSelected7, NumberObject)
concat_obj (NumberObject, ObjectSelected8, NumberObject)
concat_obj (NumberObject, ObjectSelected9, NumberObject)

在这里插入图片描述

2.创建训练文件并生成神经网络识别分类文件

**************** 创建训练文件
TrainFile:='./Charactor.trf'
Words:=['苏','E','C','6','2','N','8']
** 完成图像与字符训练对应关系
write_ocr_trainf (NumberObject, GrayImage1, Words, TrainFile)
** 读取训练文件
read_ocr_trainf_names (TrainFile, CharacterNames, CharacterCount)
** 创建一个分类识别器
create_ocr_class_mlp (8, 10, 'constant', 'default', CharacterNames, 80, 'none', 10, 42, OCRHandle)
** 训练分类识别器
trainf_ocr_class_mlp (OCRHandle, TrainFile, 200, 1, 0.01, Error, ErrorLog)
** 保存分类识别文件
write_ocr_class_mlp (OCRHandle, './Charactor.omc')

在这里插入图片描述

3.根据刚刚生成的训练文件识别车牌

*********************** 基于训练omc文件开始识别带中文车牌**************
read_ocr_class_mlp ('./Charactor.omc', OCRHandle1)
do_ocr_multi_class_mlp (NumberObject, GrayImage1, OCRHandle1, Class, Confidence)
dev_clear_window ()
dev_display (Image)
dev_set_color ('red')
set_display_font (WindowHandle, 30, 'mono', 'true', 'false')
for Index := 0 to |Class|-1 by 1
    set_tposition (WindowHandle,30, 120+36*Index)
    write_string (WindowHandle, Class[Index])
endfor

在这里插入图片描述

至此车牌的中文识别成功

五、根据传入的图片进行车牌识别

就是在不同的位置定位并查找车牌

dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
* 把某个目录下面的.jpg文件进行读取
list_image_files ('./车牌图片', 'jpg', [], ImageFiles)
for k := 0 to |ImageFiles|-1 by 1
    read_image (image, ImageFiles[k])
    decompose3 (image, r, g, b)
    trans_from_rgb (r, g, b, h, s, v, 'hsv')
    *h通道进行处理
    threshold (h, Region, 142, 160)
    *矩形膨胀
    dilation_rectangle1 (Region, RegionDilation, 6.5, 0.5)
    *打断
    connection (RegionDilation, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [80,242,8000], [147,450,1451147])
    shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
    area_center (RegionTrans, Area, Row, Column)
    count_obj (RegionTrans, Number1)
    
    *如果h通道没逼进车牌,选择其他通道进行处理
    if (Number1!=1)
        *s通道进行处理
        if(Number1==0)
            threshold (s, Region, 253, 255)
            dilation_rectangle1 (Region, RegionDilation, 4, 0.5)
            connection (RegionDilation, ConnectedRegions)
            select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [80,294,8000], [157,450,60000])
            shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
            area_center (RegionTrans, Area, Row, Column)
            count_obj (RegionTrans, Number1)
        endif
        if(Number1==3)
            threshold (h, Region, 142, 160)
            dilation_rectangle1 (Region, RegionDilation, 6.5, 0.5)
            connection (RegionDilation, ConnectedRegions)
            select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [250,700,145000], [270,720,160000])
            shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
            area_center (RegionTrans, Area, Row, Column)
            count_obj (RegionTrans, Number1)
        endif
        
        *s通道更换阈值范围处理
        if (Number1==0)
            threshold (s, Region, 170, 255)
            dilation_rectangle1 (Region, RegionDilation,10, 0.5)
            connection (RegionDilation, ConnectedRegions)
            select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [70,250,3000], [157,450,60000])
            shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
            area_center (RegionTrans, Area, Row, Column)
            count_obj (RegionTrans, Number1)
        endif
        
        *r通道进行处理
        if (Number1==0)
            threshold (v, Region, 100, 255)
            connection (Region, ConnectedRegions)
            select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [40,85,1000], [100,200,60000])
            shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
            area_center (RegionTrans, Area, Row, Column)
            count_obj (RegionTrans, Number1)
        endif
        
        if(Number1==2)
            threshold (s, Region, 170, 255)
            connection (Region, ConnectedRegions)
            select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [70,219,3000], [157,450,60000])
            shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
            area_center (RegionTrans, Area, Row, Column)
            count_obj (RegionTrans, Number1) 
        endif
        
        if(Number1==0)
            trans_from_rgb (r, g, b, h, s, v, 'hsv')
            threshold (s, Region, 170, 255)
            dilation_rectangle1 (Region, RegionDilation1, 20, 1)
            connection (RegionDilation1, ConnectedRegions)
            select_shape (ConnectedRegions, SelectedRegions, ['height','width','area'], 'and', [233,500,10000], [240,706,120000])
            shape_trans (SelectedRegions, RegionTrans, 'rectangle2')
            area_center (RegionTrans, Area, Row, Column)
        endif
    endif
    
    *仿射变换
    orientation_region (RegionTrans, Phi)
    *将角度调成与水平角度近似,方便旋转
    a:=deg(Phi)
    *-180<a<0
    if (a<-90)
        if(-181<a)
            a:=180+a 
            Phi:=rad(a)
        endif
    endif
    vector_angle_to_rigid (Row, Column, Phi, Row, Column, rad(0), HomMat2D)
    affine_trans_image (image, ImageAffinTrans, HomMat2D, 'constant', 'false')
    affine_trans_region (RegionTrans, RegionAffineTrans, HomMat2D, 'nearest_neighbor')
    reduce_domain (ImageAffinTrans, RegionAffineTrans, ImageReduced)
    
    *字符识别预处理
*     decompose3 (ImageReduced, r, g, b)
*     trans_from_rgb (r, g, b, h, s, v, 'hsv')
*     threshold (r, Region, 140, 255)
*     dilation_rectangle1 (Region, RegionDilation2, 5, 1)
*     connection (Region, ConnectedRegions1)
    * 特征筛选排序
*     select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [55,7], [85,50])
*     sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
*     count_obj (SortedRegions, Number)
    
    
    decompose3 (ImageReduced, r, g, b)
    trans_from_rgb (r, g, b, h, s, v, 'hsv')
    threshold (r, Region, 155, 255)
    connection (Region, ConnectedRegions1)
    select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [55,7], [85,50])
    sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
    count_obj (SortedRegions, Number)
    *判断字符个数
    if(Number!=6)
        if(Number=0)
            threshold (r, Region, 130, 255) 
            connection (Region, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [45,7], [85,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)  
        endif
        if(Number=0)
            threshold (r, Region, 130, 255) 
            connection (Region, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [40,7], [85,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)  
        endif
        if(Number=0)
            threshold (r, Region, 140, 255) 
            opening_circle (Region, RegionOpening, 1.1)
            connection (RegionOpening, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [30,7], [85,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)  
        endif
        if(Number==0)
            threshold (r, Region, 135, 255) 
            erosion_circle (Region, RegionErosion, 3)
            connection (RegionErosion, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [30,7], [85,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number) 
        endif
        if(Number==0)
            threshold (r, Region, 135, 255) 
            erosion_circle (Region, RegionErosion, 5)
            connection (RegionErosion, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [160,7], [175,75])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number) 
        endif   
        if(Number==3)
            threshold (r, Region, 135, 255) 
            erosion_circle (Region, RegionErosion, 5)
            connection (RegionErosion, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [160,7], [180,75])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number) 
        endif     
        if(Number==0)
            threshold (r, Region, 60, 120) 
            connection (Region, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [15,7], [30,15])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number) 
        endif   
        if(Number==1)
            threshold (r, Region, 130, 170) 
            connection (Region, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [48,7], [60,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)
        endif
        if(Number<6)
            threshold (r, Region, 180, 255) 
            connection (Region, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [49.1,6], [85,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)
        endif
        if(Number<6)
            threshold (r, Region, 180, 255) 
            connection (Region, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [48,15.1], [85,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)
        endif
        if(Number==7)
            threshold (r, Region, 170, 255) 
            erosion_circle (Region, RegionErosion, 1)
            connection (RegionErosion, ConnectedRegions1)
            select_shape (ConnectedRegions1, SelectedRegions1, ['height','width'], 'and', [48,14.5], [82,50])
            sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'row')
            count_obj (SortedRegions, Number)   
        endif
    endif
    area_center (SortedRegions, Area1, Row1, Column1)
    
    *识别显示
    if(Number==6)
        invert_image (r, ImageInvert)
        read_ocr_class_mlp ('Industrial_0-9A-Z_NoRej.omc', OCRHandle)
        do_ocr_multi_class_mlp (SortedRegions, ImageInvert, OCRHandle, Class, Confidence)
        dev_display (image)
        set_display_font (WindowHandle, 50, 'mono', 'true', 'false')
        chepai:=''
        for i := 0 to 5 by 1
            data:= Class[i]
            if (data=='I')
                data:='1'
            endif
            if (data=='O')
                data:='0'
            endif
            
            chepai:=chepai+data
        endfor
        dev_set_color ('red')
        set_tposition (WindowHandle, 100,100)
        write_string (WindowHandle, chepai)
    endif
    stop()
endfor

在这里插入图片描述

六、结合C#与Halcon联合编程实现简易车牌识别应用

1、项目环境的搭建

在这里插入图片描述

2、基于Halcon导出C#项目
在这里插入图片描述
导出文件源码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HalconDotNet;
namespace VLPR
{
    
    
    class HDevelopExport
    {
    
    
        public void InitHalcon()

        {
    
    
            // Default settings used in HDevelop 
            HOperatorSet.SetSystem("width", 512);
            HOperatorSet.SetSystem("height", 512);
            if (HalconAPI.isWindows)
                HOperatorSet.SetSystem("use_window_thread", "true");

        }

        // Chapter: Graphics / Text
        // Short Description: Set font independent of OS 
        public void set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, HTuple hv_Font,
            HTuple hv_Bold, HTuple hv_Slant)
        {
    
    
            // Local control variables 

            HTuple hv_OS = null, hv_BufferWindowHandle = new HTuple();
            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
            HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
            HTuple hv_Scale = new HTuple(), hv_Exception = new HTuple();
            HTuple hv_SubFamily = new HTuple(), hv_Fonts = new HTuple();
            HTuple hv_SystemFonts = new HTuple(), hv_Guess = new HTuple();
            HTuple hv_I = new HTuple(), hv_Index = new HTuple(), hv_AllowedFontSizes = new HTuple();
            HTuple hv_Distances = new HTuple(), hv_Indices = new HTuple();
            HTuple hv_FontSelRegexp = new HTuple(), hv_FontsCourier = new HTuple();
            HTuple hv_Bold_COPY_INP_TMP = hv_Bold.Clone();
            HTuple hv_Font_COPY_INP_TMP = hv_Font.Clone();
            HTuple hv_Size_COPY_INP_TMP = hv_Size.Clone();
            HTuple hv_Slant_COPY_INP_TMP = hv_Slant.Clone();
            HTuple hv_i = new HTuple();

            HOperatorSet.GetSystem("operating_system", out hv_OS);

            if ((int)((new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
                new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1)))) != 0)
            {
    
    
                hv_Size_COPY_INP_TMP = 16;
            }

            if ((int)(new HTuple(((hv_OS.TupleSubstr(0, 2))).TupleEqual("Win"))) != 0)
            {
    
    
                //Set font on Windows systems
                try
                {
    
    
                    //Check, if font scaling is switched on
                    HOperatorSet.OpenWindow(0, 0, 256, 256, 0, "buffer", "", out hv_BufferWindowHandle);
                    HOperatorSet.SetFont(hv_BufferWindowHandle, "-Consolas-16-*-0-*-*-1-");
                    HOperatorSet.GetStringExtents(hv_BufferWindowHandle, "test_string", out hv_Ascent,
                        out hv_Descent, out hv_Width, out hv_Height);
                    //Expected width is 110
                    hv_Scale = 110.0 / hv_Width;
                    hv_Size_COPY_INP_TMP = ((hv_Size_COPY_INP_TMP * hv_Scale)).TupleInt();
                    HOperatorSet.CloseWindow(hv_BufferWindowHandle);
                }
                // catch (Exception) 
                catch (HalconException HDevExpDefaultException1)
                {
    
    
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    //throw (Exception)
                }
                if ((int)((new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))).TupleOr(
                    new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("courier")))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "Courier New";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "Consolas";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "Arial";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "Times New Roman";
                }
                if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
    
    
                    hv_Bold_COPY_INP_TMP = 1;
                }
                else if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
    
    
                    hv_Bold_COPY_INP_TMP = 0;
                }
                else
                {
    
    
                    hv_Exception = "Wrong value of control parameter Bold";
                    throw new HalconException(hv_Exception);
                }
                if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
    
    
                    hv_Slant_COPY_INP_TMP = 1;
                }
                else if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
    
    
                    hv_Slant_COPY_INP_TMP = 0;
                }
                else
                {
    
    
                    hv_Exception = "Wrong value of control parameter Slant";
                    throw new HalconException(hv_Exception);
                }
                try
                {
    
    
                    HOperatorSet.SetFont(hv_WindowHandle, ((((((("-" + hv_Font_COPY_INP_TMP) + "-") + hv_Size_COPY_INP_TMP) + "-*-") + hv_Slant_COPY_INP_TMP) + "-*-*-") + hv_Bold_COPY_INP_TMP) + "-");
                }
                // catch (Exception) 
                catch (HalconException HDevExpDefaultException1)
                {
    
    
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    //throw (Exception)
                }
            }
            else if ((int)(new HTuple(((hv_OS.TupleSubstr(0, 2))).TupleEqual("Dar"))) != 0)
            {
    
    
                //Set font on Mac OS X systems. Since OS X does not have a strict naming
                //scheme for font attributes, we use tables to determine the correct font
                //name.
                hv_SubFamily = 0;
                if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
    
    
                    hv_SubFamily = hv_SubFamily.TupleBor(1);
                }
                else if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleNotEqual("false"))) != 0)
                {
    
    
                    hv_Exception = "Wrong value of control parameter Slant";
                    throw new HalconException(hv_Exception);
                }
                if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
    
    
                    hv_SubFamily = hv_SubFamily.TupleBor(2);
                }
                else if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleNotEqual("false"))) != 0)
                {
    
    
                    hv_Exception = "Wrong value of control parameter Bold";
                    throw new HalconException(hv_Exception);
                }
                if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))) != 0)
                {
    
    
                    hv_Fonts = new HTuple();
                    hv_Fonts[0] = "Menlo-Regular";
                    hv_Fonts[1] = "Menlo-Italic";
                    hv_Fonts[2] = "Menlo-Bold";
                    hv_Fonts[3] = "Menlo-BoldItalic";
                }
                else if ((int)((new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))).TupleOr(
                    new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("courier")))) != 0)
                {
    
    
                    hv_Fonts = new HTuple();
                    hv_Fonts[0] = "CourierNewPSMT";
                    hv_Fonts[1] = "CourierNewPS-ItalicMT";
                    hv_Fonts[2] = "CourierNewPS-BoldMT";
                    hv_Fonts[3] = "CourierNewPS-BoldItalicMT";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
                {
    
    
                    hv_Fonts = new HTuple();
                    hv_Fonts[0] = "ArialMT";
                    hv_Fonts[1] = "Arial-ItalicMT";
                    hv_Fonts[2] = "Arial-BoldMT";
                    hv_Fonts[3] = "Arial-BoldItalicMT";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
                {
    
    
                    hv_Fonts = new HTuple();
                    hv_Fonts[0] = "TimesNewRomanPSMT";
                    hv_Fonts[1] = "TimesNewRomanPS-ItalicMT";
                    hv_Fonts[2] = "TimesNewRomanPS-BoldMT";
                    hv_Fonts[3] = "TimesNewRomanPS-BoldItalicMT";
                }
                else
                {
    
    
                    //Attempt to figure out which of the fonts installed on the system
                    //the user could have meant.
                    HOperatorSet.QueryFont(hv_WindowHandle, out hv_SystemFonts);
                    hv_Fonts = new HTuple();
                    hv_Fonts = hv_Fonts.TupleConcat(hv_Font_COPY_INP_TMP);
                    hv_Fonts = hv_Fonts.TupleConcat(hv_Font_COPY_INP_TMP);
                    hv_Fonts = hv_Fonts.TupleConcat(hv_Font_COPY_INP_TMP);
                    hv_Fonts = hv_Fonts.TupleConcat(hv_Font_COPY_INP_TMP);
                    hv_Guess = new HTuple();
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP);
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-Regular");
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "MT");
                    for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Guess.TupleLength())) - 1); hv_I = (int)hv_I + 1)
                    {
    
    
                        HOperatorSet.TupleFind(hv_SystemFonts, hv_Guess.TupleSelect(hv_I), out hv_Index);
                        if ((int)(new HTuple(hv_Index.TupleNotEqual(-1))) != 0)
                        {
    
    
                            if (hv_Fonts == null)
                                hv_Fonts = new HTuple();
                            hv_Fonts[0] = hv_Guess.TupleSelect(hv_I);
                            break;
                        }
                    }
                    //Guess name of slanted font
                    hv_Guess = new HTuple();
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-Italic");
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-ItalicMT");
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-Oblique");
                    for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Guess.TupleLength())) - 1); hv_I = (int)hv_I + 1)
                    {
    
    
                        HOperatorSet.TupleFind(hv_SystemFonts, hv_Guess.TupleSelect(hv_I), out hv_Index);
                        if ((int)(new HTuple(hv_Index.TupleNotEqual(-1))) != 0)
                        {
    
    
                            if (hv_Fonts == null)
                                hv_Fonts = new HTuple();
                            hv_Fonts[1] = hv_Guess.TupleSelect(hv_I);
                            break;
                        }
                    }
                    //Guess name of bold font
                    hv_Guess = new HTuple();
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-Bold");
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-BoldMT");
                    for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Guess.TupleLength())) - 1); hv_I = (int)hv_I + 1)
                    {
    
    
                        HOperatorSet.TupleFind(hv_SystemFonts, hv_Guess.TupleSelect(hv_I), out hv_Index);
                        if ((int)(new HTuple(hv_Index.TupleNotEqual(-1))) != 0)
                        {
    
    
                            if (hv_Fonts == null)
                                hv_Fonts = new HTuple();
                            hv_Fonts[2] = hv_Guess.TupleSelect(hv_I);
                            break;
                        }
                    }
                    //Guess name of bold slanted font
                    hv_Guess = new HTuple();
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-BoldItalic");
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-BoldItalicMT");
                    hv_Guess = hv_Guess.TupleConcat(hv_Font_COPY_INP_TMP + "-BoldOblique");
                    for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Guess.TupleLength())) - 1); hv_I = (int)hv_I + 1)
                    {
    
    
                        HOperatorSet.TupleFind(hv_SystemFonts, hv_Guess.TupleSelect(hv_I), out hv_Index);
                        if ((int)(new HTuple(hv_Index.TupleNotEqual(-1))) != 0)
                        {
    
    
                            if (hv_Fonts == null)
                                hv_Fonts = new HTuple();
                            hv_Fonts[3] = hv_Guess.TupleSelect(hv_I);
                            break;
                        }
                    }
                }
                hv_Font_COPY_INP_TMP = hv_Fonts.TupleSelect(hv_SubFamily);
                try
                {
    
    
                    HOperatorSet.SetFont(hv_WindowHandle, (hv_Font_COPY_INP_TMP + "-") + hv_Size_COPY_INP_TMP);
                }
                // catch (Exception) 
                catch (HalconException HDevExpDefaultException1)
                {
    
    
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    //throw (Exception)
                }
            }
            else
            {
    
    
                //Set font for UNIX systems
                hv_Size_COPY_INP_TMP = hv_Size_COPY_INP_TMP * 1.25;
                hv_AllowedFontSizes = new HTuple();
                hv_AllowedFontSizes[0] = 11;
                hv_AllowedFontSizes[1] = 14;
                hv_AllowedFontSizes[2] = 17;
                hv_AllowedFontSizes[3] = 20;
                hv_AllowedFontSizes[4] = 25;
                hv_AllowedFontSizes[5] = 34;
                if ((int)(new HTuple(((hv_AllowedFontSizes.TupleFind(hv_Size_COPY_INP_TMP))).TupleEqual(
                    -1))) != 0)
                {
    
    
                    hv_Distances = ((hv_AllowedFontSizes - hv_Size_COPY_INP_TMP)).TupleAbs();
                    HOperatorSet.TupleSortIndex(hv_Distances, out hv_Indices);
                    hv_Size_COPY_INP_TMP = hv_AllowedFontSizes.TupleSelect(hv_Indices.TupleSelect(
                        0));
                }
                if ((int)((new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))).TupleOr(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(
                    "Courier")))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "courier";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "helvetica";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
                {
    
    
                    hv_Font_COPY_INP_TMP = "times";
                }
                if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
    
    
                    hv_Bold_COPY_INP_TMP = "bold";
                }
                else if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
    
    
                    hv_Bold_COPY_INP_TMP = "medium";
                }
                else
                {
    
    
                    hv_Exception = "Wrong value of control parameter Bold";
                    throw new HalconException(hv_Exception);
                }
                if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
    
    
                    if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("times"))) != 0)
                    {
    
    
                        hv_Slant_COPY_INP_TMP = "i";
                    }
                    else
                    {
    
    
                        hv_Slant_COPY_INP_TMP = "o";
                    }
                }
                else if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
    
    
                    hv_Slant_COPY_INP_TMP = "r";
                }
                else
                {
    
    
                    hv_Exception = "Wrong value of control parameter Slant";
                    throw new HalconException(hv_Exception);
                }
                try
                {
    
    
                    HOperatorSet.SetFont(hv_WindowHandle, ((((((("-adobe-" + hv_Font_COPY_INP_TMP) + "-") + hv_Bold_COPY_INP_TMP) + "-") + hv_Slant_COPY_INP_TMP) + "-normal-*-") + hv_Size_COPY_INP_TMP) + "-*-*-*-*-*-*-*");
                }
                // catch (Exception) 
                catch (HalconException HDevExpDefaultException1)
                {
    
    
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    if ((int)((new HTuple(((hv_OS.TupleSubstr(0, 4))).TupleEqual("Linux"))).TupleAnd(
                        new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("courier")))) != 0)
                    {
    
    
                        HOperatorSet.QueryFont(hv_WindowHandle, out hv_Fonts);
                        hv_FontSelRegexp = (("^-[^-]*-[^-]*[Cc]ourier[^-]*-" + hv_Bold_COPY_INP_TMP) + "-") + hv_Slant_COPY_INP_TMP;
                        hv_FontsCourier = ((hv_Fonts.TupleRegexpSelect(hv_FontSelRegexp))).TupleRegexpMatch(
                            hv_FontSelRegexp);
                        if ((int)(new HTuple((new HTuple(hv_FontsCourier.TupleLength())).TupleEqual(
                            0))) != 0)
                        {
    
    
                            hv_Exception = "Wrong font name";
                            //throw (Exception)
                        }
                        else
                        {
    
    
                            try
                            {
    
    
                                HOperatorSet.SetFont(hv_WindowHandle, (((hv_FontsCourier.TupleSelect(
                                    0)) + "-normal-*-") + hv_Size_COPY_INP_TMP) + "-*-*-*-*-*-*-*");
                            }
                            // catch (Exception) 
                            catch (HalconException HDevExpDefaultException2)
                            {
    
    
                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
                                //throw (Exception)
                            }
                        }
                    }
                    //throw (Exception)
                }
            }
            // dev_set_preferences(...); only in hdevelop

            return;
        }

        // Chapter: Graphics / Text
        // Short Description: This procedure writes a text message. 
        public void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem,
            HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
        {
    
    



            // Local iconic variables 

            // Local control variables 

            HTuple hv_Red = null, hv_Green = null, hv_Blue = null;
            HTuple hv_Row1Part = null, hv_Column1Part = null, hv_Row2Part = null;
            HTuple hv_Column2Part = null, hv_RowWin = null, hv_ColumnWin = null;
            HTuple hv_WidthWin = null, hv_HeightWin = null, hv_MaxAscent = null;
            HTuple hv_MaxDescent = null, hv_MaxWidth = null, hv_MaxHeight = null;
            HTuple hv_R1 = new HTuple(), hv_C1 = new HTuple(), hv_FactorRow = new HTuple();
            HTuple hv_FactorColumn = new HTuple(), hv_UseShadow = null;
            HTuple hv_ShadowColor = null, hv_Exception = new HTuple();
            HTuple hv_Width = new HTuple(), hv_Index = new HTuple();
            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
            HTuple hv_W = new HTuple(), hv_H = new HTuple(), hv_FrameHeight = new HTuple();
            HTuple hv_FrameWidth = new HTuple(), hv_R2 = new HTuple();
            HTuple hv_C2 = new HTuple(), hv_DrawMode = new HTuple();
            HTuple hv_CurrentColor = new HTuple();
            HTuple hv_Box_COPY_INP_TMP = hv_Box.Clone();
            HTuple hv_Color_COPY_INP_TMP = hv_Color.Clone();
            HTuple hv_Column_COPY_INP_TMP = hv_Column.Clone();
            HTuple hv_Row_COPY_INP_TMP = hv_Row.Clone();
            HTuple hv_String_COPY_INP_TMP = hv_String.Clone();

            // Initialize local and output iconic variables 
            //This procedure displays text in a graphics window.
            //
            //Input parameters:
            //WindowHandle: The WindowHandle of the graphics window, where
            //   the message should be displayed
            //String: A tuple of strings containing the text message to be displayed
            //CoordSystem: If set to 'window', the text position is given
            //   with respect to the window coordinate system.
            //   If set to 'image', image coordinates are used.
            //   (This may be useful in zoomed images.)
            //Row: The row coordinate of the desired text position
            //   If set to -1, a default value of 12 is used.
            //Column: The column coordinate of the desired text position
            //   If set to -1, a default value of 12 is used.
            //Color: defines the color of the text as string.
            //   If set to [], '' or 'auto' the currently set color is used.
            //   If a tuple of strings is passed, the colors are used cyclically
            //   for each new textline.
            //Box: If Box[0] is set to 'true', the text is written within an orange box.
            //     If set to' false', no box is displayed.
            //     If set to a color string (e.g. 'white', '#FF00CC', etc.),
            //       the text is written in a box of that color.
            //     An optional second value for Box (Box[1]) controls if a shadow is displayed:
            //       'true' -> display a shadow in a default color
            //       'false' -> display no shadow (same as if no second value is given)
            //       otherwise -> use given string as color string for the shadow color
            //
            //Prepare window
            HOperatorSet.GetRgb(hv_WindowHandle, out hv_Red, out hv_Green, out hv_Blue);
            HOperatorSet.GetPart(hv_WindowHandle, out hv_Row1Part, out hv_Column1Part, out hv_Row2Part,
                out hv_Column2Part);
            HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_RowWin, out hv_ColumnWin,
                out hv_WidthWin, out hv_HeightWin);
            HOperatorSet.SetPart(hv_WindowHandle, 0, 0, hv_HeightWin - 1, hv_WidthWin - 1);
            //
            //default settings
            if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
    
    
                hv_Row_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
    
    
                hv_Column_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(new HTuple()))) != 0)
            {
    
    
                hv_Color_COPY_INP_TMP = "";
            }
            //
            hv_String_COPY_INP_TMP = ((("" + hv_String_COPY_INP_TMP) + "")).TupleSplit("\n");
            //
            //Estimate extentions of text depending on font size.
            HOperatorSet.GetFontExtents(hv_WindowHandle, out hv_MaxAscent, out hv_MaxDescent,
                out hv_MaxWidth, out hv_MaxHeight);
            if ((int)(new HTuple(hv_CoordSystem.TupleEqual("window"))) != 0)
            {
    
    
                hv_R1 = hv_Row_COPY_INP_TMP.Clone();
                hv_C1 = hv_Column_COPY_INP_TMP.Clone();
            }
            else
            {
    
    
                //Transform image to window coordinates
                hv_FactorRow = (1.0 * hv_HeightWin) / ((hv_Row2Part - hv_Row1Part) + 1);
                hv_FactorColumn = (1.0 * hv_WidthWin) / ((hv_Column2Part - hv_Column1Part) + 1);
                hv_R1 = ((hv_Row_COPY_INP_TMP - hv_Row1Part) + 0.5) * hv_FactorRow;
                hv_C1 = ((hv_Column_COPY_INP_TMP - hv_Column1Part) + 0.5) * hv_FactorColumn;
            }
            //
            //Display text box depending on text size
            hv_UseShadow = 1;
            hv_ShadowColor = "gray";
            if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(0))).TupleEqual("true"))) != 0)
            {
    
    
                if (hv_Box_COPY_INP_TMP == null)
                    hv_Box_COPY_INP_TMP = new HTuple();
                hv_Box_COPY_INP_TMP[0] = "#fce9d4";
                hv_ShadowColor = "#f28d26";
            }
            if ((int)(new HTuple((new HTuple(hv_Box_COPY_INP_TMP.TupleLength())).TupleGreater(
                1))) != 0)
            {
    
    
                if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(1))).TupleEqual("true"))) != 0)
                {
    
    
                    //Use default ShadowColor set above
                }
                else if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(1))).TupleEqual(
                    "false"))) != 0)
                {
    
    
                    hv_UseShadow = 0;
                }
                else
                {
    
    
                    hv_ShadowColor = hv_Box_COPY_INP_TMP[1];
                    //Valid color?
                    try
                    {
    
    
                        HOperatorSet.SetColor(hv_WindowHandle, hv_Box_COPY_INP_TMP.TupleSelect(
                            1));
                    }
                    // catch (Exception) 
                    catch (HalconException HDevExpDefaultException1)
                    {
    
    
                        HDevExpDefaultException1.ToHTuple(out hv_Exception);
                        hv_Exception = "Wrong value of control parameter Box[1] (must be a 'true', 'false', or a valid color string)";
                        throw new HalconException(hv_Exception);
                    }
                }
            }
            if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(0))).TupleNotEqual("false"))) != 0)
            {
    
    
                //Valid color?
                try
                {
    
    
                    HOperatorSet.SetColor(hv_WindowHandle, hv_Box_COPY_INP_TMP.TupleSelect(0));
                }
                // catch (Exception) 
                catch (HalconException HDevExpDefaultException1)
                {
    
    
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    hv_Exception = "Wrong value of control parameter Box[0] (must be a 'true', 'false', or a valid color string)";
                    throw new HalconException(hv_Exception);
                }
                //Calculate box extents
                hv_String_COPY_INP_TMP = (" " + hv_String_COPY_INP_TMP) + " ";
                hv_Width = new HTuple();
                for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                    )) - 1); hv_Index = (int)hv_Index + 1)
                {
    
    
                    HOperatorSet.GetStringExtents(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
                        hv_Index), out hv_Ascent, out hv_Descent, out hv_W, out hv_H);
                    hv_Width = hv_Width.TupleConcat(hv_W);
                }
                hv_FrameHeight = hv_MaxHeight * (new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                    ));
                hv_FrameWidth = (((new HTuple(0)).TupleConcat(hv_Width))).TupleMax();
                hv_R2 = hv_R1 + hv_FrameHeight;
                hv_C2 = hv_C1 + hv_FrameWidth;
                //Display rectangles
                HOperatorSet.GetDraw(hv_WindowHandle, out hv_DrawMode);
                HOperatorSet.SetDraw(hv_WindowHandle, "fill");
                //Set shadow color
                HOperatorSet.SetColor(hv_WindowHandle, hv_ShadowColor);
                if ((int)(hv_UseShadow) != 0)
                {
    
    
                    HOperatorSet.DispRectangle1(hv_WindowHandle, hv_R1 + 1, hv_C1 + 1, hv_R2 + 1, hv_C2 + 1);
                }
                //Set box color
                HOperatorSet.SetColor(hv_WindowHandle, hv_Box_COPY_INP_TMP.TupleSelect(0));
                HOperatorSet.DispRectangle1(hv_WindowHandle, hv_R1, hv_C1, hv_R2, hv_C2);
                HOperatorSet.SetDraw(hv_WindowHandle, hv_DrawMode);
            }
            //Write text.
            for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                )) - 1); hv_Index = (int)hv_Index + 1)
            {
    
    
                hv_CurrentColor = hv_Color_COPY_INP_TMP.TupleSelect(hv_Index % (new HTuple(hv_Color_COPY_INP_TMP.TupleLength()
                    )));
                if ((int)((new HTuple(hv_CurrentColor.TupleNotEqual(""))).TupleAnd(new HTuple(hv_CurrentColor.TupleNotEqual(
                    "auto")))) != 0)
                {
    
    
                    HOperatorSet.SetColor(hv_WindowHandle, hv_CurrentColor);
                }
                else
                {
    
    
                    HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
                }
                hv_Row_COPY_INP_TMP = hv_R1 + (hv_MaxHeight * hv_Index);
                HOperatorSet.SetTposition(hv_WindowHandle, hv_Row_COPY_INP_TMP, hv_C1);
                HOperatorSet.WriteString(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
                    hv_Index));
            }
            //Reset changed window settings
            HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
            HOperatorSet.SetPart(hv_WindowHandle, hv_Row1Part, hv_Column1Part, hv_Row2Part,
                hv_Column2Part);

            return;
        }

        HTuple hv_ExpDefaultWinHandle = new HTuple();

        #region 变量定义
        // Local iconic variables 
        HTuple hv_path = null, hv_Width = null, hv_Height = null;
        HObject ho_image, ho_r, ho_g, ho_b, ho_h, ho_s;
        HObject ho_v, ho_Region, ho_RegionDilation, ho_ConnectedRegions;
        HObject ho_SelectedRegions, ho_RegionTrans, ho_RegionDilation1 = null;
        HObject ho_ImageAffinTrans, ho_RegionAffineTrans, ho_ImageReduced;
        HObject ho_ConnectedRegions1, ho_SelectedRegions1, ho_SortedRegions;
        HObject ho_RegionOpening = null, ho_RegionErosion = null, ho_ImageInvert = null;
        HTuple hv_chepai = new HTuple(), hv_i = new HTuple();
        HTuple hv_data = new HTuple();

        // Local control variables 
        HTuple hv_WindowHandle = null, hv_Area = null;
        HTuple hv_Row = null, hv_Column = null, hv_Number1 = null;
        HTuple hv_Phi = null, hv_a = null, hv_HomMat2D = null;
        HTuple hv_Number = null, hv_Area1 = null, hv_Row1 = null;
        HTuple hv_Column1 = null, hv_OCRHandle = new HTuple();
        HTuple hv_Class = new HTuple(), hv_Confidence = new HTuple();
        HTuple hv_chepaiID = null, hv_chepaiIDString = null;
        private HTuple hv_Font;
        private HTuple hv_FontWithSize;

        // Initialize local and output iconic variables 
        #endregion

        /// <summary>
        /// 加载图片到HWWindowControl的方法
        /// </summary>
        /// <param name="window"></param>
        /// <param name="window_width"></param>
        /// <param name="window_height"></param>
        /// <param name="path"></param>
        public void ReadImage(HTuple window, HTuple window_width, HTuple window_height, string path)
        {
    
    
            hv_ExpDefaultWinHandle = window;
            HOperatorSet.GenEmptyObj(out ho_image);
            //初始化本地和输出变量
            ho_image.Dispose();
            if (HDevWindowStack.IsOpen())
            {
    
    
                HOperatorSet.CloseWindow(HDevWindowStack.Pop());
            }
            
            HOperatorSet.SetWindowAttr("background_color", "black");

            HOperatorSet.ReadImage(out ho_image, path);
            HOperatorSet.GetImageSize(ho_image, out hv_Width, out hv_Height);
            if (HDevWindowStack.IsOpen())
            {
    
    
                HOperatorSet.SetPart(HDevWindowStack.GetActive(), 0, 0, window_width, window_height);
            }
            HOperatorSet.OpenWindow(0, 0, window_width, window_height, hv_ExpDefaultWinHandle, "visible", "", out hv_WindowHandle);
            HDevWindowStack.Push(hv_WindowHandle);
            if (HDevWindowStack.IsOpen())
            {
    
    
                HOperatorSet.DispObj(ho_image, HDevWindowStack.GetActive());
            }


        }

        /// <summary>
        /// 识别图片车牌号码的方法
        /// </summary>
        /// <returns></returns>
        public string RecognitionImage()
        {
    
    

            #region 
            HOperatorSet.GenEmptyObj(out ho_r);
            HOperatorSet.GenEmptyObj(out ho_g);
            HOperatorSet.GenEmptyObj(out ho_b);
            HOperatorSet.GenEmptyObj(out ho_h);
            HOperatorSet.GenEmptyObj(out ho_s);
            HOperatorSet.GenEmptyObj(out ho_v);
            HOperatorSet.GenEmptyObj(out ho_Region);
            HOperatorSet.GenEmptyObj(out ho_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_SelectedRegions);
            HOperatorSet.GenEmptyObj(out ho_RegionTrans);
            HOperatorSet.GenEmptyObj(out ho_RegionDilation1);
            HOperatorSet.GenEmptyObj(out ho_ImageAffinTrans);
            HOperatorSet.GenEmptyObj(out ho_RegionAffineTrans);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_ConnectedRegions1);
            HOperatorSet.GenEmptyObj(out ho_SelectedRegions1);
            HOperatorSet.GenEmptyObj(out ho_SortedRegions);
            HOperatorSet.GenEmptyObj(out ho_RegionOpening);
            HOperatorSet.GenEmptyObj(out ho_RegionErosion);
            HOperatorSet.GenEmptyObj(out ho_ImageInvert);
            HOperatorSet.Decompose3(ho_image, out ho_r, out ho_g, out ho_b);
            #endregion
            try
            {
    
    
                ho_r.Dispose(); ho_g.Dispose(); ho_b.Dispose();
                HOperatorSet.Decompose3(ho_image, out ho_r, out ho_g, out ho_b);
                ho_h.Dispose(); ho_s.Dispose(); ho_v.Dispose();
                HOperatorSet.TransFromRgb(ho_r, ho_g, ho_b, out ho_h, out ho_s, out ho_v, "hsv");
                //h通道进行处理
                ho_Region.Dispose();
                HOperatorSet.Threshold(ho_h, out ho_Region, 142, 160);
                ho_RegionDilation.Dispose();
                HOperatorSet.DilationRectangle1(ho_Region, out ho_RegionDilation, 6.5, 0.5);
                ho_ConnectedRegions.Dispose();
                HOperatorSet.Connection(ho_RegionDilation, out ho_ConnectedRegions);
                ho_SelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, ((new HTuple("height")).TupleConcat(
                    "width")).TupleConcat("area"), "and", ((new HTuple(80)).TupleConcat(242)).TupleConcat(
                    8000), ((new HTuple(147)).TupleConcat(450)).TupleConcat(1451147));
                ho_RegionTrans.Dispose();
                HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);
                HOperatorSet.CountObj(ho_RegionTrans, out hv_Number1);

                //如果h通道没逼进车牌,选择其他通道进行处理
                if ((int)(new HTuple(hv_Number1.TupleNotEqual(1))) != 0)
                {
    
    
                    //s通道进行处理
                    if ((int)(new HTuple(hv_Number1.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_s, out ho_Region, 253, 255);
                        ho_RegionDilation.Dispose();
                        HOperatorSet.DilationRectangle1(ho_Region, out ho_RegionDilation, 4, 0.5);
                        ho_ConnectedRegions.Dispose();
                        HOperatorSet.Connection(ho_RegionDilation, out ho_ConnectedRegions);
                        ho_SelectedRegions.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (
                            (new HTuple("height")).TupleConcat("width")).TupleConcat("area"), "and",
                            ((new HTuple(80)).TupleConcat(294)).TupleConcat(8000), ((new HTuple(157)).TupleConcat(
                            450)).TupleConcat(60000));
                        ho_RegionTrans.Dispose();
                        HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                        HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);
                        HOperatorSet.CountObj(ho_RegionTrans, out hv_Number1);
                    }
                    if ((int)(new HTuple(hv_Number1.TupleEqual(3))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_h, out ho_Region, 142, 160);
                        ho_RegionDilation.Dispose();
                        HOperatorSet.DilationRectangle1(ho_Region, out ho_RegionDilation, 6.5,
                            0.5);
                        ho_ConnectedRegions.Dispose();
                        HOperatorSet.Connection(ho_RegionDilation, out ho_ConnectedRegions);
                        ho_SelectedRegions.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (
                            (new HTuple("height")).TupleConcat("width")).TupleConcat("area"), "and",
                            ((new HTuple(250)).TupleConcat(700)).TupleConcat(145000), ((new HTuple(270)).TupleConcat(
                            720)).TupleConcat(160000));
                        ho_RegionTrans.Dispose();
                        HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                        HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);
                        HOperatorSet.CountObj(ho_RegionTrans, out hv_Number1);
                    }

                    //s通道更换阈值范围处理
                    if ((int)(new HTuple(hv_Number1.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_s, out ho_Region, 170, 255);
                        ho_RegionDilation.Dispose();
                        HOperatorSet.DilationRectangle1(ho_Region, out ho_RegionDilation, 10, 0.5);
                        ho_ConnectedRegions.Dispose();
                        HOperatorSet.Connection(ho_RegionDilation, out ho_ConnectedRegions);
                        ho_SelectedRegions.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (
                            (new HTuple("height")).TupleConcat("width")).TupleConcat("area"), "and",
                            ((new HTuple(70)).TupleConcat(250)).TupleConcat(3000), ((new HTuple(157)).TupleConcat(
                            450)).TupleConcat(60000));
                        ho_RegionTrans.Dispose();
                        HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                        HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);
                        HOperatorSet.CountObj(ho_RegionTrans, out hv_Number1);
                    }

                    //r通道进行处理
                    if ((int)(new HTuple(hv_Number1.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_v, out ho_Region, 100, 255);
                        ho_ConnectedRegions.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions);
                        ho_SelectedRegions.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (
                            (new HTuple("height")).TupleConcat("width")).TupleConcat("area"), "and",
                            ((new HTuple(40)).TupleConcat(85)).TupleConcat(1000), ((new HTuple(100)).TupleConcat(
                            200)).TupleConcat(60000));
                        ho_RegionTrans.Dispose();
                        HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                        HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);
                        HOperatorSet.CountObj(ho_RegionTrans, out hv_Number1);
                    }

                    if ((int)(new HTuple(hv_Number1.TupleEqual(2))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_s, out ho_Region, 170, 255);
                        ho_ConnectedRegions.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions);
                        ho_SelectedRegions.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (
                            (new HTuple("height")).TupleConcat("width")).TupleConcat("area"), "and",
                            ((new HTuple(70)).TupleConcat(219)).TupleConcat(3000), ((new HTuple(157)).TupleConcat(
                            450)).TupleConcat(60000));
                        ho_RegionTrans.Dispose();
                        HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                        HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);
                        HOperatorSet.CountObj(ho_RegionTrans, out hv_Number1);
                    }

                    if ((int)(new HTuple(hv_Number1.TupleEqual(0))) != 0)
                    {
    
    
                        ho_h.Dispose(); ho_s.Dispose(); ho_v.Dispose();
                        HOperatorSet.TransFromRgb(ho_r, ho_g, ho_b, out ho_h, out ho_s, out ho_v,
                            "hsv");
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_s, out ho_Region, 170, 255);
                        ho_RegionDilation1.Dispose();
                        HOperatorSet.DilationRectangle1(ho_Region, out ho_RegionDilation1, 20,
                            1);
                        ho_ConnectedRegions.Dispose();
                        HOperatorSet.Connection(ho_RegionDilation1, out ho_ConnectedRegions);
                        ho_SelectedRegions.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (
                            (new HTuple("height")).TupleConcat("width")).TupleConcat("area"), "and",
                            ((new HTuple(233)).TupleConcat(500)).TupleConcat(10000), ((new HTuple(240)).TupleConcat(
                            706)).TupleConcat(120000));
                        ho_RegionTrans.Dispose();
                        HOperatorSet.ShapeTrans(ho_SelectedRegions, out ho_RegionTrans, "rectangle2");
                        HOperatorSet.AreaCenter(ho_RegionTrans, out hv_Area, out hv_Row, out hv_Column);

                    }
                }

                //仿射变换
                HOperatorSet.OrientationRegion(ho_RegionTrans, out hv_Phi);
                //将角度调成与水平角度近似,方便旋转
                hv_a = hv_Phi.TupleDeg();
                //-180<a<0
                if ((int)(new HTuple(hv_a.TupleLess(-90))) != 0)
                {
    
    
                    if ((int)(new HTuple((new HTuple(-181)).TupleLess(hv_a))) != 0)
                    {
    
    
                        hv_a = 180 + hv_a;
                        hv_Phi = hv_a.TupleRad();
                    }
                }
                HOperatorSet.VectorAngleToRigid(hv_Row, hv_Column, hv_Phi, hv_Row, hv_Column,
                    (new HTuple(0)).TupleRad(), out hv_HomMat2D);
                ho_ImageAffinTrans.Dispose();
                HOperatorSet.AffineTransImage(ho_image, out ho_ImageAffinTrans, hv_HomMat2D,
                    "constant", "false");
                ho_RegionAffineTrans.Dispose();
                HOperatorSet.AffineTransRegion(ho_RegionTrans, out ho_RegionAffineTrans, hv_HomMat2D,
                    "nearest_neighbor");
                ho_ImageReduced.Dispose();
                HOperatorSet.ReduceDomain(ho_ImageAffinTrans, ho_RegionAffineTrans, out ho_ImageReduced
                    );

                //字符识别
                ho_r.Dispose(); ho_g.Dispose(); ho_b.Dispose();
                HOperatorSet.Decompose3(ho_ImageReduced, out ho_r, out ho_g, out ho_b);
                ho_h.Dispose(); ho_s.Dispose(); ho_v.Dispose();
                HOperatorSet.TransFromRgb(ho_r, ho_g, ho_b, out ho_h, out ho_s, out ho_v, "hsv");
                ho_Region.Dispose();
                HOperatorSet.Threshold(ho_r, out ho_Region, 155, 255);
                ho_ConnectedRegions1.Dispose();
                HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                ho_SelectedRegions1.Dispose();
                HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1, (new HTuple("height")).TupleConcat(
                    "width"), "and", (new HTuple(55)).TupleConcat(7), (new HTuple(85)).TupleConcat(
                    50));
                ho_SortedRegions.Dispose();
                HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                    "true", "row");
                HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                //判断字符个数
                if ((int)(new HTuple(hv_Number.TupleNotEqual(6))) != 0)
                {
    
    
                    if ((int)(new HTuple(hv_Number.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 130, 255);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(45)).TupleConcat(
                            7), (new HTuple(85)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }

                    if ((int)(new HTuple(hv_Number.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 130, 255);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(40)).TupleConcat(
                            7), (new HTuple(85)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }

                    if ((int)(new HTuple(hv_Number.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 140, 255);
                        ho_RegionOpening.Dispose();
                        HOperatorSet.OpeningCircle(ho_Region, out ho_RegionOpening, 1.1);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_RegionOpening, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(30)).TupleConcat(
                            7), (new HTuple(85)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }

                    if ((int)(new HTuple(hv_Number.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 135, 255);
                        ho_RegionErosion.Dispose();
                        HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 3);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_RegionErosion, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(30)).TupleConcat(
                            7), (new HTuple(85)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }

                    if ((int)(new HTuple(hv_Number.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 135, 255);
                        ho_RegionErosion.Dispose();
                        HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 5);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_RegionErosion, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(160)).TupleConcat(
                            7), (new HTuple(175)).TupleConcat(75));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }

                    if ((int)(new HTuple(hv_Number.TupleEqual(3))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 135, 255);
                        ho_RegionErosion.Dispose();
                        HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 5);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_RegionErosion, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(160)).TupleConcat(
                            7), (new HTuple(180)).TupleConcat(75));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }


                    if ((int)(new HTuple(hv_Number.TupleEqual(0))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 60, 120);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(15)).TupleConcat(
                            7), (new HTuple(30)).TupleConcat(15));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }

                    if ((int)(new HTuple(hv_Number.TupleEqual(1))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 130, 170);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(48)).TupleConcat(
                            7), (new HTuple(60)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }
                    if ((int)(new HTuple(hv_Number.TupleLess(6))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 180, 255);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(49.1)).TupleConcat(
                            6), (new HTuple(85)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }
                    if ((int)(new HTuple(hv_Number.TupleLess(6))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 180, 255);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(48)).TupleConcat(
                            15.1), (new HTuple(85)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }
                    if ((int)(new HTuple(hv_Number.TupleEqual(7))) != 0)
                    {
    
    
                        ho_Region.Dispose();
                        HOperatorSet.Threshold(ho_r, out ho_Region, 170, 255);
                        ho_RegionErosion.Dispose();
                        HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 1);
                        ho_ConnectedRegions1.Dispose();
                        HOperatorSet.Connection(ho_RegionErosion, out ho_ConnectedRegions1);
                        ho_SelectedRegions1.Dispose();
                        HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1,
                            (new HTuple("height")).TupleConcat("width"), "and", (new HTuple(48)).TupleConcat(
                            14.5), (new HTuple(82)).TupleConcat(50));
                        ho_SortedRegions.Dispose();
                        HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character",
                            "true", "row");
                        HOperatorSet.CountObj(ho_SortedRegions, out hv_Number);
                    }
                }

                //识别显示
                if ((int)(new HTuple(hv_Number.TupleEqual(6))) != 0)
                {
    
    
                    ho_ImageInvert.Dispose();
                    HOperatorSet.InvertImage(ho_r, out ho_ImageInvert);
                    HOperatorSet.ReadOcrClassMlp("Industrial_0-9A-Z_NoRej.omc", out hv_OCRHandle);
                    HOperatorSet.DoOcrMultiClassMlp(ho_SortedRegions, ho_ImageInvert, hv_OCRHandle,
                        out hv_Class, out hv_Confidence);
                    if (HDevWindowStack.IsOpen())
                    {
    
    
                        HOperatorSet.DispObj(ho_image, HDevWindowStack.GetActive());
                    }

                    hv_chepai = "";
                    for (hv_i = 0; (int)hv_i <= 5; hv_i = (int)hv_i + 1)
                    {
    
    
                        hv_data.Dispose();
                        hv_data = hv_Class.TupleSelect(hv_i);
                        if ((int)(new HTuple(hv_data.TupleEqual("I"))) != 0)
                        {
    
    
                            hv_data.Dispose();
                            hv_data = "1";
                        }
                        if ((int)(new HTuple(hv_data.TupleEqual("O"))) != 0)
                        {
    
    
                            hv_data.Dispose();
                            hv_data = "0";
                        }
                        hv_chepai = hv_chepai + hv_data;
                    }
                    HOperatorSet.SetColor(hv_WindowHandle, "red");
                    HOperatorSet.SetTposition(hv_WindowHandle, 100, 100);
                    HOperatorSet.WriteString(hv_WindowHandle, hv_chepai);

                    hv_chepaiIDString = "";
                    for (hv_i = 0; (int)hv_i <= (int)((new HTuple(hv_chepai.TupleLength())) - 1); hv_i = (int)hv_i + 1)
                    {
    
    
                        hv_chepaiIDString = hv_chepaiIDString + (hv_chepai.TupleSelect(hv_i));
                    }
                    return hv_chepaiIDString;

                }
                else return hv_chepaiIDString = "识别失败";
            }
            catch (HalconException)
            {
    
    
                ho_image.Dispose();
                ho_r.Dispose();
                ho_g.Dispose();
                ho_b.Dispose();
                ho_h.Dispose();
                ho_s.Dispose();
                ho_v.Dispose();
                ho_Region.Dispose();
                ho_RegionDilation.Dispose();
                ho_ConnectedRegions.Dispose();
                ho_SelectedRegions.Dispose();
                ho_RegionTrans.Dispose();
                ho_RegionDilation1.Dispose();
                ho_ImageAffinTrans.Dispose();
                ho_RegionAffineTrans.Dispose();
                ho_ImageReduced.Dispose();
                ho_ConnectedRegions1.Dispose();
                ho_SelectedRegions1.Dispose();
                ho_SortedRegions.Dispose();
                ho_RegionOpening.Dispose();
                ho_RegionErosion.Dispose();
                ho_ImageInvert.Dispose();


                ho_image.Dispose();
                ho_r.Dispose();
                ho_g.Dispose();
                ho_b.Dispose();
                ho_h.Dispose();
                ho_s.Dispose();
                ho_v.Dispose();
                ho_Region.Dispose();
                ho_RegionDilation.Dispose();
                ho_ConnectedRegions.Dispose();
                ho_SelectedRegions.Dispose();
                ho_RegionTrans.Dispose();
                ho_RegionDilation1.Dispose();
                ho_ImageAffinTrans.Dispose();
                ho_RegionAffineTrans.Dispose();
                ho_ImageReduced.Dispose();
                ho_ConnectedRegions1.Dispose();
                ho_SelectedRegions1.Dispose();
                ho_SortedRegions.Dispose();
                ho_RegionOpening.Dispose();
                ho_RegionErosion.Dispose();
                ho_ImageInvert.Dispose();
                return hv_chepaiIDString = "识别失败";
            }
        }
    }
}

3、基于C#项目编写加载图片及识别过程

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using VLPR;

namespace CardRecognition
{
    
    
    public partial class Form1 : Form
    {
    
    
        private HDevelopExport HD = new HDevelopExport();

        string ImagePath; // 图片路径
        public Form1()
        {
    
    
            InitializeComponent();
        }

        /// <summary>
        /// 加载图片的按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLoadImage_Click(object sender, EventArgs e)
        {
    
    
            // 设置过滤文件条件
            openFileDialog1.Filter = "JPG文件|*.jpg";
            // 设置关闭对话回到当前目录
            openFileDialog1.RestoreDirectory= true;
            // 打开对话框
            if (openFileDialog1.ShowDialog() == DialogResult.OK) 
            {
    
    
                ImagePath= openFileDialog1.FileName;
                // 读取图片并显示到该窗口上面
                HD.ReadImage(hWindowControl1.HalconWindow, hWindowControl1.Width, hWindowControl1.Height, ImagePath);
            }
        }

        /// <summary>
        /// 识别图片车牌号码的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
    
    
            var cardNumber = HD.RecognitionImage();
            this.textBox1.Text = this.textBox1.Text + cardNumber + "\r\n";
        }
    }
}

在这里插入图片描述

项目源码:https://download.csdn.net/download/aa2528877987/87645528

猜你喜欢

转载自blog.csdn.net/aa2528877987/article/details/129848088
今日推荐