Halcom 发表于 2017-2-7 22:48:49

确定物体照射光的方向偏角--SVD奇异值分解

初始化一个圆,采用形变模型,进行在已知图形上找圆,计算缩放因子,进而拟合一个圆:具体代码如下:
* 倾斜角和偏角 (tilt and slant values) of a photometric stereo setup by
* using images of a sphere with lambertian reflection(朗伯体表面反射模型).
* 确定光线照射的方向
dev_update_off ()
dev_close_window ()
dev_open_window_fit_size (0, 0, 640, 494, 500, 500, WindowHandle1)
Color := 'green'
dev_set_color (Color)
dev_set_draw ('margin')
dev_set_line_width (3)
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
ApproxSphereRadius := 200
* 读取图像-共6张图像
ImageFiles := 'photometric_stereo/shaded_sphere_0' +
read_image (Images, ImageFiles)
* 将这6张图像融合为一个多通道图像
channels_to_image (Images, MultichannelImage)
count_channels (MultichannelImage, NumImages)
dev_display (Images)
* 显示基本信息
disp_message (WindowHandle1, 'Detect the position of the sphere ...', 'window', 12, 12, 'black', 'true')
* 在位置产生一个ApproxSphereRadius=200半径的圆
gen_circle_contour_xld (ContourCircle, 200, 200, ApproxSphereRadius, 0, 6.28318, 'positive', 1)
* 在原始图像上找圆,并拟合
create_scaled_shape_model_xld (ContourCircle, 'auto', 0.0, 0.0, 'auto', 0.9, 1.5, 'auto', 'auto', 'ignore_color_polarity', 1, ModelID)
find_scaled_shape_model (MultichannelImage, ModelID, 0.0, 0.0, .9, 1.1, .95, 1, .5, 'least_squares_high', 0, .9, RowCenter, ColumnCenter, Angle, Scale, MatchScore)
* 获取一个半径,是初始化半径的Scale倍
SphereRadius := ApproxSphereRadius * Scale
gen_cross_contour_xld (CenterCross, RowCenter, ColumnCenter, 15, 0.0)
dev_display (CenterCross)
dev_display_shape_matching_results (ModelID, Color, RowCenter, ColumnCenter, Angle, Scale, Scale, 0)
disp_continue_message (WindowHandle1, 'black', 'true')
clear_shape_model (ModelID)
stop ()

