1. Halcon基础
1.1. 图像采集和XLD
-
通道分解和组合
* Image Acquisition 01: Code generated by Image Acquisition 01 read_image (img, 'C:/Users/SKQ/Desktop/fruit.jpg') count_channels(img,channelNum) for i:=1 to channelNum by 1 access_channel(img,currentCnlImg,i) stop() endfor *分解通道 decompose3 (img,R,G,B) *合并通道 compose3(R,G,B,RAddG)
-
图像获取、阈值分割
* Image Acquisition 01: Code generated by Image Acquisition 01 *关闭窗口 dev_close_window() read_image (img, 'egypt1.png') *获取图像尺寸 get_image_size(img,width,height) *显示图片 dev_open_window(0,0,width,height,'black',Whandle) dev_display(img) *阈值分割 threshold (img, region, 23, 131) *显示结果 dev_display(region)
- 数据结构
n:=20 arr[0]:='asad' arr[10]:=30 arr[9]:=n*arr[10] *初始化一个数组,指定输出 tuple_gen_const(100,13,nums) *初始化一个输出 nums:=gen_tuple_const(10,1234)
-
流程分支
a:=10 if (a<=0) * true为1 y:=true elseif(a!=10) *false为0 y:=false else y:=20 endif score:=90 if(score>90 and score<=100) result:='优秀' endif * switch结构 result:='' idx:=1 switch (idx) case 1: result:='OK' break case 2: result:='NG' break case 3: result:='NONE' break default: result:='ERROR' endswitch
-
循环结构
*建立一个空数组 arr:=[] * for for i:=1 to 10 by 1 arr[i-1]:=i endfor stop() *arr=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] *数组赋值的特殊语法 arr:=[] for i:=1 to 10 by 1 arr:=[arr,i] endfor stop() *arr=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] *break arr:=[] for i:=1 to 10 by 1 if(i==3) continue endif if(i==7) break endif arr:=[arr,i] endfor * arr=[1,2,4,5,6] * While循环 flag:=false arr1:=[] num:=5 i:=0 while(flag==false) if(i==num) flag:=true else arr1:=[arr1,i] i:=i+1 endif endwhile * arr1=[0,1,2,3,4] * repeat until循环 flag:=false arr2:=[] j:=0 cnt:=10 repeat arr2:=[arr2,j] if(j==cnt) flag:=true else j:=j+1 endif until (flag=true)
-
ROI绘制
dev_close_window() * Image Acquisition 01: Code generated by Image Acquisition 01 read_image (img, 'C:/Users/Public/Documents/MVTec/HALCON-18.11-Progress/examples/images/claudia.png') dev_open_window_fit_image(img,0,0,-1, -1, WindowHandle) dev_display(img) *交互式画图,程序执行时在窗口绘画ROI,点击右键完成绘制,程序继续执行 draw_rectangle1(WindowHandle,r1,col1,r2,col2) *生成ROI gen_rectangle1 (ROI_0, r1,col1,r2,col2) *减少处理区域 reduce_domain(img,ROI_0,img_reduced) dev_display(img_reduced) *多边形 draw_polygon(ROI,WindowHandle) *填充 shape_trans(ROI,filled,'convex') reduce_domain(img,filled,img_reduced)
1.1.1. XLD
extended line descriptor,扩展的直线描述符,是一种描述亚像素的数据结构。
-
亚像素级边缘提取
* Image Acquisition 01: Code generated by Image Acquisition 01 *关闭窗口 dev_close_window() read_image (img, 'fabrik') *打开适应图片大小的窗口 dev_open_window_fit_image(img,0,0,-1,-1,Whandle) edges_sub_pix(img,edges,'canny',2,12,22) *显示 dev_display(edges)
1.2. 平移、旋转和缩放
1.2.1. 基础理论
1.2.1.1. 矩阵
- 概念 在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合 [1] ,最早来自于方程组的系数及常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。
A matrix is a two-dimensional array of scalars.矩阵是标量的二维数组。
- 单位矩阵和零矩阵
- 单位矩阵:从左上角到右下角的对角线上的元素都为1,其他元素都为0
- 零矩阵:所有元素都为0
当矩阵只有一列,矩阵-矩阵的乘法编程矩阵-向量乘法,结果是一个列向量。
1.2.1.2. 矩阵应用
有一些二维和三维的矩阵很实用,比如旋转、缩放和剪切的矩阵。
1.2.1.2.1. 平移矩阵
1.2.1.2.2. 旋转矩阵
http://immersivemath.com/ila/ch06_matrices/ch06.html?#auto_label_435
1.2.1.2.3. 缩放矩阵
缩放矩阵和坐标向量相乘,结果为[fxrcos(θ),fyrsin(θ)],可以看做x和y坐标分别乘了一个缩放系数得到缩放后的坐标。
1.2.1.2.4. 剪切矩阵(shearing matrix)
1.2.1.3. 矩阵的运算法则
1.3. 几何变换
常见的几何变换包括旋转、平移、缩放、镜像、转置、错切等,以及几种组合变换,包括刚体变换、相似变换、仿射变换和投影变换
1.3.1. 刚体变换
刚体变换也称为欧式变换,刚体变换只包含平移和旋转。
1.3.2. 相似变换(similarity transformation)
-
概念 相似变换:由一个平面/立体图形变换到另一个平面/立体图形,在改变过程中保持形状不变,大小、方向、位置可变。
-
性质 任何相似变换都可以分解为等比例缩放、平移、旋转的组合。
1.3.3. 仿射变换(affine transformation)
- 概念 仿射变换:由一个平面/立体图形变换到另一个平面/立体图形,在改变过程中保持直线和平行线不变,大小、方向、位置可变。
仿射变换和相似变换的区别在于允许图形任意倾斜、在两个方向上任意伸缩。
- 性质 任何仿射变换都可以分解为缩放、平移、旋转、切变(shearing)的组合。
1.3.4. 投影变换(单应性变换)
投影变换不保证直线投影之后的平行关系
1.3.4.1. 应用
单应性在计算机视觉领域是一个非常重要的概念,它在图像校正、图像拼接、相机位姿估计、视觉SLAM等领域有非常重要的作用。
投影变换相关的halcon算子: hom_vector_to_proj_hom_mat2d
1.3.5. 插值
- 概念 插值:利用已知数据预测位置数据
图像插值:给定一个像素点,根据它周围像素点的信息来对该像素点的像素进行预测。
- 为什么需要插值? 输入图像矩阵m*n,其中的元素都是整数值,经过几何变换后元素可能变成非整数值,此时需要将非整数转换为整数输出。 插值是为了保证变换后的图像和原始图像差别尽可能小。
- 常见的插值算法
- 最近邻:选取离目标点最近的灰度值作为新的插入点的灰度值
- 双线性
- 双三次
1.3.6. halcon应用
-
平移
read_image (img,'claudia') *获取图像尺寸 get_image_size(img,width,height) *打开窗口 dev_open_window(0,0,width,height,'black',WindowHandle) *显示图像 dev_display(img) * 定义平移矩阵 hom_mat2d_identity (matIdentity) hom_mat2d_translate(matIdentity,height/2,height/2,matTranslate) *平移变换 affine_trans_image(img,imgAffined,matTranslate, 'constant', 'true') affine_trans_image(img,imgAffined2,matTranslate, 'constant', 'false')
-
仿射变换(平移、旋转、缩放) 测试图:
read_image (img,'C:/Users/SKQ/Desktop/tri.png') *获取图像尺寸 get_image_size(img,width,height) *打开窗口 dev_open_window(0,0,width,height,'black',WindowHandle) *显示图像 dev_display(img) rgb1_to_gray(img,grayImg) threshold (grayImg, Regions, 202, 255) *获取中心 area_center(Regions,area,row,col) *平移 hom_mat2d_identity(mat) hom_mat2d_translate (mat,height/2-row,width/2-row,matTranslate) affine_trans_image(img,imgTranslated,matTranslate,'constant', 'false') *旋转 hom_mat2d_rotate(mat,-3.14/2,height/2,width/2,matRotate) affine_trans_image(imgTranslated,imgRotated,matRotate,'constant', 'false') * 缩放 * hom_mat2d_scale(mat,2,2,0,0,matScale) hom_mat2d_scale(mat,2,2,height/2,width/2,matScale) affine_trans_image(imgRotated,imgScaled,matScale,'constant', 'false')
1.4. 匹配
- correlation-based matching,基于相关性的匹配,基于灰度值
- shape-based matching,基于形状的匹配,基于提取的边缘生成特征模型来匹配
- component-based matching,可以看做高级的形状匹配,高级之处在于特征可以由可以移动的多个部分(旋转和平移)组成
- local deformable matching,局部变形匹配,跟形状匹配类似,但可以对形变进行处理并返回矫正的特征模型。
- perspective deformable matching,透视变形匹配,跟形状匹配类似, 可以对强透视形变进行处理。
- descriptor-based matching,跟透视形变匹配类似,主要区别在于基于点而不是边缘来创建和查找匹配模型。
- 3D matching,由许多不同的方法组成
- point-based matching,基于点的匹配,目的是合并两幅重叠的图像,匹配的结果是从一幅图像到另一幅图像的映射。
1.5. 图像增强
1.5.1. 概念
图像增强:有目的地强调图像的整体或局部特性,讲原来不清晰的图像变得清晰或强调某些感兴趣的特征,扩大图像中不同物体特征之间的差别,抑制不感兴趣的特征、改善图像质量、丰富信息量,加强图像判读和识别效果,满足某些特殊分析的需要。
1.5.2. 分类
1.5.2.1. 空间域
1.5.2.1.1. 点运算
1.5.2.1.1.1. 灰度变换
灰度变换包括:线性灰度变换、分段线性灰度变换、非线性灰度变换 相关算子:
-
取反算子
invert_image(Image:ImageInvert::)
公式:g’:=255-g
-
增强算子
emphasize(Image : ImageEmphasize : MaskWidth, MaskHeight, Factor : )
公式:res:=round((orig-mean)*Factor)+orgi
-
缩放算子
scale_image(Image : ImageScaled : Mult, Add : )
公式:g’:=g*Mult+Add
1.5.2.1.1.2. 直方图修正
1.5.2.1.2. 邻域运算
1.5.2.1.2.1. 图像平滑
- 噪声
- 均值滤波 适合去除高斯噪声
- 中值滤波 适合去除椒盐噪声
1.5.2.1.2.2. 图像锐化
锐化:增强图像的边缘或轮廓,突出边缘和轮廓信息,原理是边缘检测。
边缘检测一般是基于梯度法(微分法):
- 基于一阶导数:一阶导数极值点为边界,包括Robert/Cross算子、Prewitt算子、Sobel算子、Krisch算子等
- 基于二阶导数:二阶导数过零点处为边界,包括Canny算子、Laplacian算子、Log算子等
1.5.2.1.3. 频率域
- 图像低频部分:灰度均匀的区域对应低频部分
- 图像高频部分:噪声、边缘、细节对应高频部分
滤波器:
- 低通滤波器:允许低频部分通过,滤除高频部分
- 高通滤波器:允许高频部分通过,滤除低频部分
频域处理步骤: 1) 进行快速傅里叶变换 2) 生成滤波器 3) 在频域中使用滤波器进行卷积 4) 反向傅里叶变换得到图形
1.5.2.1.3.1. 低通滤波器
低通滤波器滤除高频如噪声、边缘,用于图像平滑
dev_close_window()
read_image (img,'fabrik')
dev_open_window_fit_image(img,0,0,-1,-1,WindowHandle)
dev_display(img)
*加噪声
add_noise_white(img,imgNoise,20)
get_image_size(imgNoise,width,height)
*创建低通滤波器
gen_lowpass (imgLowpass,0.3, 'none', 'dc_center', width, height)
*进行傅里叶变换得到频率图像
fft_generic (imgNoise,imgFFT,'to_freq', -1, 'sqrt', 'dc_center', 'complex')
*进行低通滤波
convol_fft (imgFFT,imgLowpass,imgConvol)
*反向傅里叶变换
fft_generic (imgConvol,imgResult,'from_freq', -1, 'sqrt', 'dc_center', 'complex')
*显示图像
dev_display(imgResult)
1.5.2.1.3.2. 高通滤波器
高通滤波器滤除低频成分,用于图像锐化
1.5.2.1.3.3. 同态滤波增强
同态滤波是把图像的照明和反射模型作为频域处理的基础,将亮度范围压缩和对比度增强的频域处理方法。
一幅图像f(x,y)可以用它的照明分量i(x,y)和反射分量r(x,y)表示: f(x,y)=i(x,y)*r(x,y)
同态滤波是改善图像照度不均的一种方法,以便后续进行二值化处理。
1.6. 图像分割
1.6.1. 阈值分割
按灰度值进行分割的图像分割方法