QQ登录

只需一步,快速开始

halcon adjust_mosaic_images函数介绍

[ 复制链接 ]
一 adjust_mosaic_images(Images : CorrectedImages : From, To, ReferenceImage, HomMatrices2D, EstimationMethod, EstimateParameters, OECFModel : )

adjust_mosaic_images执行全景图像的辐射调整。
被纠正的图像为参数Images ,被纠正的图像保存于CorrectedImages


From和To的参数必须包含全景图中所有图像对的源和目标索引。
每个图像对的射影矩阵3x3必须在同质矩阵2d中传递。
使用参数ReferenceImage选择将用作亮度和白平衡参考的图像。


这意味着,一个图像指定了“ideal”亮度和白平衡设置。
所有其他图像将被纠正,使其亮度和白平衡匹配的参考图像。
换句话说,参考图像不会改变,但是所有其他图像都会改变。


使用EstimationMethod选择应该使用快速但不太准确的确定方法,
还是使用较慢但更准确的确定方法。
可以通过将EstimationMethod设置为'standard'或'gold_standard'来实现的。


基于“standard”的方法只使用图像对之间重叠区域内所有图像的平均灰度值差。
在“gold_standard”中,会显式地考虑重叠区域中每个像素的灰度值差异。

在所有情况下,误差最小的函数被计算为相应灰度值之差的平方和。



个别方法的可用性取决于所选的 EstimateParameters,
这些参数决定了用于估计辐射调整项的模型。
总是可以通过选择“vignetting”来确定图像中的渐晕量。
但是,如果选择EstimationMethod,则必须将其设置为'gold_standard'。
对于其余的辐射测量调整,有三种不同的选择:


图像晕动的估计是建立在已知的基础上的
2019-05-28_112343.jpg
该方法假定渐晕不存在于图像的中心,
且由上式可知,渐晕随开角的增大而增大。


1. 图像调整与加性模型。
这应该只用于调整图像与非常小的差异曝光或白平衡。
要选择此方法,必须将EstimateParameters设置为'add_gray'。
这个模型可以单独选择,也只能通过EstimationMethod = 'standard'
或者结合EstimateParameters = 'vignetting'
和EstimationMethod = 'gold_standard'来选择。


该模型基于这样的假设,
即通过向每幅接受参考图像的图像中添加一个单独的值来纠正图像之间的灰度值差异。
基本上,对每个图像的修改都可以表示为调用scale_image:
scale_image(Image_n,CorrectedImage_n,1.0,Add_n)
Add_n为图像 修正项。


2. 用线性模型调整图像。
在这个模型中,图像被期望用一个使用线性传递函数的相机拍摄。
因此,平差项表示为乘因子。要选择这个模型,必须将EstimateParameters设置为“mult_gray”。
它可以被EstimationMethod = 'standard'或EstimationMethod = 'gold_standard'调用。
也可以使用EstimateParameters = 'vignetting'组合调用,
在这种情况下必须将EstimationMethod设置为'gold_standard'。


该模型基于图像之间灰度值的差异可以通过将每幅图像中的灰度值乘以一个因子来修正的假设。
基本上,对每个图像的修改都可以再次表示为调用scale_image:
scale_image(Image_n,CorrectedImage_n,Mult_n,0)
Mult_n为图像 修正项。


3.图像调整与校准模型。
在该模型中,假设图像是用一个非线性传递函数相机拍摄的。
利用OECFModel选择的OECF类函数来逼近图像采集过程中实际使用的OECF。
与线性模型一样,修正项用乘法因子表示。
这个模型可以通过选择EstimateParameters = ['mult_gray','response']来选择,
并且必须使用EstimationMethod = 'gold_standard'来调用。
在这种情况下,可以通过选择来确定晕渲的数量


这个模型与线性模型相似。
然而,在这种情况下,相机可能会有非线性响应。
这意味着在将图像的灰度值乘以各自的校正因子之前,
必须将灰度值反向投影到线性响应中。
为此,必须确定相机的响应。
由于响应通常不会在一个图像序列上发生变化,
因此假定该参数在整个图像序列中都是常量。




任何一种功能都可以看作是一种嗅鞘细胞。
与操作符radiometric_self_calibration一样,
可能会使用多项式拟合,但对于马赛克应用程序中的典型图像,
这种方法效果不是很好。
原因是多项式拟合需要确定的参数太多。
相反,只能估计更简单的响应函数类型。
目前,只有所谓的拉盖尔函数可用。