确定入射光倾角:* Compute the tilt and slant angles of the light source:
* 选取的区域应该尽可能的大,确保计算结果的鲁棒性
MinGray := 170
MaxGray := 255
measure_light_source_orientation_from_sphere (MultichannelImage, SphereRadius, RowCenter, ColumnCenter, MinGray, MaxGray, Tilt, Slant)
measure_light_source_orientation_from_sphere对应的函数如下:
* 输出参数:
* Tilts:   The computed tilt values:正视图的倾斜角
* Slants:The computed slant values:横截面视图的倾斜角
get_image_size (ShadeImages, Width, Height)
* 根据半径参数,产生一个模拟等大小的球-Heights
compute_sphere_heights_and_normal_vectors (Heights, NormalVectors, Radius, RowCenter, ColumnCenter, Width, Height)
* 去背景
threshold (Heights, Region, 0.01, 1.2 * Radius)
reduce_domain (Heights, Region, Heights)
reduce_domain (NormalVectors, Region, NormalVectors)
* ShapeImages通道数量
count_channels (ShadeImages, NumChannels)
Tilts := []
Slants := []
for Index := 1 to NumChannels by 1
    * 选取第Index个通道的图像
    access_channel (ShadeImages, ShadeImage, Index)
    reduce_domain (ShadeImage, Region, ShadeImage)
    * Get well illuminated parts
    threshold (ShadeImage, RegionShade, MinGray, MaxGray)
    * 获取区域所在的全部坐标点
    get_region_points (RegionShade, Rows, Columns)
    * 获取原图像ShadeImage在全部坐标点上的灰度值
    get_grayval (ShadeImage, Rows, Columns, GrayvalI)
    if (|GrayvalI| >= 3)
      create_matrix (|GrayvalI|, 1, GrayvalI, MatrixIID)
      * Create matrix N of the surface normal vectors
      decompose3 (NormalVectors, Nx, Ny, Nz)
      get_grayval (Nx, Rows, Columns, GvNx)
      get_grayval (Ny, Rows, Columns, GvNy)
      get_grayval (Nz, Rows, Columns, GvNz)
      GvN :=
      create_matrix (3, |GvNx|, , MatrixNtID)
      transpose_matrix (MatrixNtID, MatrixNID)
      *
      * 奇异值分解
      svd_matrix (MatrixNID, 'reduced', 'both', MatrixUID, MatrixSID, MatrixVID)
      mult_matrix (MatrixUID, MatrixIID, 'ATB', MatrixMultID)
      get_value_matrix (MatrixMultID, , , UI)
      get_value_matrix (MatrixSID, , , S)
      UI_S := []
      for I := 0 to 2 by 1
            UI_S := / S]
      endfor
      create_matrix (3, 1, UI_S, MatrixUI_SID)
      mult_matrix (MatrixVID, MatrixUI_SID, 'AB', MatrixLID)
      get_value_matrix (MatrixLID, , , L)
      * Clean up memory
      clear_matrix (MatrixNtID)
      clear_matrix (MatrixNID)
      clear_matrix (MatrixUID)
      clear_matrix (MatrixSID)
      clear_matrix (MatrixVID)
      clear_matrix (MatrixIID)
      clear_matrix (MatrixMultID)
      clear_matrix (MatrixUI_SID)
      clear_matrix (MatrixLID)
      *
      * Calculate tilt and slant from orientation vector
      NormL := sqrt(L * L + L * L + L * L)
      L := L / NormL
      tuple_atan2 (L, L, Tilt)
      Slant := abs(asin(L))
      Tilts :=
      Slants :=
    else
      Tilts :=
      Slants :=
    endif
