第六十六节:Halcon深度学习环境配置与GPU加速
深度学习开发环境搭建
Halcon深度学习按照不同应用范围分为三个方向[1]:
- 目标检测:用于定位项目,得到物料的位置坐标和角度
- 分类:用于缺陷检测,可得到物料是好是坏
- 语义分割:用于缺陷检测,可得到缺陷区域
环境配置步骤
- 安装显卡驱动
确保安装支持CUDA的NVIDIA显卡驱动,这是GPU加速的基础[1]。
-
安装CUDA并行通用架构
- 验证CUDA环境
system('nvidia-smi')
- 验证CUDA环境
-
安装深度学习的Halcon环境
配置深度学习专用的Halcon运行时环境,支持GPU计算加速[1]。
- 安装打标签软件
使用专门的深度学习数据标注工具,为训练样本生成准确的标签[1]。
第六十七节:目标检测深度学习实现流程
数据集准备与标注
打标签过程:
- 新建项目 - 创建目标检测项目
- 框选目标 - 为每张图像打标签,尽量使矩形框相切框住物料
- 重叠处理 - 对于重叠的物体,需要按照物体本身的大小框住重叠区域
- 导出数据 - 打完标签后,导出数据为数据集[11]
深度学习网络创建
* 读入数据集
read_dict('dataset.hdict', [], DLDataset)
* 创建数据字典
create_dict(Dict)
set_dict_tuple(Dict, 'image_width', 416)
set_dict_tuple(Dict, 'image_height', 416)
set_dict_tuple(Dict, 'batch_size', 8)
* 创建神经网络模型
create_dl_model_detection('yolo_v3', 3, Dict, DLModelHandle)
模型训练与优化
* 设置模型参数
set_dl_model_param(DLModelHandle, 'batch_size', 8)
set_dl_model_param(DLModelHandle, 'learning_rate', 0.001)
set_dl_model_param(DLModelHandle, 'min_confidence', 0.5)
* 训练模型
create_dl_train_param(DLModelHandle, 100, [], [], TrainParam)
train_dl_model(DLModelHandle, TrainParam, 0, [])
第六十八节:语义分割深度学习实现
语义分割数据准备
打标签工具使用:
- 准备classes.txt文件,表示各个类别的名称,一个类别一行
- 准备打标签的图需放入image文件夹内,文件夹名称必须为image
- 使用专门打标签软件进行像素级标注[7]
标注操作步骤:
- 按字母a表示添加一个标签
- 按字母n开始画区域,用鼠标在图像上圈区域
- 右键确认,并按数字键选择圈住的区域的类型
- 按字母c,按下数字选择区域所对应的正确的类型,按回车
- 按字母d,保存该张图
- 按向右箭头,接着下一张图标注[7]
语义分割模型训练
* 语义分割模型创建
create_dl_model_segmentation('unet', 2, Dict, DLSegModelHandle)
* 数据集预处理
preprocess_dl_dataset(DLDataset, 'preprocessed/', [], PreprocessParam)
* 模型训练
train_dl_model(DLSegModelHandle, TrainParam, 0, [])
第六十九节:字符识别与OCR技术
OCR分类器训练流程
创建MLP神经网络
* 创建分类器
create_ocr_class_mlp(80, 60, 'softmax', 'normalization', 10, [], [], OCRHandle)
* 训练样本准备
write_ocr_trainf(CharRegions, CharImage, Characters, 'train.trf')
* 追加训练样本
append_ocr_trainf(CharRegions, CharImage, Characters, 'train.trf')
* 训练模型
trainf_ocr_class_mlp(OCRHandle, 'train.trf', 100, 0.001, 0.001, Error, ErrorLog)
字符预处理技术
图像增强与分割
* 拉开灰度对比度
emphasize(Image, ImageEnhanced, 10, 10, 1.0)
* 字符分割
char_threshold(ImageEnhanced, Regions, 20, 95)
* 字符区域优化
opening_rectangle1(Regions, RegionsOpened, 1, 1)
connection(RegionsOpened, ConnectedRegions)
select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 50, 10000)
OCR文本模型识别
* 创建文本模型
create_text_model_reader('auto', [], TextModel)
* 设置文本模型参数
set_text_model_param(TextModel, 'min_font_height', 20)
set_text_model_param(TextModel, 'max_font_height', 80)
* 文本查找
find_text(Image, TextModel, TextResult)
第七十节:工业相机标定技术
单目相机标定流程
标定板描述文件生成
* 生成圆形标定板描述文件
gen_caltab(7, 7, 0.0125, 0.3, 'caltab.ps', 'caltab.descr')
标定助手应用
标定步骤:
-
采集标定板图像 - 采集10-15张标定板图像,尽量覆盖整个视野[36]
-
设置标定参数 - 包括焦距、畸变系数、像元尺寸等[36]
-
执行标定 - 使用TSAI两步标定法计算内外参[36]
-
评估标定精度 - 计算反向投影均方误差(RMSE)[36]
-
创建标定模型
create_calib_data('calibration_object', 1, 1, CalibDataID) -
设置初始内参
set_calib_data_cam_param(CalibDataID, 0, 'area_scan_polynomial',
[0.008, 0, 5.12e-6, 5.12e-6, 1280, 960, 2560, 1920]) -
设置标定板描述文件
set_calib_data_calib_object(CalibDataID, 0, 'caltab.descr') -
采集并标定
for Index := 1 to 12 by 1
read_image(Image, 'calib_' + Index$'02d')
find_calib_object(Image, CalibDataID, 0, 0, Index, [])
get_calib_data_observ_points(CalibDataID, 0, 0, Index, Row, Col, Pose)
endfor
calibrate_cameras(CalibDataID, Errors)
-
第七十一节:手眼标定技术
眼在手上手眼标定
标定原理与实现
基本原理:确定机械手坐标系(Base、Tool)和摄像机坐标系之间的矩阵转换关系[16]。
* 读取保存的标定数据
read_pose('eye_hand_poses.dat', EyeInHandPoses)
read_image(Image, 'calib_image_1')
* 创建标定模型
create_calib_data('hand_eye_moving_cam', 1, 1, CalibDataID)
* 设置标定参数
set_calib_data_cam_param(CalibDataID, 0, 'area_scan_polynomial', CameraParams)
set_calib_data_calib_object(CalibDataID, 0, 'caltab.descr')
* 添加标定观察
for Index := 1 to 15 by 1
read_image(Image, 'handeye_' + Index$'02d')
find_calib_object(Image, CalibDataID, 0, 0, Index, [])
get_calib_data_observ_points(CalibDataID, 0, 0, Index, Row, Col, Pose)
set_calib_data(CalibDataID, 'hand_eye', 'tool_in_base_pose', Index, EyeInHandPoses[Index-1])
endfor
* 执行手眼标定
calibrate_hand_eye(CalibDataID, Errors)
旋转中心标定
三点拟合圆方法[23]:
-
在相机视野内移动标志点三次,机器人U轴旋转
-
求出标志点的像素坐标,转换为世界坐标
-
根据三个点确定圆的圆心坐标
-
计算tool0和tool1之间的偏差
-
三点拟合圆求旋转中心
fit_circle_contour_xld(Contour, 'algebraic', -1, 0, 0, 3, 2, CenterRow, CenterCol, Radius, StartPhi, EndPhi, PointOrder) -
计算偏差
ToolOffsetX := Row1 - CenterRow
ToolOffsetY := Col1 - CenterCol
-
第七十二节:多相机系统标定与坐标统一
双目标定实现
标定流程
* 创建双目标定模型
create_calib_data('calibration_object', 2, 1, CalibDataID)
* 设置两个相机的初始内参
set_calib_data_cam_param(CalibDataID, 0, 'area_scan_polynomial', CamParam1)
set_calib_data_cam_param(CalibDataID, 1, 'area_scan_polynomial', CamParam2)
* 采集标定板图像(两个相机同时采集)
for Index := 1 to 12 by 1
read_image(ImageLeft, 'left_' + Index$'02d')
read_image(ImageRight, 'right_' + Index$'02d')
find_calib_object(ImageLeft, CalibDataID, 0, 0, Index, [])
find_calib_object(ImageRight, CalibDataID, 1, 0, Index, [])
endfor
* 执行双目标定
calibrate_cameras(CalibDataID, Errors)
* 获取相机间相对位姿
get_calib_data(CalibDataID, 'camera', 1, 'extrinsic_poses', Cam1ToCam2Pose)
坐标系统一方法
方法一:借助第三方坐标系
通过机器人base坐标系,将两个相机的像素点通过九点标定映射到base坐标系下[13]。
方法二:利用蜂窝标定板
使用蜂窝标定板进行多相机标定,不需要全部拍全,但至少找到一个finder,6张标定图即可[30]。
* 创建蜂窝标定板
create_caltab(10, 10, 0.008, 0.3, [50, 50, 100, 100, 150, 150, 200, 200, 250, 250, 50, 150, 250, 350, 450],
'positive', 'hexagonal_caltab.ps', 'hexagonal_caltab.descr')
第七十三节:运动控制系统集成
运动板卡控制
雷赛DMC2410板卡应用
硬件组成:驱动器、模组、开关电源、电磁阀、真空发生器、空气压缩机、吸嘴、雷赛板卡、编码器、限位开关(9个)[24]
* 运动控制算子示例
* 连续JOG运动
set_axis_status(0, 1) * 开启第一轴
start_jog(0, 1, 1000) * 开始JOG运动
* 点位运动
set_target_position(0, X, Y)
start_point_move(0, 1)
* 回零运动
home_move(0, 1)
机器人TCP通讯
爱普森机器人程序控制
* TCP通讯设置
opennet('192.168.0.100', 2000) * 连接到机器人IP地址
* 发送运动命令
send_command('MoveJ XY(' + X$'.2f' + ',' + Y$'.2f' + ',' + Z$'.2f' + ',U0)')
* 吸气控制
send_command('On 8') * 开启吸气
send_command('Off 8') * 关闭吸气
第七十四节:串口通信协议实现
Modbus RTU协议
协议格式
Modbus RTU帧格式[25]:
-
第一个字节:从站地址码
-
第二个字节:功能码
-
数据区:寄存器地址和数据
-
校验位:CRC校验或求和校验
-
创建Modbus请求
function create_modbus_request(device_addr, function_code, reg_addr, reg_count)
request = [device_addr, function_code, reg_addr_hi, reg_addr_lo, reg_count_hi, reg_count_lo]- 计算CRC校验
crc = calculate_crc16(request)
request = [request, crc_low, crc_high]
return request
endfunction - 计算CRC校验
-
发送Modbus请求
send_serial_data(request, 8)
-
C#串口通信实现
public class SerialPortManager
{
private SerialPort serialPort;
public void InitializeSerialPort(string portName, int baudRate)
{
serialPort = new SerialPort();
serialPort.PortName = portName;
serialPort.BaudRate = baudRate;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
}
// 十六进制发送
public void SendHexData(string hexString)
{
byte[] data = new byte[hexString.Length / 2];
for (int i = 0; i < data.Length; i++)
{
data[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
serialPort.Write(data, 0, data.Length);
}
// 字符串发送
public void SendStringData(string data)
{
byte[] byteData = Encoding.Default.GetBytes(data);
serialPort.Write(byteData, 0, byteData.Length);
}
}
第七十五节:网络通信协议实现
TCP/UDP通信
TCP服务器端实现
public class TcpServerManager
{
private TcpListener tcpListener;
private NetworkStream networkStream;
public async Task StartServerAsync(int port)
{
tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
while (true)
{
TcpClient client = await tcpListener.AcceptTcpClientAsync();
await HandleClientAsync(client);
}
}
private async Task HandleClientAsync(TcpClient client)
{
networkStream = client.GetStream();
byte[] buffer = new byte[1024];
int bytesRead = await networkStream.ReadAsync(buffer, 0, buffer.Length);
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
// 处理接收到的数据
ProcessMessage(message);
// 发送响应
string response = "Message received: " + message;
byte[] responseData = Encoding.UTF8.GetBytes(response);
await networkStream.WriteAsync(responseData, 0, responseData.Length);
}
}
UDP通信实现
public class UdpCommunicationManager
{
private UdpClient udpClient;
public void InitializeUdpClient(int localPort)
{
udpClient = new UdpClient(localPort);
}
public async Task SendUdpMessage(string message, string remoteHost, int remotePort)
{
byte[] data = Encoding.UTF8.GetBytes(message);
await udpClient.SendAsync(data, data.Length, remoteHost, remotePort);
}
public async Task<string> ReceiveUdpMessage()
{
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = await udpClient.Receive(ref remoteEP);
return Encoding.UTF8.GetString(data);
}
}
第七十六节:光源选型与光学系统设计
光源分类与应用
各类光源特点
环形光源[28]:
- 使用率最高,光线方向性较强
- 低角度环形光源一般打凹凸缺陷、划痕等
- 高角度范围大,各方向都有打光
同轴光源:
- 适合打金属等反光物料、凹凸物料
- 会降低亮度,打光面积较小
背光源:
- 适合透明物料、或测量项目
- 一般用短波长,衍射弱,蓝光
打光原则与技巧
反射定律应用[28]
* 光源选择判断逻辑
if (MaterialType == 'metal' and SurfaceType == 'mirror')
* 使用偏振片+同轴光源
LightSource = 'coaxial'
Polarizer = true
elseif (DefectType == 'scratch')
* 使用低角度环形光
LightSource = 'low_angle_ring'
Angle = 30 * 30度低角度
elseif (MaterialType == 'transparent')
* 使用背光源
LightSource = 'backlight'
Wavelength = 'blue' * 蓝光
endif
光源大小计算[28]
* 计算光源大小
* 光源大小最小为视野大小的两倍
LightSize = 2 * FOV
LightSize = max(LightSize, MinLightSize) * 确保不小于最小尺寸
第七十七节:镜头选型与焦距计算
镜头焦距计算公式
基本焦距公式[40]
* 根据工作距离和视野计算焦距
* 公式1: f = (WD * CCD_Size) / FOV
* 公式2: f = (Magnification * WD) / (Magnification + 1)
calculate_lens_parameters(WorkDistance, FOV, CCDWidth, CCDHeight, Magnification, FocalLength, FNumber)
* 其中:
* WorkDistance: 工作距离(mm)
* FOV: 视野范围(mm)
* CCDWidth/Height: CCD靶面尺寸(mm)
* Magnification: 放大倍率
* FocalLength: 计算出的焦距(mm)
远心镜头选型[40]
远心镜头优势:
-
可矫正畸变,精度要求高时使用
-
当客户精度要求非常高、视野比较小、物料比较小时使用
- 远心镜头参数选择
if (AccuracyRequirement >= 0.01) * 精度要求1丝以上
LensType = 'telecentric'
Magnification = RequiredFOV / CCDSize
WorkingDistance = 65 * 标准远心镜头工作距离
endif
- 远心镜头参数选择
景深计算与应用[40]
* 景深计算
* DOF = (2 * CircleOfConfusion * FNumber * (Magnification + 1)) / (Magnification^2)
calculate_depth_of_field(Magnification, FNumber, COC, DepthOfField)
* 景深影响因素
* 焦距越小,景深越大
* 光圈越小,景深越大
* 工作距离越大,景深越大
第七十八节:频域图像处理技术
频域滤波器设计
高斯滤波器应用
* 创建高斯滤波器
gen_gauss_filter(GaussFilter, 512, 512, 1.0, 1.0, 0, 'none', 0, 0, 512, 512)
* 频域滤波
convol_fft(Image, GaussFilter, ImageFiltered)
带通滤波器
* 正弦带通滤波器 - 适用于微小划痕
gen_sin_bandpass(SinBandpass, 512, 512, 'none', 0, 0, 512, 512)
* 差分滤波器
gen_gauss_filter(Gauss1, 512, 512, 0.5, 1.5, 0, 'none', 0, 0, 512, 512)
gen_gauss_filter(Gauss2, 512, 512, 1.0, 1.0, 0, 'none', 0, 0, 512, 512)
sub_image(Gauss1, Gauss2, DiffFilter, 1, 0)
频域缺陷增强
* 利用频域得到背景图,空间域差分增强缺陷
power_real(FFTImage, PowerSpectrum)
convert_image_type(PowerSpectrum, PowerSpectrum, 'byte')
threshold(PowerSpectrum, BackgroundRegion, 128, 255)
gen_image_proto(PowerSpectrum, BackgroundImage, 255)
* 空间域差分
sub_image(Image, BackgroundImage, DefectImage, 1, 128)
emphasize(DefectImage, DefectEnhanced, 3, 3, 1.5)
第七十九节:二维码识别技术
二维码码制选择与参数设置
常用码制特点[29]
-
QR码:最常见的码,有三个方框和一个小方框
-
Data Matrix ECC 200:无任何标记的二维码
-
Aztec Code:中间有个框
-
Micro_QR Code:左下角有个方框
-
创建二维码模型
create_data_code_2d_model('Data Matrix ECC 200', 'default_parameters', [], QRCodeModel) -
设置识别参数
set_data_code_2d_param(QRCodeModel, 'symbol_size_min', 10)
set_data_code_2d_param(QRCodeModel, 'symbol_size_max', 100)
set_data_code_2d_param(QRCodeModel, 'contrast_min', 30)
set_data_code_2d_param(QRCodeModel, 'module_gap_min', 'no')
-
难识别二维码处理
透视变换矫正
* 二维码透视变换
* 找到二维码四个角点
points_foerstner_sub_pix(Image, 1, 200, 3, 'gauss', 1, 0, 'true', Row, Col, JI, COV, PSI)
* 计算透视变换矩阵
hom_vector_to_proj_hom_mat2d(Row, Col, [1,1,1,1], RowTrans, ColTrans, [1,1,1,1], 'normalized', HomMat2D)
* 应用透视变换
projective_trans_image(Image, ImageCorrected, HomMat2D, 'bilinear', 'false', 'false', 0.5)
* 在矫正后图像中识别二维码
find_data_code_2d(ImageCorrected, SymbolXLDs, QRCodeModel, 30, 35, ResultHandles, DecodedDataStrings)
第八十节:一维码识别技术
条码码制与参数设置
常用码制特点[42]
-
Code 128:通用性最强,支持所有ASCII字符
-
Code 39:支持数字和大写字母
-
EAN-13:商品条码,13位数字
-
ITF:交叉25码,只支持数字
-
创建一维码模型
create_bar_code_model('auto', 'default_parameters', BarCodeModel) -
设置码制类型
set_bar_code_param(BarCodeModel, 'code_type', 'Code 128') -
设置识别参数
set_bar_code_param(BarCodeModel, 'element_size_min', 2)
set_bar_code_param(BarCodeModel, 'element_size_max', 8)
set_bar_code_param(BarCodeModel, 'contrast_min', 20)
set_bar_code_param(BarCodeModel, 'check_char', 'absent')
-
特殊条码处理
凹凸状一维码处理[49]
* 环形一维码处理
* 先进行极坐标转换拉直
image_to_polar_coords(Image, PolarImage, 512, 512, 256, 256, 100, 200, 0, 6.28318, 'interpolation')
* 然后在拉直图像中识别条码
find_bar_code(PolarImage, SymbolRegions, BarCodeModel, 'auto', 'interpolated', DecodedDataStrings)
参数调优
* 针对小条码优化
set_bar_code_param(BarCodeModel, 'symbol_size_min', 5)
set_bar_code_param(BarCodeModel, 'symbol_size_max', 15)
set_bar_code_param(BarCodeModel, 'element_size_variable', 'true')
* 启用投票机制
set_bar_code_param(BarCodeModel, 'majority_voting', 'true')
第八十一节:工业测量技术
二维测量实现
测量助手应用[38]
测量流程:
-
定位 → 确定测量基准
-
分割 → 提取边缘特征
-
拟合 → 使用最小二乘法
-
标定 → 转换为实际尺寸
-
测量 → 计算几何参数
-
创建测量矩形
gen_measure_rectangle2(100, 200, 0, 50, 20, 640, 480, 'bilinear', MeasureHandle) -
边缘对测量
measure_pairs(Image, MeasureHandle, 1.0, 20, 'positive', 'all',
RowEdge, ColEdge, Amplitude, Distance, IntraDistance, InterDistance)
-
一维测量技术
亚像素边缘提取[41]
* Canny边缘检测
edges_sub_pix(Image, Edges, 'canny', 1, 20, 40)
* 直线拟合
fit_line_contour_xld(Edges, 'regression', 0, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
测量结果分析
* 计算测量值
* 两点间距离
distance_pp(RowBegin, ColBegin, RowEnd, ColEnd, Distance)
* 直线与直线夹角
angle_ll(RowBegin, ColBegin, RowEnd, ColEnd, Row2Begin, Col2Begin, Row2End, Col2End, Angle)
第八十二节:3D视觉技术应用
双目立体视觉
双目标定与重建[32]
* 双目标定
calibrate_stereo_cameras(Caltab, CalibParam1, CalibParam2, NFinalPose1, NFinalPose2, c1Pc2, Errors)
* 图像矫正
rectify_stereo_image(Image1Rect, Image2Rect, CalibParam1, CalibParam2, c1Pc2)
* 视差图计算
stereo_match(Image1Rect, Image2Rect, Disparity, Score, 'ncc', 15, 5, 5, 1, 0, 'none', 'false')
* 3D坐标重建
disparity_image_to_xyz(Disparity, CalibParam1, Row, Col, Z, X, Y)
激光三角测量
光平面标定与点云重建[21]
* 光平面标定
calibrate_sheet_of_light(LowPose, HighPose, LightPlanePose, [])
fit_3d_plane_xyz(X, Y, Z, PlaneParams)
* 点云重建
reconstruct_sheet_of_light_profile(Image, SheetOfLightModel, X, Y, Z, Intensity)
第八十三节:模板匹配进阶技术
多尺度模板匹配
等比缩放匹配[4]
* 创建等比缩放模板
create_scaled_shape_model(Template, 5, 0.8, 1.2, 0.01, 0.5, 0.8, 'auto', 'use_polarity')
* 查找缩放匹配
find_scaled_shape_model(Image, ScaleModelID, 0.8, 1.2, 0.5, 600, 1, 0.5, 'least_squares', 0, 0.8,
Row, Column, Angle, Scale, Score)
不等比缩放匹配
* 创建各向异性缩放模板
create_aniso_shape_model(Template, 5, 0.8, 1.2, 0, 0.8, 1.2, 0, 'auto', 'use_polarity')
* 查找各向异性缩放匹配
find_aniso_shape_model(Image, AnisoModelID, 0.8, 1.2, 0, 0.8, 1.2, 0, 0.5, 600, 1, 0.5,
'least_squares', 0, 0.8, Row, Column, Angle, ScaleR, ScaleC, Score)
多模板匹配
* 创建多个模板
create_shape_model(Template1, 4, 0, 0.785, 'auto', 'use_polarity', 'auto', 1, ModelID1)
create_shape_model(Template2, 4, 0, 0.785, 'auto', 'use_polarity', 'auto', 1, ModelID2)
* 模板句柄数组
ModelHandles := [ModelID1, ModelID2]
* 多模板查找
find_shape_models(Image, ModelHandles, 0, 0.785, 0.5, 8, 1, 0.5, 'least_squares', 0, 0.8,
ModelIDs, Row, Column, Angle, Score)
第八十四节:字符识别高级技术
OCR文本模型应用
自动文本分割[35]
* 创建文本模型
create_text_model_reader('auto', [], TextModel)
* 查找文本
find_text(Image, TextModel, TextResult)
* 获取文本结果
get_text_result(TextResult, 'class', TextClasses)
get_text_result(TextResult, 'confidence', TextConfidences)
手动模式OCR
* 设置文本模型为手动模式
set_text_model_param(TextModel, 'manual_text_lines', 'true')
* 查找文本(手动模式返回区域)
find_text(Image, TextModel, TextResult)
* 获取分割的字符区域
get_text_object(TextLines, TextResult, 'lines')
get_text_object(CharRegions, TextResult, 'words')
* 识别字符
do_ocr_multi_class_mlp(CharRegions, Image, OCRHandle, RecChar, Confidence)
复杂背景OCR处理
预处理技术
* 差分高斯增强
diff_of_gauss(Image, ImageEnhanced, 1.0, 2.0)
* 字符分割
partition_dynamic(CharRegions, PartitionedRegions, 20, 0.2)
* 区域优化
opening_rectangle1(CharRegions, CharRegionsOpened, 2, 2)
fill_up(CharRegionsOpened, CharRegionsFilled)
第八十五节:工业项目实战案例
自动贴合系统
系统架构
硬件组成:
- 爱普森六轴机器人
- 上相机(物料定位)
- 下相机(放置检测)
- 真空吸盘
- 控制系统[39]
贴合算法流程
* 上相机物料定位
read_image(ImageTop, 'top_image')
find_shape_model(ImageTop, TopModelID, 0, 3.14159, 0.7, 1, 0.5, 'least_squares', 0, 0.8,
TopRow, TopCol, TopAngle, TopScore)
* 计算物料姿态
affine_trans_point_2d(TopRow, TopCol, HomMat2D, WorldRow, WorldCol)
* 机器人抓取
MoveJ(L PickPose)
On 8 ' 开启吸气
WaitTime(0.5)
Off 8
* 下相机位置检测
read_image(ImageBottom, 'bottom_image')
find_shape_model(ImageBottom, BottomModelID, 0, 3.14159, 0.8, 1, 0.5, 'least_squares', 0, 0.8,
BottomRow, BottomCol, BottomAngle, BottomScore)
* 位置纠偏
* 计算位置偏差
DeltaX := BottomCol - TargetCol
DeltaY := BottomRow - TargetRow
DeltaAngle := BottomAngle - TargetAngle
* 应用纠偏
CorrectedX := PickX + DeltaX
CorrectedY := PickY + DeltaY
CorrectedU := PickU + DeltaAngle
* 放置物料
MoveL(XY(CorrectedX, CorrectedY, PlaceZ, CorrectedU))
On 9 ' 关闭吸气
分选机系统
深度学习分类集成
* 读取深度学习模型
read_dl_model('classification_model.hdl', DLModelHandle)
* 图像预处理
preprocess_dl_samples(Image, ImagePreprocessed, PreprocessParam)
* 分类推理
apply_dl_model(DLModelHandle, ImagePreprocessed, [], [], DLResult)
* 获取分类结果
get_dict_tuple(DLResult, 'classification', ClassificationResult)
* 根据分类结果控制分选
if (ClassificationResult[0] == 'good')
* 发送到合格品通道
send_command('MoveTo GoodChannel')
elseif (ClassificationResult[0] == 'defect')
* 发送到不良品通道
send_command('MoveTo DefectChannel')
endif
总结
通过Day6的学习,我们深入掌握了Halcon的高级视觉技术:
- 深度学习应用 - 目标检测、语义分割、分类的实现流程
- OCR识别技术 - 从基础字符识别到复杂文本处理
- 工业标定技术 - 相机标定、手眼标定、多相机系统
- 运动控制集成 - 机器人控制、通信协议实现
- 光学系统设计 - 光源选型、镜头配置
- 图像处理算法 - 频域处理、模板匹配进阶
- 条码识别技术 - 一维码、二维码的完整解决方案
- 工业实战 - 贴合系统、分选机等实际项目应用
这些技术构成了现代工业视觉系统的核心知识体系,为实际工程应用提供了强有力的技术支撑。
下节预告:Day7将深入学习Halcon的高级算法优化、3D视觉应用以及完整的工业项目解决方案设计。