拉盖尔型OECF的响应仅由一个称为Phi的参数决定。
在第一步中,将整个灰度值谱(对于0到255为8位的图像)转换为区间内的浮点数[0:1]。
然后在此基础上计算OECF反投影,得到的灰度值再次转换为原始区间。



基于Laguerre-type OECF将灰度值反变换为线性值,表达式为:
2019-05-28_112343.jpg
I_l, I_nl为线性与非线性灰度值。

只有在选择了校准模型后才使用参数OECFModel。
否则,OECFModel的任何输入都将被忽略。

参数 EstimateParameters也可以用来影响运算符的性能和内存消耗。
使用“no_cache”可以禁用内部缓存机制。
只有当EstimationMethod被设置为'gold_standard'时,这个开关才有影响。
否则此开关将被忽略。
当禁用内部缓存时,操作符使用的内存要少得多,
但因此会在最小化算法的每次迭代中再次计算相应的灰度值对。
因此,只有当所有物理内存在计算的某个点上被耗尽时,才建议禁用缓存。


影响性能的第二个选项是使用子抽样。
当将EstimateParameters设置为“subsampling_2”时,
图像会在内部缩小2倍。
尽管有建议的值列表,但不仅可以使用因子2和4,
而且可以通过将其附加到EstimateParameters中的subsampling来指定任何整数。
这样,图像数据量就大大减少了,这使得内部最小化的计算速度大大加快。
事实上,使用适度的子抽样甚至可能有更好的结果,因为它也减少了轻微mis的影响
虽然如果EstimationMethod设置为“standard”,子抽样也会影响最小化,但它对“gold_standard”最有用。


关于在应用程序中使用adjust_mosaic_images的一些更常见的说明:
只有在图像中可见明显的晕渲时,
晕渲的估计才能很好地工作。
否则,操作者可能会导致不稳定的结果。

由于问题相当复杂,所以对响应的估计相当慢。

因此,建议不要在关键时间应用程序中确定响应。
除此之外,只有当图像之间存在较大的亮度差异时,才能正确确定响应。


校正饱和度是不可能的。
如果图像中有饱和区域,它们将保持饱和。

adjust_mosaic_imagess只能用于校正由于曝光时间(快门时间、光圈)

不同或光照强度不同造成的图像亮度不同。
它不能用于纠正基于每个图像内不均匀照明的亮度差异。


参数
Images,CorrectedImages输入和输出的图像。
From,To源图像和目标图像索引
ReferenceImage,HomMatrices2D参考图像和投影矩阵
EstimationMethod,EstimateParameters校正的估计算法及参数。
EstimationMethod值有 'gold_standard', 'standard'
EstimateParameters值有add_gray', 'mult_gray', 'response', 'vignetting', 'subsampling_2', 'subsampling_4', 'no_cache'
OECFModel使用的OECF模型。值有 'laguerre'


二.gen_spherical_mosaic(Images : MosaicImage : CameraMatrices,
RotationMatrices, LatMin, LatMax, LongMin, LongMax, LatLongStep, StackingOrder, Interpolation : )
gen_spherical_mosaic从输入图像Images 创建一个MosaicImage
空间图像的位姿是用来计算图像相对于球体表面的位置的,
可以用stationary - camera_self - calibration来确定。
结果参数 CameraMatrices和RotationMatrices可以传递使用。
球面马赛克只能由使用固定摄像机拍摄的图像创建(请参见stationary_camera_self_calibration)。


马赛克以球坐标(经度和纬度)计算。
MosaicImage的行轴对应纬度,列轴对应经度。
gen_spherical_mosaic计算的球体部分由LatMin、LatMax、LongMin和LongMax确定。
这些参数以度数指定,并确定经纬度坐标的矩形部分
纬度-90对应北极(即北极)。,则垂直向上的观测方向),
而90则对应南极(即,垂直向下的观看方向)。
经度0对应于正前方的观察方向。
负经度对应左侧的观测方向,正经度对应右侧的观测方向。
因此,为了获得球体的完整图像,
必须使用LatMin = -90、LatMax = 90、LongMin = -180和LongMax = 180。


在许多情况下,马赛克不会覆盖整个球体。
在这些情况下,使用上述参数选择球体的所需部分是有用的。
这可以通过显式地指定所需的矩形来实现。
然而,通常需要确定自动包含所有图像的最小矩形。
这可以通过使用LatMin < -90、LatMax > 90、LongMin < -180和LongMax > 180来实现。
只有位于正常值范围之外的参数才会自动确定。


