halcon相机标定及图像矫正(代码)

侵删

1 halcon相机标定和图像矫正

对于相机采集的图片,会由于相机本身和透镜的影响产生形变,通常需要对相机进行标定,获取相机的内参或内外参,然后矫正其畸变。相机畸变主要分为径向畸变和切向畸变,其中径向畸变是由透镜造成的,切向畸变是由成像仪与相机透镜的不平行造成的。

针孔模型是理想透镜的成像模型,但是实际中相机的透镜不可能是理想的模型,透镜形状的非理想特征造成像点会沿径向发生畸变。一个像点沿径向内缩叫负畸变,或桶形畸变沿径向外延叫正畸变,或枕形畸变。这种崎变相对于光轴严格对称的,也是畸变的主要分量。

图1径向畸变                           图2切向畸变

相机标定模型公式,

 

                  Or                                                                      (1-1)

其中,(X,Y,Z)为世界坐标系中的实际点坐标,(u,v)为图像坐标系统的像素坐标,A为相机内参,f像素单元的焦距,c图像像素中心点。

                                                   (1-2)

 

图3相机成像模型

1.1 halcon相机标定

1.1.1标定助手及相机参数设置

打开halcon标定助手,加载标定板文件,选择相机类型,设置相机参数,然后加载相机采集的标定图像,如下图所示,图像中全部标定点能够检测出,即采集的相机已经设置好,然后生成代码。

 

图4 halcon标定助手

标定板生成:

标定板文件的生成分为.descr和.cpd的文件,不同格式文件需使用不同函数进行生成。如,

*生成的是27*31,标定点直径0.0075mm的.cpd标定板(精度高标定板)

create_caltab (27, 31, 0.0075, [13, 6, 6, 20, 20], [15, 6, 24, 6, 24], 'light_on_dark', 'D:/calplate.cpd', 'caltab.ps')

*生成的是7*7,标定点之间距离0.1m,直径0.5的.descr标定板

gen_caltab( 7, 7, 0.1, 0.5, 'D:/caltab.descr', 'caltab.ps')

加载标定图像:

 

图5加载标定图像

如图5所示,加载标定图像后,状态为确定时,表示标定图像可用于进行标定,然后通过标定助手直接生成标定代码即可。

    如图6所示,加载标定图像后,状态为检测出品质问题,此原因大多是照片质量问题,例如光照、对焦、曝光等,需按照halcon标定注意事项的内容拍摄照片。一般照片检测出品质问题也可以进行相机标定。

加载标定板图像会出现“标志点提取失败”,出现此原因的需要根据标定界面下的状态栏查找halcon错误信息,例”inconsistent....(image mirrored? )”,则需要查找相应原因(实际标定板(透明)与标定板文件图片的可能有镜像区别,将实际标定板翻转即可,多试)。此不可进行相机标定。

                            

图6 相机标定问题

相机初始参数设置:

例如,

*(f, k, cell width, cell height, cx, cy, width, height)k为畸变系数

StartParameters := [0.029,0,4.3e-006,4.3e-006,2592,1728,5184,3456]

*(f, k1, k2, k3, p1, p2, cell width, cell height, cx, cy, width, height)k1,k2,k3径向畸变, p1,p2为切向畸变

StartParameters := [0.029,0,0,0,0,0,4.3e-006,4.3e-006,2592,1728,5184,3456]

其中,相机初始参数根据相机模型的不同而不同,若相机模型为area(division),则相机参数为7个,若area(多项式),则相机参数12个。

1.1.2 标定程序

利用标定助手生成代码,然后执行结果,分析其正确性,若需要将其生成为C/C++程序,可通过halcon界面的‘文件’项‘导出’成.cpp文件。

 

图7 halcon生成C程序

Halcon标定程序

*Calibration 01: Code generated by Calibration 01

*读入某个文件夹下的所有标定图像

list_files ('D:/halconvc/img', ['files','follow_links'], ImageFiles)

tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm

|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)

*初始标定参数设置及定义标定板文件

TmpCtrl_ReferenceIndex := 0

TmpCtrl_PlateDescription := 'D:/calib/calplate.cpd'

