第3章 CHAPTER 3 HALCON语法 第3章HALCON语法 3.1变量的创建与赋值 在HALCON中可以创建变量并为变量赋值,可通过下面的程序来了解HALCON的变量创建和赋值。 *Image变量的赋值 read_image(Image,'C:/Users/admin/Pictures/Saved/Pictures/logo001.png') CopyImage:=Image *区域的赋值 gen_rectangle1(Rectangle, 100, 100, 300, 300) CopyRegion:=Rectangle *亚像素数据的赋值 gen_contour_region_xld(Rectangle, Contours, 'border') CopyXLD:=Contours *Tuple的创建赋值 *Tuple赋空值 EmptyTuple := [] *Tuple赋单个值 Value:=1 *Tuple赋多个值 ValueArray:=[2,10] *创建相同值的数组 tuple_gen_const(10,5, Newtuple) 第一行代码使用read_image来读取一张图像,如图31所示。 图31读取出来的图像 图像的地址是在C盘里面设置好的一个logo的图像,需要把它复制给一个新的变量CopyImage,HALCON的变量是不需要声明的,直接输入CopyImage:=image,即可完成图像的复制。创建矩形区域用的是gen_rectangle1函数,这个函数的参数中: (1) 第一个参数Rectangle是输出的创建区域; (2) 第二个参数Row1是创建的这个Rectangle左上角的Row值,即Y值; (3) 第三个参数Column1是创建的这个Rectangle左上角的Column值,即X值; (4) 第四个参数Row2是创建的这个Rectangle右下角的Row值,即Y值; (5) 第五个参数Column2是创建的这个Rectangle右下角的Column值,即X值。 创建区域输入的参数值分别为100、100、300、300。图32是创建的矩形区域。 图32区域的创建 要把这个矩阵赋给一个新的区域变量CopyRegion,操作的方式和复制Image的方式一致,输入CopyRegion:=Rectangle,就完成了区域的复制。 创建一个亚像素数据(Extended Line Descriptions): 使用gen_countour_region_xld函数来创建亚像素数据,这里创建亚像素数据的方式是通过之前创建的Region来转化为一个亚像素数据。这个函数的参数中: (1) 第一个参数Regions是输入的区域; (2) 第二个参数Contours是输出的亚像素数据; (3) 第三个参数Mode是选择转换的方式,这里选择border,是指输出它的边缘。 图33所示为亚像素数据的创建。 图33亚像素数据的创建 复制Contours的方式和复制Region和Image的方式相同,输入CopyXLD:=contours就可以完成复制了。 数组的赋值共有四种类型: 第一种是给数组赋空值,通过代码EmptyTuple:=[]来实现数组赋空值; 第二种是给数组赋单值,通过代码Value:=1来给数组赋单值; 第三种是给数组赋多值,通过在“[]”中写入多个值来实现,值与值之间使用“,”隔开; 最后是创建相同数值的数组,可通过tuple_gen_const函数实现,这个函数的参数中: (1) 第一个参数Length是输入相同的数值的个数; (2) 第二个参数Const是相同数值的值; (3) 第三个参数Newtuple为输出的结果。 3.2if语句 if语句用于条件选择,即根据不同条件选择执行不同的主体语句。if语句的结构如下: if(条件) 主体语句 elseif(条件) 主体语句 else 主体语句 endif 通过下面的例子对if语句进行讲解。 *if语句的判断使用 Value:=10 Result:=0 *大于 if(Value>10) Result:=1 endif 给Value赋值为10,初始化结果变量Result,将其赋值为0。上例是一个“大于”的比较条件,如果Value大于10就会执行if语句中的主体语句,结果变量Result就等于1。这是HALCON的一个if语句,是if加上endif的结构,后面不需要任何的括号来结尾,而是通过if和endif来自动分割语句部分。 *小于 Result:=0 if(Value<10) Result:=1 endif 上例是一个“小于”的比较条件,第一行是if(Value<10),即如果Value小于10,Result的值为1。 *大于或等于 Result:=0 if(Value>=10) Result:=1 endif 上例是“大于或等于”的比较条件,先把Result初始化为0,然后判断条件改为Value大于或等于10,例子中,“大于或等于”使用的是“>”加上“=”的方式,然后用endif结束循环。 *小于或等于 Result:=0 if(Value<=10) Result:=1 endif 上例是“小于或等于”的比较条件,Result初始化为0,然后写入if(Value<=10),例子中,“小于或等于”使用“<”加上“=”来表示。 *等于 Result:=0 if(Value=10) Result:=1 endif Result:=0 if(Value==10) Result:=1 endif 上例是“等于”的比较条件,Result初始化为0,方便验证结果。HALCON中if的“等于”语句有两种写法,第一种是if(Value=10),在HALCON中“=”为判断语句,而不是赋值语句; 第二种写法是if(Value==10),即用两个等号表示判断,在C语言中也是这样用的,表示判断Value是否等于10。 *不等于 Result:=0 if(Value#9) Result:=1 endif Result:=0 if(Value!=9) Result:=1 endif 上例是“不等于”的比较条件,“不等于”有两种写法,第一种是if(Value#9),用#来表示“不等于”; 还有一种写法和C语言类似,使用“!”加上“=”来表示“不等于”。 *与条件,两个条件均为true,则为true Tuple:=5 Value:=10 Result:=0 if(Value>9 and Tuple>4) Result:=1 endif 上例是两个条件判断的“与”关系,初始化Result变量为0,然后创建Tuple变量且值为5,然后进入if条件选择,一个条件为Value>9,一个条件为Tuple>4,与关系使用and来表示。Result的结果等于1,说明Value>9和Tuple>4两个条件都满足,如果Result的结果等于0,说明两个结果并不同时满足。 *条件或,一个条件为true,则为true Result:=0 Value:=10 Tuple:=5 if(Value>10 or Tuple>4) Result:=1 endif 上例是两个条件判断的“或”关系,使用or来表示,表示在多个条件中,只要有一个条件是正确的,总的结果就是正确的。Value大于10和Tuple大于4这两个条件只要有一个满足,可以得到Result的结果等于1。 *条件异或,两个结果相同为false Result:=0 Value:=10 Tuple:=5 if(Value>10 xor Tuple>5) Result:=1 endif 上例是两个条件判断的“异或”关系,使用xor来表示,描述的是如果多个条件的结果都相同,则总结果为false,即结果为0; 如果有不同的结果则为true,即总结果为1。例子中两个条件判断的结果都为0,结果相同,所以变量Result为0。 *非语句 Result:=0 Value:=10 Tuple:=5 if(not(Value>10 and Tuple>5)) Result:=1 endif 上例是非语句,使用not来表示,表示在当前的结果条件下取相反的结果,例如结果是正确的,那就取错误的结果; 如果结果是错误的则取正确的结果。例子中两个判断的结果都为0,这两个条件的与结果也为0,经过非语句变换结果为1,所以Result的结果为1。 *if多重选择 Result:=0 Value:=10 Tuple:=5 if(Value>9) Result:=1 elseif(Tuple>5) Result:=1 else Result:=0 endif 上例是if的多重选择,先初始化Result变量为0,多重选择中用到了if、elseif、else和endif语句。elseif是在if的条件判断为错误的时候进行的判断,判断语句的编写和if一致。例子中先判断Value>9是否为正确的,如果不正确,进入elseif的判断条件; 再判断Tuple>5是否是正确的,如果Tuple大于5不正确,就会进入else的主体语句,即默认的主体语句; 如果不存在默认的主体语句,则直接跳出if判断。例子中Value>9为true,所以Result的值为1。 3.3for循环语句 下例介绍HALCON 的for循环语句。在编程中经常会用到循环语句,来进行循环往复的操作。 for循环的结构如下: for(Index:=StartNumber to EndNumber by Step) 循环的语句 endfor 其中,Index是循环的变量,每次循环结束都会加上Step的值; StartNumber是开始的数值; EndNumber是结束的数值; 当Index大于EndNumber时,循环就结束了。下面是for循环例子。 *循环的次数 EndNumber:=10 *初始化数组 Array:=[] for i:=1 to EndNumber by 1 Array:=[Array,i] endfor 首先把循环次数设置为10,初始化Array数组为空,循环起始的数值设置为1,步长也设置为1,在循环结构里把i插入数组Array中。运行的结果为[1,2,3,4,5,6,7,8,9,10]。 可以把Step设置成其他的数值来加大步长,例子如下: Array1:=[] EndNumber:=10 for i:=0 to EndNumber-1 by 2 Array1:=[Array1,i] endfor 把Step设置为2,结束数值设置为EndNumber-1,i设置成0,得到的结果为[0, 2, 4, 6, 8]。 Step不仅可以设置为正数,也可以设置为负数,例子如下: Array2:=[] EndNumber:=10 for i:=EndNumber to 1 by -1 Array2:=[Array2,i] endfor 把Step设置为-1,把i设置为EndNumber,即10,EndNumber设置为1,得到的结果是[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]。 3.4中断语句 在HALCON中,continue和break是用来继续运行下次循环和跳出当前循环的,break和contiune可以用在for、while和switch循环中,起到控制程序运行的作用。下面是break和continue在for循环中使用的例子,在其他循环语句中的用法也是一致的。 *break和continue语句 Array3:=[] for i:=1 to Number by 1 if(i=3) continue endif if(i=7) break endif Array3:=[Array3,i] endfor 在for循环中,如果满足条件i=3,则执行continue语句,继续进行下一次的循环,数值不能存入Array3这个数组中; 如果i=7,就执行break语句,直接结束当前for循环,运行的结果是[1, 2, 4, 5, 6]; 当i=3的时候数值没有存入数组,当i=7的时候循环结束,所以7之后的数值也没有存入数组。结果符合预期。 3.5while循环语句 while循环语句是用于多次循环的语句,通过判断条件来控制循环是继续还是结束; 当条件为正确时继续执行循环,当条件为错误时退出循环。While循环语句的结构如下: while(条件) 循环体语句 endwhile while循环语句例子如下: *while语句 Flag:=0 Array:=[] Number:=5 i:=0 while(Flag=0) if(i=Number) Flag:=1 endif Array:=[Array,i] i:=i+1 endwhile 首先,设置条件变量Flag为0,Flag是用来控制while语句继续运行或中断的条件变量。然后,初始化Array为空,Number设为5,用作结束的数值,然后i设为0用来计数,通过一个while循环来实现把数写入数组中。首先是while,条件是Flag=0,可以通过改变Flag的值来终止while的循环。在while循环体里面写入主体语句,主体语句是把i放入数组中,i每次循环结束增加1。if语句用来结束while语句,判断的条件是i=Number,主体语句是Flag:=1,通过改变Flag的值来结束while语句。最后得到的结果是[0, 1, 2, 3, 4, 5]。 *repeat and until Flag:=1 Array1:=[] i:=0 repeat Array1:=[Array1,i] i:=i+1 until (Flag=1) *和while循环对比 Array3:=[] i:=0 while(Flag=0) Array3:=[Array3,i] i:=i+1 endwhile repeat和until类似于C语言中的do…while,但是有所不同。do…while语句是while的条件为正确的时候,继续执行,而repeat…until语句是当until语句为正确的时候就跳出循环。和while相比,repeat…until是先执行repeat语句,然后再进行条件判断,而while是直接进行判断。上面例子对比的是repeat…until和while的结果: Array1为0,Array3为空。这说明,在使用repeat…until时,会先执行一次主体语句。 *break和continue语句 Flag:=0 Array2:=[] i:=0 while(Flag=0) if(i=3) i:=i+1 continue endif if(i=5) break endif Array2:=[Array2,i] i:=i+1 endwhile 上例通过使用break和continue来控制while的循环结束和继续运行。使用方法与for循环类似。while循环可以在flag=0时连续进行循环,当i=3时,执行一次continue语句,不赋值给array2这个数组; 当i=5时,直接执行break,跳出整个while循环。最后array2结果是[0, 1, 2, 4],符合预期。 3.6switch语句 switch语句是一个条件选择语句,当if多层嵌套时,可以用switch来代替,使得结构简单。switch的结构如下: switch(条件) case常量表达式一: 主体语句 break case常量表达式二: 主体语句 break default: 主体语句 endswitch 使用的方法是将条件与常量表达式一一对比,当条件的值与switch的某一个常量表达式的值相等时,就执行这个常量表达式对应的主体语句。每个case只是入口,不代表执行完当前case主体语句就结束整个switch语句,如果需要在执行完case的主体语句之后结束switch,可使用break; 当没有case与条件匹配时,可以通过default来执行默认的主体语句。switch语句的例子如下: *switch语句 result:='' Index:=1 switch(Index) case 1: result:=result+'1' break *break后switch会在此跳出 case 2: result:=result+'2' break case 3: result:=result+'3' *没有break程序会继续运行 case 4: *case 4为空直接进入case 5,这样case 4和case 5的结果相同 case 5: result:=result+'5' break default: *没有匹配的case,就会进入default默认语句 result:='-1' endswitch 首先初始化result字符串为空,然后把Index设为1,开始执行switch语句,判断Index和case是否匹配。Index匹配到了1,继续往下运行,运行到result=result+'1',然后执行break,跳出整个switch语句,就完成switch语句的执行,result的结果是1。 把Index改为2时,执行一次switch语句,结果是result等于2,因为它进入case 2的主体语句中。 如果把Index改为3,执行一次switch语句,语句会执行到case 3的主体语句,然后执行result=result+'3'这一语句,由于case 3后面没有写break,会继续执行接下来的程序; 执行到case 4,case 4是一个空的语句,后面也没有写 break,程序还会继续往下执行; 执行到case 5,然后执行result=result+'5'这一语句,case 5后面有break语句,跳出switch语句,result结果为35。 如果把index改为6,没有case等于6,程序会运行default的主体语句,程序进入default之后,运行的结果是result='-1',然后结束switch语句。