MosaicImage中每个像素的角度步长可以用LatLongStep来选择,
LatLongStep也是以角度为单位指定的角度。
这样就可以控制镶嵌图像的分辨率。
如果将LatLongStep设置为0,则通过尽量保持原始图像的像素大小,自动计算角度步长。


将图像添加到马赛克中的模式由StackingOrder给出。
对于StackingOrder = 'voronoi',马赛克图像中的点由各自输入图像的voronoi单元确定。
这意味着灰度值是从输入图像的点取的,其中心与马赛克图像中的像素在球面上的距离最小。
这种模式的优点是,晕渲和未校正的径向畸变在马赛克图像中不太明显,
因为它们通常是相对于图像中心对称的。
或者,通过如下所述参数的选择,可以选择一种模式,
其效果与连续将图像绘制到马赛克图像中一样。
在这里,将图像添加到马赛克图像中的顺序非常重要。
因此,可以按堆栈顺序传递整数值数组。
这个数组中的第一个索引将位于图像堆栈的底部,
而最后一个索引将位于顶部。
如果给定的是“default”而不是整数数组,
则使用规范顺序(图像中使用的顺序是Images内对应的顺序)。
因此,如果既不使用“voronoi”也不使用“default”,
那么StackingOrder必须包含数字1、…,n,
其中n是图像 Images中传递的图像数量。
应该注意的是,模式“voronoi”不能总是使用。
例如,必须传递至少两个图像才能使用此模式。


此外,对于球面上图像中心位置的非常特殊的配置,
不能唯一地确定Voronoi单元。
使用StackingOrder = 'blend',可以使用另一种模式,它可以平滑地混合马赛克的图像。
这样,图像之间的接缝就不那么明显了。
图像之间的缝线与“voronoi”中相同。
这种模式使图像在视觉上更吸引人,但需要更多的资源。
如果模式“voronoi”或“blend”由于任何原因不能使用,则模式将在内部自动切换为“default”。


参数插值选择所需的插值模式来创建马赛克。“
双线性”和“双三次”插值适用于所有叠加顺序模式。
“nearest_neighbor”仅在StackingOrder设置为“default”或“voronoi”时可用。


参数:
Images,MosaicImage 输入输出图像。
CameraMatrices 3x3投影相机矩阵,确定相机内部参数。
RotationMatrices 由3x3变换矩阵组成的数组,用于确定相机在各自图像中的旋转。
LatMin,LatMax,球面镶嵌图像中点的最小,最大纬度。
LongMin,LongMax 球面镶嵌图像中点的最小,最大经度。
LatLongStep经纬度角步宽。
StackingOrder 将图像添加到马赛克图像的模式。值有blend', 'voronoi', 'default'
Interpolation 创建马赛克图像时 用的插值模式。值有'nearest_neighbor', 'bilinear', 'bicubic'


例程:
*例程用教学内部128张图像,合成一张360x130视角的图像。
*相机拍照时曝光和折平移设为自动,所以图片间高度颜色相关很大。
*可以调用adjust_mosaic_images对图像进行校正。
dev_close_window ()
dev_open_window (0, 0, 978, 324, 'black', WindowHandle)
dev_set_part (0, 0, 647, 1955)
gen_empty_obj (Images)
for J := 1 to 128 by 1
    read_image (Image, 'panorama/sankt_martin_automatic_' + J$'03d')
    concat_obj (Images, Image, Images)
endfor
get_image_size (Image, Width, Height)
stop()
*构造元组来确定应该匹配哪些图像,拼接图像为16条垂直条带,每条条带8幅图像
*对于每个图像,我们将当前图像后面的图像匹配到相同的条带,左边的匹配到相邻条带中。
FF := [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8]
TT := [2,9,3,10,4,11,5,12,6,13,7,14,8,15,16]
From := []
To := []
for J := 0 to 15 by 1
    From := [From,(FF - 1 + 8 * J) % 128 + 1]
    To := [To,(TT - 1 + 8 * J) % 128 + 1]