StartParameters := [0.029,0,0,0,0,0,4.3e-006,4.3e-006,2592,1728,5184,3456]

TmpCtrl_FindCalObjParNames := 'sigma'

TmpCtrl_FindCalObjParValues := 1

 

* Calibration 01: Create calibration model for managing calibration data

create_calib_data ('calibration_object', 1, 1, CalibHandle)

set_calib_data_cam_param(CalibHandle,0,'area_scan_polynomial', StartParameters)

set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription)

* Calibration 01: Collect mark positions and estimated poses for all plates

gen_empty_obj (Images)

for Index := 0 to |ImageFiles|-1 by 1

    read_image (Image, ImageFiles[Index])

    concat_obj(Images,Image,Images)

*提取图像Images中标定板上的圆形标志来确定标定板的有效区域

    find_calib_object (Image, CalibHandle, 0, 0, Index, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues)

endfor

* Calibration 01: Perform the actual calibration

calibrate_cameras (CalibHandle, TmpCtrl_Errors)

get_calib_data (CalibHandle, 'camera', 0, 'params', CameraParam)

 

   *将内外参保存到磁盘

write_cam_par(CameraParam,'D:/halconvc/campar.dat')

get_calib_data (CalibHandle, 'calib_obj_pose', [0, TmpCtrl_ReferenceIndex], 'pose', CameraPose)

set_origin_pose (CameraPose, 0, 0, 0.01, CameraPose)

write_pose(CameraPose,'D:/halconvc/campos.dat')

stop()

 

*另外读取内外参文件的函数

read_cam_par ('D:/halconvc/campar.dat', CameraParam)

read_pose ('D:/halconvc/campos.dat', CameraPose)

1.2图像矫正

Halcon中图像矫正,接上述程序,以下介绍两种方法。

使用内外参,即相机内参和位资

*  goal: rectify images

*  first determine parameters such that the entire image content is visible

*  -> transform image boundary into world plane, determine smallest

*     rectangle around it

*当设备固定后,位资是唯一的

select_obj(images,image,1)

get_image_pointer1(Image, Pointer, Type, Width, Height)

gen_rectangle1 (ImageRect, 0, 0, Height-1, Width-1)

gen_contour_region_xld (ImageRect, ImageBorder, 'border')

contour_to_world_plane_xld(ImageBorder, ImageBorderWCS, CameraParam,

CameraPose, 1)

smallest_rectangle1_xld (ImageBorderWCS, MinY, MinX, MaxY, MaxX)

set_origin_pose(CameraPose, MinX, MinY, 0.01, PoseForEntireImage)

image_points_to_world_plane(CameraParam,PoseForEntireImage,[Height/2, Height/2, Height/2+1], [Width/2, Width/2+1, Width/2], 1, WorldPixelX, WorldPixelY)

distance_pp(WorldPixelY[0], WorldPixelX[0], WorldPixelY[1], WorldPixelX[1],

            WorldLength1)

distance_pp(WorldPixelY[0], WorldPixelX[0], WorldPixelY[2], WorldPixelX[2],

            WorldLength2)

ScaleForSimilarPixelSize := (WorldLength1+WorldLength2)/2

*  -> determine output image size such that entire input image fits into it

ExtentX := MaxX-MinX

ExtentY := MaxY-MinY

WidthRectifiedImage := ExtentX/ScaleForSimilarPixelSize

HeightRectifiedImage := ExtentY/ScaleForSimilarPixelSize

*  create mapping with the determined parachuangjia

*创建一个投射图,其描述图像平面与坐标轴系统中平面Z为零之间的映射

gen_image_to_world_plane_map(Map, CameraParam, PoseForEntireImage, Width, Height, WidthRectifiedImage, HeightRectifiedImage, \

                             ScaleForSimilarPixelSize, 'bilinear')

clear_calib_data (CalibHandle)

 

* Map the images

for I :=  1 to |ImageFiles| by 1

  select_obj (Images, Img, I)

  map_image (Img, Map, ImageMapped)

  write_image (ImageMapped, 'jpg', 0, 'D:/halconvc/picture/'+I)

Endfor

②仅使用内参

read_image (Image,'D:/halconvc/img/IMG_00.JPG')

