* This example program shows how several images of a PCB can be combined * into a large mosaic image of the PCB. The program shows how to use * proj_match_points_ransac and gen_projective_mosaic to achieve this. * Please note that the PCB has some degradations on its surface, which look * like folds and may easily be mistaken as the seams between the images * in the mosaic image. To show that this is not the case, the program * also displays the true seams of the mosaic image. dev_update_off () dev_close_window () dev_open_window (0, 0, 640, 480, 'white', WindowHandle) dev_set_color ('green') set_display_font (WindowHandle, 14, 'mono', 'true', 'false') * Read in the images and show them one-by-one. Please not the fold-like * degradations running across the PCB. gen_empty_obj (Images) for J := 1 to 6 by 1 *图像路径在Halcon的examples文件夹下 read_image (Image, 'mosaic/pcb_' + J$'02') concat_obj (Images, Image, Images) dev_display (Image) disp_message (WindowHandle, 'Image ' + J$'d', 'image', -1, -1, 'black', 'true') wait_seconds (1)endfordisp_continue_message (WindowHandle, 'black', 'true')stop ()* To show the point matches that are used to compute the projective* transformation between the images, we will show all images in a large* tiled image with some space between the images so that the extents* of the images are easily visible.dev_set_window_extents (-1, -1, 640 / 4, 2980 / 4)tile_images_offset (Images, TiledImage, [0,800,1600,2400,3200,4000], [0,0,0,0,0,0], [-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1], 640, 4000)dev_clear_window ()dev_display (TiledImage)disp_message (WindowHandle, 'All 6 images', 'window', 12, 12, 'black', 'true')disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 2980 / 4 - 50, 12, 'black', 'true')stop ()* Now we compute point matches between the five pairs of images and with this* the projective transformation between the image pairs. Note that the code* below calls the point operator for each image pair. Since the images form* a strip, with a little book keeping we could make the process a little more* efficient by saving the points from the last iteration (ImageT in pair J will* be identical to ImageF in pair J+1). This is not done here because such an* optimization would be quite cumbersome in the general case where the images* can lie in a general configuration that cannot be represented by a strip.dev_clear_window ()dev_display (TiledImage)disp_message (WindowHandle, 'Point matches', 'window', 12, 3, 'black', 'true')* We define the image pairs, i.e., which image should be mapped to which image.From := [1,2,3,4,5]To := [2,3,4,5,6]Num := |From|* We need a variable to accumulate the projective transformation matrices.ProjMatrices := []* Furthermore, since we want to create a rigid mosaic below we need to* accumulate all the point correspondences and the number of matches per* image pair.Rows1 := []Cols1 := []Rows2 := []Cols2 := []NumMatches := []* Now we can determine the transformations between the five image pairs.for J := 0 to Num - 1 by 1 F := From[J] T := To[J] select_obj (Images, ImageF, F) select_obj (Images, ImageT, T) * Extract the points in both images. *特征点寻找 points_foerstner (ImageF, 1, 2, 3, 200, 0.3, 'gauss', 'false', RowJunctionsF, ColJunctionsF, CoRRJunctionsF, CoRCJunctionsF, CoCCJunctionsF, RowAreaF, ColAreaF, CoRRAreaF, CoRCAreaF, CoCCAreaF) points_foerstner (ImageT, 1, 2, 3, 200, 0.3, 'gauss', 'false', RowJunctionsT, ColJunctionsT, CoRRJunctionsT, CoRCJunctionsT, CoCCJunctionsT, RowAreaT, ColAreaT, CoRRAreaT, CoRCAreaT, CoCCAreaT) * Determine the point matches and the transformation for the current * image pair. *特征点匹配,相匹配的特征点需要足够多 proj_match_points_ransac (ImageF, ImageT, RowJunctionsF, ColJunctionsF, RowJunctionsT, ColJunctionsT, 'ncc', 21, 0, 0, 480, 640, 0, 0.5, 'gold_standard', 1, 4364537, ProjMatrix, Points1, Points2) * Accumulate the transformation matrix. ProjMatrices := [ProjMatrices,ProjMatrix] * Accumulate the point matches and number of point matches. Rows1 := [Rows1,subset(RowJunctionsF,Points1)] Cols1 := [Cols1,subset(ColJunctionsF,Points1)] Rows2 := [Rows2,subset(RowJunctionsT,Points2)] Cols2 := [Cols2,subset(ColJunctionsT,Points2)] NumMatches := [NumMatches,|Points1|] * Generate crosses that represent the extracted points in the tiled image. * Note that we have to take the row offsets of the images in the tiled image * into account. gen_cross_contour_xld (PointsF, RowJunctionsF + (F - 1) * 500, ColJunctionsF, 6, rad(45)) gen_cross_contour_xld (PointsT, RowJunctionsT + (T - 1) * 500, ColJunctionsT, 6, rad(45)) * Generate a representation of the matched point pairs as lines. We create * XLD contours from the lines so that we can zoom into the graphics window * to take a closer look at the matches. RowF := subset(RowJunctionsF,Points1) + (F - 1) * 500 ColF := subset(ColJunctionsF,Points1) RowT := subset(RowJunctionsT,Points2) + (T - 1) * 500 ColT := subset(ColJunctionsT,Points2) gen_empty_obj (Matches) for K := 0 to |RowF| - 1 by 1 gen_contour_polygon_xld (Match, [RowF[K],RowT[K]], [ColF[K],ColT[K]]) concat_obj (Matches, Match, Matches) endfor * Now display the extracted data. dev_set_color ('blue') dev_display (Matches) dev_set_color ('green') dev_display (PointsF) dev_display (PointsT) endfor disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 2980 / 4 - 50, 12, 'black', 'true') stop () * Finally, we can generate the mosaic image from the projective transformations. *拼接图像生成 gen_projective_mosaic (Images, MosaicImage, 2, From, To, ProjMatrices, 'default', 'false', MosaicMatrices2D)get_image_size (MosaicImage, Width, Height)dev_set_window_extents (-1, -1, Width / 3, Height / 3)dev_clear_window ()dev_display (MosaicImage)disp_message (WindowHandle, 'Projective mosaic', 'window', 12, 12, 'black', 'true')disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', Height / 3 - 50, 12, 'black', 'true')stop ()* To show more clearly that the folds visible in the image do not result from the* mosaicking, we display the seams between the images in the mosaic image.* This can be done most easily by creating an image that contains the border* of the images, generating a mosaic from it, and segmenting the resulting* mosaic image.get_image_size (Image, Width, Height)gen_image_const (ImageBlank, 'byte', Width, Height)gen_rectangle1 (Rectangle, 0, 0, Height - 1, Width - 1)paint_region (Rectangle, ImageBlank, ImageBorder, 255, 'margin')gen_empty_obj (ImagesBorder)for J := 1 to 6 by 1 concat_obj (ImagesBorder, ImageBorder, ImagesBorder)endforgen_projective_mosaic (ImagesBorder, MosaicImageBorder, 2, From, To, ProjMatrices, 'default', 'false', MosaicMatrices2D)threshold (MosaicImageBorder, Seams, 128, 255)dev_clear_window ()dev_display (MosaicImage)disp_message (WindowHandle, 'Seams between the\nimages', 'window', 12, 12, 'black', 'true')dev_set_color ('yellow')dev_display (Seams)disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 550, 12, 'black', 'true')stop ()* If you look very closely at the projective mosaic above, you may note that* there is a very slight projective distortion in the mosaic. This happens* because the transformations cannot be determined with perfect accuracy* because of very small errors in the point coordinates due to noise. Because* of the strip configuration, essentially the overlapping area between the image* pairs can act like a hinge around which the images may rotate out of the image* plane. In this example, we know that the mapping between the images must* be a rigid transformation. If we want to force the transformation to be rigid* we can simply use bundle_adjust_mosaic. *拼接图像几何调整 bundle_adjust_mosaic (6, 1, From, To, ProjMatrices, Rows1, Cols1, Rows2, Cols2, NumMatches, 'rigid', MosaicMatrices2D, Rows, Cols, Error) * Now, we can generate the mosaic image from the rigid transformations. gen_bundle_adjusted_mosaic (Images, MosaicImageRigid, MosaicMatrices2D, 'default', 'false', TransMatrix2D) get_image_size (MosaicImageRigid, Width, Height) dev_set_window_extents (-1, -1, Width / 3, Height / 3) dev_clear_window () dev_display (MosaicImageRigid) disp_message (WindowHandle, 'Rigid mosaic', 'window', 12, 12, 'black', 'true')
Halcon图像拼接gen_projective_mosaic例程
最新推荐文章于 2024-08-13 07:44:06 发布