endfor
HomMatrices2D := []
Rows1 := []
Cols1 := []
Rows2 := []
Cols2 := []
NumMatches := []
stop()
for J := 0 to |From| - 1 by 1
    *选择两张图像来区域
    select_obj (Images, ImageF, From[J])
    select_obj (Images, ImageT, To[J])
    * 提取图像点
    points_foerstner (ImageF, 1, 2, 3, 50, 0.1, 'gauss', 'true', RowsF, ColsF, CoRRJunctions, CoRCJunctions, CoCCJunctions, RowArea, ColumnArea, CoRRArea, CoRCArea, CoCCArea)
    points_foerstner (ImageT, 1, 2, 3, 50, 0.1, 'gauss', 'true', RowsT, ColsT, CoRRJunctions1, CoRCJunctions1, CoCCJunctions1, RowArea1, ColumnArea1, CoRRArea1, CoRCArea1, CoCCArea1)
    concat_obj (ImageT, ImageF, ImageTF)
    tile_images_offset (ImageTF, TiledImage, [0,0], [0,Width + 20], [-1,-1], [-1,-1], [-1,-1], [-1,-1], 2 * Width + 20, Height)
    gen_cross_contour_xld (PointsF, RowsF, ColsF + Width + 20, 6, rad(45))
    gen_cross_contour_xld (PointsT, RowsT, ColsT, 6, rad(0))
    * 图像转为灰度图
    rgb1_to_gray (ImageF, ImageFG)
    rgb1_to_gray (ImageT, ImageTG)
    *确定图像间投影转换,累积结果数据
    proj_match_points_ransac (ImageFG, ImageTG, RowsF, ColsF, RowsT, ColsT, 'ncc', 10, 0, 0, 648, 968, [rad(-10),rad(40)], 0.5, 'gold_standard', 10, 42, HomMat2D, Points1, Points2)
    HomMatrices2D := [HomMatrices2D,HomMat2D]
    Rows1 := [Rows1,subset(RowsF,Points1)]
    Cols1 := [Cols1,subset(ColsF,Points1)]
    Rows2 := [Rows2,subset(RowsT,Points2)]
    Cols2 := [Cols2,subset(ColsT,Points2)]
    NumMatches := [NumMatches,|Points1|]
    * 显示匹配点
    RF := subset(RowsF,Points1)
    CF := subset(ColsF,Points1) + Width + 20
    RT := subset(RowsT,Points2)
    CT := subset(ColsT,Points2)
    gen_empty_obj (Matches)
    for K := 0 to |RF| - 1 by 1
        gen_contour_polygon_xld (Match, [RF[K],RT[K]], [CF[K],CT[K]])
        concat_obj (Matches, Match, Matches)
    endfor
    dev_clear_window ()
    dev_display (TiledImage)
    dev_set_color ('blue')
    dev_display (Matches)
    dev_set_color ('green')
    dev_display (PointsF)
    dev_display (PointsT)
    dev_set_color ('yellow')
    set_tposition (WindowHandle, 20, 20)
    write_string (WindowHandle, 'Matches between images ' + From[J]$'d' + ' and ' + To[J]$'d')
endfor
dev_clear_window ()
dev_set_window_extents (-1, -1, 856, 428)
dev_set_color ('yellow')
set_tposition (WindowHandle, 20, 20)
write_string (WindowHandle, 'Performing self-calibration...')
*执行自标定
stationary_camera_self_calibration (128, 968, 648, 6, From, To, HomMatrices2D, Rows1, Cols1, Rows2, Cols2, NumMatches, 'gold_standard', ['focus','principal_point','kappa'], 'true', CameraMatrix, Kappa, RotationMatrices, X, Y, Z, Error)
stop()
dev_clear_window ()
dev_set_color ('yellow')
set_tposition (WindowHandle, 20, 20)
write_string (WindowHandle, 'Removing radial distortions...')
*从图像中去除径向畸变
cam_mat_to_cam_par (CameraMatrix, Kappa, 968, 648, CamParam)
change_radial_distortion_cam_par ('fixed', CamParam, 0, CamParOut)
gen_radial_distortion_map (Map, CamParam, CamParOut, 'bilinear')
map_image (Images, Map, Images)
dev_clear_window ()
dev_set_color ('yellow')
set_tposition (WindowHandle, 20, 20)
write_string (WindowHandle, 'Adjusting the images radiometrically...')
*在对图像进行校正之前,我们要计算图像间的透视变换,相机内外参通过自标定获得。
*这会比匹配返回的透视图转换更精确,因为它们对所有图像都进行了优化。
*计算过程可以参考stationary_camera_self_calibration。
hom_mat2d_invert (CameraMatrix, CameraMatrixInv)
PermMat := [0.0,1.0,0.5,1.0,0.0,0.5,0.0,0.0,1.0]
hom_mat2d_invert (PermMat, PermMatInv)
hom_mat2d_compose (CameraMatrixInv, PermMatInv, CamMatPermInv)
hom_mat2d_compose (PermMat, CameraMatrix, CamMatPerm)
HomMats2D := []
for J := 0 to |From| - 1 by 1
    RotMatFrom := RotationMatrices[9 * (From[J] - 1):9 * (From[J] - 1) + 8]
    RotMatTo := RotationMatrices[9 * (To[J] - 1):9 * (To[J] - 1) + 8]
    hom_mat2d_transpose (RotMatFrom, RotMatFromInv)
    hom_mat2d_compose (RotMatTo, RotMatFromInv, RotMat)
    hom_mat2d_compose (RotMat, CamMatPermInv, RotCamMatInv)
    hom_mat2d_compose (CamMatPerm, RotCamMatInv, HomMat2D)
    HomMats2D := [HomMats2D,HomMat2D]