read_cam_par('D:/halconvc/campar.dat',CameraParam)

CarParamVirtualFixed:=CameraParam

*对于area(diversion)相机模型(7个参数)

change_radial_distortion_cam_par('adaptive',CameraParam,0,CarParamVirtualFixed)

*对于area(多项式)相机模型(12个参数)

change_radial_distortion_cam_par('adaptive',CameraParam,[0,0,0,0,0],CarParamVirtualFixed)


*上述相机模型选一种后进行下面的map_image

*创建一个投射图,其描述图像与其相应正在改变的径向畸变,而对于12个参数的畸变包括径向和切向畸变

gen_radial_distortion_map(Map,CameraParam,CarParamVirtualFixed,'bilinear')

map_image(Image,Map,ImageMapped)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254706.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

函数参数的传递问题(一级指针和二级指针)

函数参数的传递问题(一级指针和二级指针) [转]原以为自己对指针掌握了,却还是对这个问题不太明白。请教! 程序1: void myMalloc(char *s) //我想在函数中分配内存,再返回 { s(char *) malloc(100); } void …

Win7下使用U盘安装linux Ubuntu16.04双系统图文教程

Win7下使用U盘安装linux Ubuntu16.04双系统图文教程 Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的开源GNU/Linux操作系统,Ubuntu 是基于DebianGNU/Linux,支持x86、amd64(即x64)和ppc架构&#xf…

CoDeSys的前世今生

工作以及网上看到不少人说,CoDeSys和西门子step7,在德国都属于标准过程,牛逼的小朋友都可以用其编程,不知真假,相信无风不起浪,多少有些依据,看看国內清一色的日系编程…

Eclipse中执行Ant脚本出现Could not find the main class的问题及解

试过了:https://blog.csdn.net/bookroader/article/details/2300337 但是不管用,偶然看到这篇没有直接关系的 https://blog.csdn.net/jiuyueguang/article/details/9350753 联想了一下。项目是JDK1.5,Eclipse是JDK1.8启动,所以在R…

视频通话研究002

还是关于视频质量。经測试,在公网server使用SQCIF(128x98)进行视频通话。2个client都是这个设置,感觉不出马赛克,模糊严重,在一个手机client抓包,例如以下: 第1,2行是client发到server的数据;第…

实力打脸: 量子隐形传输与 “瞬间移动” 毫无关系

有两个团队已经在量子隐形传输研究领域创造了新的传输记录:利用深不可测的量子力学知识将一个粒子的量子态迅速从一个位置迁移到另一个位置的粒子上。其中一个团队采用这种方法,运用一种光学纤维将一个光子的量子态穿越加拿大西南部的一个城市&#xff0…

Android初级教程:使用xml序列器

之前备份短信的时候生成xml都是手动拼写的&#xff0c;有一个问题&#xff1a;当短信里面存在</body>这样的标签的时候&#xff0c;最后结果就不是完整的xml文件&#xff0c;显然出错。但是&#xff0c;今天使用序列化器的方式&#xff0c;就能有效的解决上边遇到的问题。…

KUKA 声明变量时的几点注意

临时变量&#xff1a; 1、src文件中定义的局部变量&#xff0c;该种变量存在于内存中的栈上。子程序调用时&#xff0c;变量在栈上动态生成。调用结束后从栈中自动销毁。 因为存在于栈上的原因&#xff0c;访问该变量需要栈指针&#xff0c;所以该种变量无法在机器人程序运行时…

简单实现

1.创建接口和实现类 &#xff08;模拟实现查询天气&#xff09; 接口&#xff1a; package com.learning.weather;/*** * weather 接口 &#xff1a;实现模拟wsdl*/ public interface WeatherInterface {/*** 查询天气* param name* return*/public String queryWeather(Strin…

有关莫比乌斯反演

对于两个定义域为整数的函数F(x)和f(x); 若有: 然后F(x)可以快速求出&#xff1b; 如何用F求解f呢&#xff1f; 莫比乌斯反演&#xff1a; 对于两个定义域为整数的函数F(x)和f(x); 若有: 则有&#xff1a; 其中μ(x)为莫比乌斯函数&#xff0c;其定义为&#xff1a; 对于&#…