endforcompute_sphere_heights_and_normal_vectors函数如下:
gen_image_surface_second_order (Parabola, 'real', -1, -1, 0, 0, 0, Radius * Radius, RowCenter, ColumnCenter, ImageWidth, ImageHeight)
sqrt_image (Parabola, SphereHeight)
* Compute the normal vectors
gen_image_surface_first_order (dX, 'real', 0, 1, 0, 0, ColumnCenter, ImageWidth, ImageHeight)
gen_image_surface_first_order (dY, 'real', -1, 0, 0, RowCenter, 0, ImageWidth, ImageHeight)
threshold (SphereHeight, Region, .01, 1.2 * Radius)
reduce_domain (dX, Region, dXReduced)
reduce_domain (dY, Region, dYReduced)
gen_image_const (Const, 'real', ImageWidth, ImageHeight)
copy_image (Const, dX)
copy_image (Const, dY)
overpaint_gray (dX, dXReduced)
overpaint_gray (dY, dYReduced)
add_image (Const, dX, dX, 1 / real(Radius), 0)
add_image (Const, dY, dY, 1 / real(Radius), 0)
add_image (Const, SphereHeight, dZ, 1 / real(Radius), 0)
copy_image (dX, SphereNormalVector)
append_channel (SphereNormalVector, dY, SphereNormalVector)
append_channel (SphereNormalVector, dZ, SphereNormalVector)在该函数的前两句代码,产生一个球体,代码很巧妙,具体如图所示,Parabola            SphereHeightdx                   dy                     dz
采用仿射变换,显示标记结果:* Display the results
get_window_extents (WindowHandle1, Row, Column, Width, Height)
dev_open_window (0, Width + 12, Width, Height, 'white', WindowHandle2)
dev_set_part (0, 0, 493, 639)
set_display_font (WindowHandle2, 14, 'mono', 'true', 'false')
PointO :=
PointE := PointO +
gen_contour_polygon_xld (LineContour, ,PointE], ,PointE])
gen_arrow_contour_xld (ArrowContour, PointE, PointE, PointO, PointO + 50, 20, 20)
hom_mat2d_identity (HomMat2DIdentity)
gen_circle_contour_xld (ContSphere, RowCenter, ColumnCenter, SphereRadius, 0, 6.28318, 'positive', 1)
gen_contour_polygon_xld (LineContourBottom, , )
for Index := 1 to NumImages by 1
    * 选择图像
    access_channel (MultichannelImage, Image, Index)
    * 标记的箭头,仿射变换--正视图top view下的入射光的倾斜角
    hom_mat2d_rotate (HomMat2DIdentity, rad(Tilt), RowCenter, ColumnCenter, HomMat2DRotateTilt)
    affine_trans_contour_xld (ArrowContour, ArrowTilt, HomMat2DRotateTilt)
    affine_trans_point_2d (HomMat2DRotateTilt, PointE, PointE, QxTilt, QyTilt)
    if (Tilt >= 0)
      PointOrder := 'positive'
    else
      PointOrder := 'negative'
    endif
    gen_circle_contour_xld (ContCircleTilt, RowCenter, ColumnCenter, 100, 0, rad(Tilt), PointOrder, 1)
    * 横截面视图下的入射光的倾斜角
    hom_mat2d_rotate (HomMat2DIdentity, rad(Slant), RowCenter, ColumnCenter, HomMat2DRotateSlant)
    affine_trans_contour_xld (ArrowContour, ArrowSlant, HomMat2DRotateSlant)
    affine_trans_point_2d (HomMat2DRotateSlant, PointE, PointE, QxSlant, QySlant)
    gen_circle_contour_xld (ContCircleSlant, RowCenter, ColumnCenter, 100, 0, rad(Slant), 'positive', 1)
    *
    dev_set_window (WindowHandle1)
    dev_display (Image)
    dev_display (LineContour)
    dev_display (ContCircleTilt)
    dev_display (ArrowTilt)
    disp_message (WindowHandle1, 'Top view (' + Index + '/' + NumImages + ')', 'window', 12, 12, 'black', 'true')
    disp_message (WindowHandle1, '0°', 'image', PointE, PointE, 'black', 'true')
    disp_message (WindowHandle1, 'Tilt = ' + Tilt +4.1f' + '°', 'image', QxTilt, QyTilt - 80, 'black', 'true')
    dev_set_window (WindowHandle2)
    dev_clear_window ()
    dev_set_color ('black')
    dev_display (LineContourBottom)
    dev_display (ContSphere)
    dev_set_color (Color)
    dev_display (LineContour)
    dev_display (ArrowSlant)
    dev_display (ContCircleSlant)
    disp_message (WindowHandle2, 'Cross section (' + Index + '/' + NumImages + ')', 'window', 12, 12, 'black', 'true')
    disp_message (WindowHandle2, '0°', 'image', PointE, PointE, 'black', 'true')
    disp_message (WindowHandle2, 'Slant = ' + Slant+4.1f' + '°', 'image', QxSlant, QySlant - 80, 'black', 'true')
    dev_set_window (WindowHandle1)
    if (Index < NumImages)
      disp_continue_message (WindowHandle2, 'black', 'true')
      stop ()
    endif
endfor
* 输出参数:* Tilts:   The computed tilt values:正视图top view的倾斜角* Slants:The computed slant values:横截面视图的倾斜角关于Tilt和Slants的解释见文档:灰度一致性纹理图像的光参数估计

buling 发表于 2017-11-27 15:18:18

楼主的思维太刁,够我这种小白学习好长时间
页: [1]
查看完整版本: 确定物体照射光的方向偏角--SVD奇异值分解