- This example program shows how to rectify a part of an image using
- vector_to_proj_hom_mat2d. This is done by extracting the four
- corners of a soccer field from an oblique view of a stadium. The four
- corners define a quadrilateral, which is then mapped to a rectangle
- that has the correct aspect ratio. If the dimensions of the field were
- known metrically, the program could be extended to perform metric
- measurements on the soccer field and stadium track.
dev_update_off ()
read_image (Image, ‘olympic_stadium’)
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, ‘black’, WindowHandle)
set_display_font (WindowHandle, 16, ‘mono’, ‘true’, ‘false’)
dev_display (Image)
disp_message (WindowHandle, ‘Oblique view of stadium track and field’, ‘image’, -1, -1, ‘black’, ‘true’)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop () - Segment the field based on its green color and its shape. This is done
- most easily by using the Hue channel of the HSV transform of the image.
decompose3 (Image, ImageR, ImageG, ImageB)
trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, ‘hsv’)
threshold (ImageH, GreenRegion, 60, 90)
connection (GreenRegion, ConnectedRegions) - Select the field region based on the fact that it is the largest component
- that roughly looks like a rotated rectangle.
select_shape_std (ConnectedRegions, RectangleRegions, ‘rectangle2’, 80)
select_shape_std (RectangleRegions, Field, ‘max_area’, 90) - Construct a ROI for the color edge extraction from the boundary of the
- segmented field.
shape_trans (Field, FieldConvex, ‘convex’)
boundary (FieldConvex, FieldBorder, ‘inner’)
dilation_rectangle1 (FieldBorder, FieldDilation, 7, 7)
dev_display (Image)
dev_set_draw (‘margin’)
dev_display (FieldDilation)
dev_set_draw (‘fill’)
disp_message (WindowHandle, ‘Field ROI based on color segmentation’, ‘image’, -1, -1, ‘black’, ‘true’)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop () - Perform the color edge extraction.
reduce_domain (Image, FieldDilation, ImageReduced)
edges_color_sub_pix (ImageReduced, Edges, ‘canny’, 1.5, 20, 40)
dev_display (Image)
dev_display (Edges)
disp_message (WindowHandle, ‘Extracted color edges’, ‘image’, -1, -1, ‘black’, ‘true’)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop () - Now select straight edges from the extracted edges and group them into
- the four sides of the quadrilateral.
select_shape_xld (Edges, SelectedEdges, ‘contlength’, ‘and’, 15, 500) - We first need to segment the edges into straight lines because the
- extracted edges may represent more than one side of the quadrilateral.
segment_contours_xld (SelectedEdges, ContoursSplit, ‘lines’, 5, 4, 2)
regress_contours_xld (ContoursSplit, RegressContours, ‘no’, 1) - Weed out edges that are not straight enough.
select_contours_xld (RegressContours, SelectedContours, ‘curvature’, 0, 0.5, 0, 0) - Select edges that are long enough to provide meaningful direction information.
select_shape_xld (SelectedContours, SelectedEdges, ‘contlength’, ‘and’, 15, 500) - Group the straight lines into the quadrilateral’s sides.
union_collinear_contours_xld (SelectedEdges, UnionContours, 30, 1, 4, 0.1, ‘attr_forget’)
dev_display (Image)
dev_display (UnionContours)
disp_message (WindowHandle, ‘Selected straight edges’, ‘image’, -1, -1, ‘black’, ‘true’)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop () - Now we need to determine the order of the sides because we want to
- intersect the sides to get the corners of the quadrilateral. First, we
- separate the sides into roughly horizontal and roughly vertical sides.
select_shape_xld (UnionContours, HorizontalEdges, ‘phi’, ‘and’, rad(-20), rad(20))
select_shape_xld (UnionContours, VerticalEdges, [‘phi’,‘phi’], ‘or’, [rad(-90),rad(60)], [rad(-60),rad(90)]) - Now we need to order the sides. The horizontal sides are sorted based on
- their row coordinates, while the vertical sides are sorted based on their
- column coordinates.
fit_line_contour_xld (HorizontalEdges, ‘tukey’, -1, 0, 10, 2, RowBegHor, ColBegHor, RowEndHor, ColEndHor, NrHor, NcHor, DistHor)
IndexHor := sort_index(RowBegHor)
fit_line_contour_xld (VerticalEdges, ‘tukey’, -1, 0, 10, 2, RowBegVer, ColBegVer, RowEndVer, ColEndVer, NrVer, NcVer, DistVer)
IndexVer := sort_index(ColBegVer) - After we have sorted the sides, we can intersect the appropriate sides
- to get the four corners of the quadrilateral.
intersection_lines (RowBegHor[IndexHor[0]], ColBegHor[IndexHor[0]], RowEndHor[IndexHor[0]], ColEndHor[IndexHor[0]], RowBegVer[IndexVer[0]], ColBegVer[IndexVer[0]], RowEndVer[IndexVer[0]], ColEndVer[IndexVer[0]], RowUL, ColUL, IsOverlapping)
intersection_lines (RowBegHor[IndexHor[0]], ColBegHor[IndexHor[0]], RowEndHor[IndexHor[0]], ColEndHor[IndexHor[0]], RowBegVer[IndexVer[1]], ColBegVer[IndexVer[1]], RowEndVer[IndexVer[1]], ColEndVer[IndexVer[1]], RowUR, ColUR, IsOverlapping)
intersection_lines (RowBegHor[IndexHor[1]], ColBegHor[IndexHor[1]], RowEndHor[IndexHor[1]], ColEndHor[IndexHor[1]], RowBegVer[IndexVer[0]], ColBegVer[IndexVer[0]], RowEndVer[IndexVer[0]], ColEndVer[IndexVer[0]], RowLL, ColLL, IsOverlapping)
intersection_lines (RowBegHor[IndexHor[1]], ColBegHor[IndexHor[1]], RowEndHor[IndexHor[1]], ColEndHor[IndexHor[1]], RowBegVer[IndexVer[1]], ColBegVer[IndexVer[1]], RowEndVer[IndexVer[1]], ColEndVer[IndexVer[1]], RowLR, ColLR, IsOverlapping) - For visualization, we generate a contour that represents the fitted
- quadrilateral, i.e., the field border.
gen_contour_polygon_xld (FieldBorder, [RowUL,RowUR,RowLR,RowLL,RowUL], [ColUL,ColUR,ColLR,ColLL,ColUL])
dev_display (Image)
dev_display (FieldBorder)
disp_message (WindowHandle, ‘Fitted field borders (quadrilateral)’, ‘image’, -1, -1, ‘black’, ‘true’)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop () - Now we can determine a projective transformation that will map our extracted
- quadrilateral to a rectangle of given dimensions. Note that we have to
- add 0.5 to the coordinates to make the extracted pixel positions fit the
- coordinate system that is used by perspective_trans_image.
vector_to_proj_hom_mat2d ([RowUL,RowUR,RowLR,RowLL] + 0.5, [ColUL,ColUR,ColLR,ColLL] + 0.5, [160,160,340,340] + 0.5, [250,550,550,250] + 0.5, ‘normalized_dlt’, [], [], [], [], [], [], HomMat2D, Covariance) - Note that we could also use the following call to determine the transformation:
- hom_vector_to_proj_hom_mat2d ([RowUL,RowUR,RowLR,RowLL] + 0.5, [ColUL,ColUR,ColLR,ColLL] + 0.5, [1,1,1,1], [160,160,340,340] + 0.5, [250,550,550,250] + 0.5, [1,1,1,1], ‘normalized_dlt’, HomMat2D)
- Now we can map the image and the quadrilateral.
projective_trans_image_size (Image, TransImage, HomMat2D, ‘bilinear’, 800, 500, ‘false’)
projective_trans_contour_xld (FieldBorder, FieldBorderTrans, HomMat2D)
dev_set_window_extents (-1, -1, 800, 500)
dev_display (TransImage)
dev_display (FieldBorderTrans)
disp_message (WindowHandle, ‘Rectified track and field:’, ‘image’, 20, 10, ‘black’, ‘true’)
disp_message (WindowHandle, ‘virtual overhead view’, ‘image’, 45, 10, ‘black’, ‘true’)
侧面矫正,仿射变换
最新推荐文章于 2024-01-10 14:53:51 发布