(原创)JS点击事件——Uncaught TypeError: Cannot set property 'onclick' of null

html部分代码&#xff1a; JS部分代码&#xff1a; 需要实现的效果&#xff1a;点击图片&#xff0c;来回相互切换。 我开始的错误做法&#xff1a;代码如上图所示&#xff08;逻辑上看起来是没有错误的&#xff09; 尝试过程&#xff1a;把JS代码放在</body>闭合标签之前…

事务传播机制/数据库异常解析——2016-8-13分享总结

一. 事务的传播机制&#xff0f;required 跟 required new 的使用与区别 基础回顾 1.1 事务的隔离级别&#xff1a; ISOLATION_READ_UNCOMMITTED&#xff08;读未提交&#xff09; ISOLATION_READ_COMMITTED&#xff08;读已提交&#xff09; ISOLATION_REPEATABLE_READ&#x…

20155307 2016-2017 《Java程序设计》第三次实验报告

&#xff08;一&#xff09;敏捷开发与XP 敏捷开发是一种以人为核心、迭代、循序渐进的开发方法。“敏捷流程”是一系列价值观和方法论的集合。从2001年开始&#xff0c;一些软件界的专家开始倡导“敏捷”的价值观和流程&#xff0c;他们肯定了流行做法的价值&#xff0c;但是强…

ElasticSearch创建、修改、获取、删除、索引Indice mapping和Index Template案例

为什么80%的码农都做不了架构师&#xff1f;>>> The best elasticsearch highlevel java rest api-----bboss ElasticSearch客户端框架bboss的ClientInterface 接口提供了创建/修改、获取、删除索引Indice和IndexTemplate的方法&#xff0c;本文举例说明其使用方法…

spring mvc注解@RequestMapping

1、url路径映射 基本功能 2、窄化请求映射 根路径子路径 注意setViewName的路径。 3、限制http请求方法 get和 post 如果是get 转载于:https://www.cnblogs.com/jway1101/p/5773923.html

老婆的驾照要下来了,形容下我此刻的心情

&#xfeff;&#xfeff; 老婆的驾照要下来了&#xff0c;形容下我此刻的心情&#xff1a; 路上遇到的女人&#xff0c;大部分是不用眼睛和脑子开车的&#xff0c;完全是凭自己的感觉开车。凡是看到前车奇慢、路口犹豫不决、不打灯缓慢变线、不该…

windows环境下OpenLDAP安装与客户端连接配置

2019独角兽企业重金招聘Python工程师标准>>> 1.下载安装OpenLDAP版本 C:\Users\Administrator>slapd -V OpenLDAP 2.4.42 Standalone LDAP Server (slapd) 2.安装过程中&#xff0c;全部用默认的操作执行即可。 3.修改OpenLDAP文件如下&#xff1a; # MDB Backen…

halcon标定后改变世界坐标系参考点方法

halcon相机标定完成后&#xff0c;世界坐标系原点在标定板的中间&#xff0c;如果要自定义坐标系原点该如何操作 如图&#xff1a; 方法1 使用仿射变换 *pose_to_hom_mat3d (FinalPose, HomMat3D) *hom_mat3d_translate_local (HomMat3D, dx, dy, 0, HomMat3DTranslate) *hom_…

KUKA---US2电源的安全属性-------老款硬线连接实现的DRIVE安全STO SBC 、新款基于Safety over EtherCAT 网络帧实现的DRIVE安全STO SBC

安全双回路的监控&#xff1a;&#xff08;工业上的安全&#xff0c;是指安全等级&#xff0c;没有绝对的安全&#xff09; 1. 机械式&#xff1a;监控关断继电器的辅助反馈触点&#xff0c;这个关断继电器包含机械联锁触点&#xff0c;这样反馈触点和主触点可以同步开关动…

X11硬线接口信号 与Profisafe安全输入输出信号之间的区别与比较

&#xfeff;&#xfeff;X11硬线接口信号 与Profisafe安全输入输出信号之间的区别与比较 Profisafe安全输入信号US2信号有待深入&#xff08;通过外部PLC &#xff1a;&#xff09; &#xfeff;&#xfeff;