endfor
*现在调整图像辐射度量。
*因为相机曝光白平移设为了自动,我们计算'mult_gray'。
*因为相机为民用相机会有很高有非线性变化,我们计算'response'。
*为补偿图像中的晕动,我们计算'vignetting'。
*最后为加速等优化,我们使用4倍的子抽样。
adjust_mosaic_images (Images, CorrectedImages, From, To, 118, HomMats2D, 'gold_standard', ['mult_gray','response','vignetting','subsampling_4'], 'laguerre')
hom_mat3d_identity (HomMat3D)
hom_mat3d_rotate (HomMat3D, rad(-5.5), 'x', 0, 0, 0, HomMat3D)
RotMat := [HomMat3D[0:2],HomMat3D[4:6],HomMat3D[8:10]]
RotMats := []
for J := 0 to 127 by 1
    RotMatCalib := RotationMatrices[J * 9:J * 9 + 8]
    hom_mat2d_compose (RotMatCalib, RotMat, RotMatRot)
    RotMats := [RotMats,RotMatRot]
endfor
dev_clear_window ()
dev_set_color ('yellow')
set_tposition (WindowHandle, 20, 20)
write_string (WindowHandle, 'Creating spherical mosaic of the original images...')
*创建原始图像的球形马赛克。
gen_spherical_mosaic (Images, SphericalMosaicOrig, CameraMatrix, RotMats, -90, 90, -180, 180, 0, 'voronoi', 'bilinear')
get_image_size (SphericalMosaicOrig, Width, Height)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_clear_window ()
dev_display (SphericalMosaicOrig)
dev_set_color ('yellow')
set_tposition (WindowHandle, Height - 300, 20)
write_string (WindowHandle, 'Spherical mosaic of the original images')
set_tposition (WindowHandle, Height - 150, 20)
write_string (WindowHandle, 'Press \'Run\' to continue')
stop ()
dev_clear_window ()
dev_set_color ('yellow')
set_tposition (WindowHandle, 20, 20)
write_string (WindowHandle, 'Creating spherical mosaic of the radiometrically adjusted images...')
* 创建辐射测量调整图像的球面马赛克。
gen_spherical_mosaic (CorrectedImages, SphericalMosaicAdjust, CameraMatrix, RotMats, -90, 90, -180, 180, 0, 'voronoi', 'bilinear')
get_image_size (SphericalMosaicAdjust, Width, Height)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_clear_window ()
dev_display (SphericalMosaicAdjust)
dev_set_color ('yellow')
set_tposition (WindowHandle, Height - 300, 20)
write_string (WindowHandle, 'Spherical mosaic of the radiometrically adjusted images')
set_tposition (WindowHandle, Height - 150, 20)
write_string (WindowHandle, 'Press \'Run\' to continue')
stop ()
dev_clear_window ()
dev_set_color ('yellow')
set_tposition (WindowHandle, 20, 20)
write_string (WindowHandle, 'Creating blended spherical mosaic of the radiometrically adjusted images...')
* 创建辐射测量调整图像的混合球面马赛克。
gen_spherical_mosaic (CorrectedImages, SphericalMosaicAdjustBlend, CameraMatrix, RotMats, -90, 90, -180, 180, 0, 'blend', 'bilinear')
get_image_size (SphericalMosaicAdjustBlend, Width, Height)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_clear_window ()
dev_display (SphericalMosaicAdjustBlend)
dev_set_color ('yellow')
set_tposition (WindowHandle, Height - 300, 20)
write_string (WindowHandle, 'Blended spherical mosaic of the radiometrically adjusted images')
  

halcon从自学到接项目视频教程,另外再赠送全网最全资源  

  

欢迎围观我录制的一套halcon自学视频教程(进入)



回复

使用道具 举报

快速回复 返回列表 客服中心 搜索