基於Halcon12的影象拼接技術(按照Halcon例子改了一下)
阿新 • • 發佈:2019-01-22
1.原圖如下:
2.處理效果圖
3.Halcon原始碼,加了一些註釋(有些註釋翻譯的並不通順)
* 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. **本示例程式顯示了PCB的幾個影象可以如何組合到PCB的大型拼接影象中。 *該程式顯示如何使用proj_match_points_rations_transac和gen_projective_mosaic來實現這一點。 *請注意,PCB在其表面有一些降解,看起來像摺疊,並且可能容易被誤認為馬賽克影象中的影象之間的 *接縫。 為了表明情況並非如此,程式還會顯示馬賽克影象的真實接縫。 dev_update_off () dev_close_window () dev_open_window (0, 0, 500, 500, '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. **閱讀影象並逐一顯示。 請不要在PCB上執行的摺疊式降級。 gen_empty_obj (Images) iImgNum:=4 ImageFiles:='F:/專案文件/專案16-小海龜--sxl/拼接影象/' for J := 1 to iImgNum by 1 * read_image (Image, 'mosaic/pcb_' + J$'02') read_image (Image, 'F:/專案文件/專案16-小海龜--sxl/拼接影象/5_'+J+'.bmp') concat_obj (Images, Image, Images) dev_display (Image) disp_message (WindowHandle, 'Image ' + J$'d', 'image', -1, -1, 'black', 'true') wait_seconds (1) endfor disp_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, 1000/3 ,4600/3 ) tile_images_offset (Images, TiledImage, [0,1000,2000,3000], [0,0,0,0], [-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], 1000,4600) dev_clear_window () dev_display (TiledImage) disp_message (WindowHandle, 'All 4 images', 'window', 12, 12, 'black', 'true') disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 1000 / 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. **現在我們計算五對影象之間的點匹配,並且通過這些影象對之間的投影變換。 請注意, *下面的程式碼呼叫每個影象對的點運算子。由於影象形成一個條帶,有一點小書保留,我們 *可以通過儲存最後一次迭代中的點(J對中的ImageT與J + 1中的ImageF相同)來使該過 *程更有效。 這不是在這裡做的,因為在一般情況下,這樣的優化將是相當麻煩的,其中 *影象可以位於不能由條帶表示的一般配置中。 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] To := [2,3,4] 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.*提取兩個影象中的點。 * 引數2:用於計算梯度的平滑量。 如果平滑是平均值,則忽略SigmaGrad。 * 引數3:用於梯度積分的平滑量。 * 引數4:在優化功能中使用的平滑量。 * 引數5:不均勻影象區域的分割閾值。 * 引數6:點區域的分割閾值。 * 引數7:平滑法。 * 引數8:消除多重檢測點。 * 引數9,10:檢測到的連線點的行、列座標。 * 引數11,12:檢測結點的協方差矩陣的行、列部分。 * 引數13,14:檢測到的區域點的行、列座標。 * 引數15,16:檢測區域的協方差矩陣的行、列部分點。 * 引數17:檢測區域的協方差矩陣的混合部分點。6 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. *引數3、4:影象1中特徵點的行、列座標。 *引數5、6:影象2中特徵點的行、列座標。 *引數7:灰度值比較指標。 *引數8:灰度值掩碼的大小。 *引數9、10:平均行、列座標移位。 *引數11、12:匹配搜尋視窗的一半高、寬度。 *引數13:旋轉角度範圍 *引數14:灰度值匹配的閾值。 *引數15:變換矩陣估計演算法。 *引數16:變換一致性檢查閾值。 *引數17:尋找隨機數發生器。 *引數18:均勻投影變換矩陣。 *引數19:影象1中匹配輸入點的指標。 *引數20:影象2中匹配輸入點的指標。 *通過查詢點之間的對應關係,計算兩個影象之間的投影變換矩陣。 * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 proj_match_points_ransac (ImageF, ImageT, RowJunctionsF, ColJunctionsF, RowJunctionsT, ColJunctionsT, 'ncc', 21, 0, 0, 1000, 1000, 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. *生成表示平鋪影象中提取點的十字。 請注意,我們必須考慮平鋪影象中的影象的行偏移量。 *引數1:生成XLD輪廓。 *引數2,3:輸入點的行、列座標 *引數4:橫槓的長度。 *引數5:取向的十字架。 gen_cross_contour_xld (PointsF, RowJunctionsF + (F - 1) * 1000, ColJunctionsF, 6, rad(45)) gen_cross_contour_xld (PointsT, RowJunctionsT + (T - 1) * 1000, 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. *生成匹配點對的表示為行。 我們從行中建立XLD輪廓, *以便我們可以放大圖形視窗,以便仔細觀察匹配。 *t := subset(t,i) 選取陣列t中的第i個元素 RowF := subset(RowJunctionsF,Points1) + (F - 1) * 1000 ColF := subset(ColJunctionsF,Points1) RowT := subset(RowJunctionsT,Points2) + (T - 1) * 1000 ColT := subset(ColJunctionsT,Points2) gen_empty_obj (Matches) for K := 0 to |RowF| - 1 by 1 *從多邊形(給定為元組)生成XLD輪廓。 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', 12000 / 4 - 50, 12, 'black', 'true') stop () * Finally, we can generate the mosaic image from the projective transformations. *最後,我們可以從投影變換生成馬賽克影象。 *引數3:中央輸入影象的索引。 *引數4:轉換的源影象的索引。 *引數5:轉換的目標影象的索引。 *引數6:3x3射影變換矩陣的陣列。 *引數7:將影象疊加在馬賽克上。 *引數8:輸入影象的域是否也應該被轉換? *引數9:由3x3投影變換矩陣構成的陣列,它決定了圖象在鑲嵌中的位置。 *將多個影象合併成一個鑲嵌影象。 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 iImgNum by 1 concat_obj (ImagesBorder, ImageBorder, ImagesBorder) endfor gen_projective_mosaic (ImagesBorder, MosaicImageBorder, 2, From, To, ProjMatrices, 'default', 'false', MosaicMatrices2D) threshold (MosaicImageBorder, Seams, 128, 255) dev_clear_window () dev_display (MosaicImage)//Seams接縫 disp_message (WindowHandle, '各影象間的接縫', 'window', 12, 12, 'black', 'true') dev_set_color ('yellow') dev_display (Seams) disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 550, 12, 'black', 'true') dump_window (WindowHandle, 'bmp', ImageFiles+'拼接縫截圖') 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。 *引數1:用於校準的不同影象的數量。 *引數2:參考影象的索引。 *引數3:轉換的源影象的索引。 *引數4:轉換的目標影象的索引。 *引數5:3x3射影變換矩陣的陣列。 *引數6:在相應的源影象中對應點的行座標。 *引數7:在各自的源影象中對應點的列座標。 *引數8:在各自的目標影象中對應點的行座標。 *引數9:在各自的目標影象中對應的點的列座標。 *引數4:在各自的影象對中對應的點的數量。 *引數5:要使用的轉換類。 *引數6:由3個投影變換矩陣構成的陣列,它們決定了影象在鑲嵌中的位置。 *引數7:由bundle調整所重建的點的行座標。 *引數8:由bundle調整重建的點的列座標。 *引數9:每個重建點的平均誤差。 *對影象馬賽克進行捆綁調整。 bundle_adjust_mosaic (iImgNum, 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, '精確拼接圖', 'window', 12, 12, 'black', 'true') dump_window (WindowHandle, 'bmp', ImageFiles+'精確拼接截圖')